Skip to content

Commit 9032bdc

Browse files
authored
Integtest input arguments changes and integration with s3 (opensearch-project#456)
* Integ tests: Logic to read arguments from pipeline, and pull artifacts from s3 Signed-off-by: Himanshu Setia <[email protected]> * isort, flake8 fixes Signed-off-by: Himanshu Setia <[email protected]> * Addressing PR comments and adding default integtest.sh file Signed-off-by: Himanshu Setia <[email protected]> * fixing ScriptFinder UTs due to change in reading order Signed-off-by: Himanshu Setia <[email protected]> * Addressing PR comments and adding more UTs Signed-off-by: Himanshu Setia <[email protected]> * PR comments Signed-off-by: Himanshu Setia <[email protected]>
1 parent 9a5843f commit 9032bdc

File tree

13 files changed

+267
-29
lines changed

13 files changed

+267
-29
lines changed

bundle-workflow/README.md

+14
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ The following options are available.
121121

122122
This step runs integration tests invoking `integtest.sh` in each component from bundle manifest.
123123

124+
To run integration tests locally, use below command. It pulls down the built bundle and its manifest file from S3, reads all components of the bundle and runs integration tests against each component.
125+
126+
```
127+
export AWS_ROLE_ARN=arn:aws:iam::<AWS_JENKINS_ACCOUNT>:role/opensearch-test
128+
export AWS_ROLE_SESSION_NAME=dummy-session
129+
130+
Next, configure temporary credentials in environment w/
131+
export AWS_SESSION_TOKEN=<value>
132+
export AWS_ACCESS_KEY_ID=<value>
133+
export AWS_SECRET_ACCESS_KEY=<value>
134+
135+
cd bundle-workflow
136+
./test.sh integ-test --test-run-id <execution-id> --s3-bucket <bucket_name> --opensearch-version <version> --build-id <id> --architecture <arch>
137+
```
124138
#### Backwards Compatibility Tests
125139

126140
This step run backward compatibility invoking `bwctest.sh` in each component from bundle manifest.

bundle-workflow/scripts/default/integtest.sh

100644100755
+88-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,89 @@
11
#!/bin/bash
2-
echo "WARNING: Dummy integtest.sh script invoked: $@"
2+
3+
set -e
4+
5+
function usage() {
6+
echo ""
7+
echo "This script is used to run integration tests for plugin installed on a remote OpenSearch/Dashboards cluster."
8+
echo "--------------------------------------------------------------------------"
9+
echo "Usage: $0 [args]"
10+
echo ""
11+
echo "Required arguments:"
12+
echo "None"
13+
echo ""
14+
echo "Optional arguments:"
15+
echo -e "-b BIND_ADDRESS\t, defaults to localhost | 127.0.0.1, can be changed to any IP or domain name for the cluster location."
16+
echo -e "-p BIND_PORT\t, defaults to 9200 or 5601 depends on OpenSearch or Dashboards, can be changed to any port for the cluster location."
17+
echo -e "-s SECURITY_ENABLED\t(true | false), defaults to true. Specify the OpenSearch/Dashboards have security enabled or not."
18+
echo -e "-c CREDENTIAL\t(usename:password), no defaults, effective when SECURITY_ENABLED=true."
19+
echo -e "-v OPENSEARCH_VERSION\t, no defaults"
20+
echo -e "-n SNAPSHOT\t, defaults to false"
21+
echo -e "-h\tPrint this message."
22+
echo "--------------------------------------------------------------------------"
23+
}
24+
25+
while getopts ":hb:p:s:c:v:n" arg; do
26+
case $arg in
27+
h)
28+
usage
29+
exit 1
30+
;;
31+
b)
32+
BIND_ADDRESS=$OPTARG
33+
;;
34+
p)
35+
BIND_PORT=$OPTARG
36+
;;
37+
s)
38+
SECURITY_ENABLED=$OPTARG
39+
;;
40+
c)
41+
CREDENTIAL=$OPTARG
42+
;;
43+
v)
44+
OPENSEARCH_VERSION=$OPTARG
45+
;;
46+
n)
47+
SNAPSHOT=$OPTARG
48+
;;
49+
:)
50+
echo "-${OPTARG} requires an argument"
51+
usage
52+
exit 1
53+
;;
54+
?)
55+
echo "Invalid option: -${OPTARG}"
56+
exit 1
57+
;;
58+
esac
59+
done
60+
61+
62+
if [ -z "$BIND_ADDRESS" ]
63+
then
64+
BIND_ADDRESS="localhost"
65+
fi
66+
67+
if [ -z "$BIND_PORT" ]
68+
then
69+
BIND_PORT="9200"
70+
fi
71+
72+
if [ -z "$SECURITY_ENABLED" ]
73+
then
74+
SECURITY_ENABLED="true"
75+
fi
76+
77+
if [ -z "$SNAPSHOT" ]
78+
then
79+
SNAPSHOT="false"
80+
fi
81+
82+
if [ -z "$CREDENTIAL" ]
83+
then
84+
CREDENTIAL="admin:admin"
85+
USERNAME=`echo $CREDENTIAL | awk -F ':' '{print $1}'`
86+
PASSWORD=`echo $CREDENTIAL | awk -F ':' '{print $2}'`
87+
fi
88+
89+
./gradlew integTest -Dopensearch.version=$OPENSEARCH_VERSION -Dbuild.snapshot=$SNAPSHOT -Dtests.rest.cluster="$BIND_ADDRESS:$BIND_PORT" -Dtests.cluster="$BIND_ADDRESS:$BIND_PORT" -Dtests.clustername="opensearch-integrationtest" -Dhttps=$SECURITY_ENABLED -Duser=$USERNAME -Dpassword=$PASSWORD --console=plain

bundle-workflow/src/manifests/build_manifest.py

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# this file be licensed under the Apache-2.0 license or a
55
# compatible open source license.
66

7+
import os
8+
9+
from aws.s3_bucket import S3Bucket
710
from manifests.manifest import Manifest
811

912
"""
@@ -54,6 +57,20 @@ def __to_dict__(self):
5457
),
5558
}
5659

60+
@staticmethod
61+
def get_build_manifest_relative_location(build_id, opensearch_version, architecture):
62+
return f"builds/{opensearch_version}/{build_id}/{architecture}/manifest.yml"
63+
64+
@staticmethod
65+
def from_s3(bucket_name, build_id, opensearch_version, architecture, work_dir=None):
66+
work_dir = work_dir if not None else str(os.getcwd())
67+
manifest_s3_path = BuildManifest.get_build_manifest_relative_location(build_id, opensearch_version, architecture)
68+
S3Bucket(bucket_name).download_file(manifest_s3_path, work_dir)
69+
with open('manifest.yml', 'r') as file:
70+
build_manifest = BuildManifest.from_file(file)
71+
os.remove(os.path.realpath(os.path.join(work_dir, 'manifest.yml')))
72+
return build_manifest
73+
5774
class Build:
5875
def __init__(self, data):
5976
self.name = data["name"]

bundle-workflow/src/manifests/bundle_manifest.py

+25
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
# this file be licensed under the Apache-2.0 license or a
55
# compatible open source license.
66

7+
import os
8+
9+
from aws.s3_bucket import S3Bucket
710
from manifests.manifest import Manifest
811

912

@@ -45,6 +48,28 @@ def __to_dict__(self):
4548
),
4649
}
4750

51+
@staticmethod
52+
def from_s3(bucket_name, build_id, opensearch_version, architecture, work_dir=None):
53+
work_dir = work_dir if not None else str(os.getcwd())
54+
manifest_s3_path = BundleManifest.get_bundle_manifest_relative_location(build_id, opensearch_version, architecture)
55+
S3Bucket(bucket_name).download_file(manifest_s3_path, work_dir)
56+
with open('manifest.yml', 'r') as file:
57+
bundle_manifest = BundleManifest.from_file(file)
58+
os.remove(os.path.realpath(os.path.join(work_dir, 'manifest.yml')))
59+
return bundle_manifest
60+
61+
@staticmethod
62+
def get_tarball_relative_location(build_id, opensearch_version, architecture):
63+
return f"bundles/{opensearch_version}/{build_id}/{architecture}/opensearch-{opensearch_version}-linux-{architecture}.tar.gz"
64+
65+
@staticmethod
66+
def get_tarball_name(opensearch_version, architecture):
67+
return f"opensearch-{opensearch_version}-linux-{architecture}.tar.gz"
68+
69+
@staticmethod
70+
def get_bundle_manifest_relative_location(build_id, opensearch_version, architecture):
71+
return f"bundles/{opensearch_version}/{build_id}/{architecture}/manifest.yml"
72+
4873
class Build:
4974
def __init__(self, data):
5075
self.name = data["name"]

bundle-workflow/src/manifests/test_manifest.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
# this file be licensed under the Apache-2.0 license or a
55
# compatible open source license.
66

7-
import yaml
7+
from manifests.manifest import Manifest
88

99

10-
class TestManifest:
10+
class TestManifest(Manifest):
1111
"""
1212
TestManifest contains the test support matrix for any component.
1313
@@ -29,15 +29,8 @@ class TestManifest:
2929
- with-security
3030
- without-security
3131
"""
32-
33-
@staticmethod
34-
def from_file(file):
35-
return TestManifest(yaml.safe_load(file))
36-
3732
def __init__(self, data):
38-
self.version = str(data["schema-version"])
39-
if self.version != "1.0":
40-
raise ValueError(f"Unsupported schema version: {self.version}")
33+
super().__init__(data)
4134
self.components = list(
4235
map(lambda entry: self.Component(entry), data["components"])
4336
)

bundle-workflow/src/run_integ_test.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@
2929
def parse_arguments():
3030
parser = argparse.ArgumentParser(description="Test an OpenSearch Bundle")
3131
parser.add_argument(
32-
"--bundle-manifest", type=argparse.FileType("r"), help="Bundle Manifest file."
32+
"--s3-bucket", type=str, help="S3 bucket name"
3333
)
3434
parser.add_argument(
35-
"--build-manifest", type=argparse.FileType("r"), help="Build Manifest file."
35+
"--opensearch-version", type=str, help="OpenSearch version to test"
3636
)
3737
parser.add_argument(
38-
"--test-manifest", type=argparse.FileType("r"), help="Test Manifest file."
38+
"--build-id", type=str, help="The build id for the built artifact"
39+
)
40+
parser.add_argument(
41+
"--architecture", type=str, help="The os architecture e.g. x64, arm64"
42+
)
43+
parser.add_argument(
44+
"--test-run-id", type=str, help="The unique execution id for the test"
3945
)
4046
parser.add_argument(
4147
"--keep",
@@ -101,16 +107,19 @@ def sync_dependencies_to_maven_local(work_dir, manifest_build_ver):
101107
def main():
102108
args = parse_arguments()
103109
console.configure(level=args.logging_level)
104-
bundle_manifest = BundleManifest.from_file(args.bundle_manifest)
105-
build_manifest = BuildManifest.from_file(args.build_manifest)
106-
test_manifest = TestManifest.from_file(args.test_manifest)
110+
test_manifest_path = os.path.join(os.path.dirname(__file__), 'test_workflow/config/test_manifest.yml')
111+
test_manifest = TestManifest.from_path(test_manifest_path)
107112
integ_test_config = dict()
108113
for component in test_manifest.components:
109114
if component.integ_test is not None:
110115
integ_test_config[component.name] = component
111116
with TemporaryDirectory(keep=args.keep) as work_dir:
112117
logging.info("Switching to temporary work_dir: " + work_dir)
113118
os.chdir(work_dir)
119+
bundle_manifest = BundleManifest.from_s3(
120+
args.s3_bucket, args.build_id, args.opensearch_version, args.architecture, work_dir)
121+
build_manifest = BuildManifest.from_s3(
122+
args.s3_bucket, args.build_id, args.opensearch_version, args.architecture, work_dir)
114123
pull_common_dependencies(work_dir, build_manifest)
115124
sync_dependencies_to_maven_local(work_dir, build_manifest.build.version)
116125
for component in bundle_manifest.components:
@@ -120,6 +129,7 @@ def main():
120129
integ_test_config[component.name],
121130
bundle_manifest,
122131
work_dir,
132+
args.s3_bucket
123133
)
124134
test_suite.execute()
125135
else:

bundle-workflow/src/test_workflow/config/test_manifest.yml

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ components:
77
test-configs:
88
- with-security
99
- without-security
10-
- with-less-security
1110
bwc-test:
1211
dependencies:
1312
test-configs:

bundle-workflow/src/test_workflow/integ_test/integ_test_suite.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ class IntegTestSuite:
2020
test_support_matrix.yml
2121
"""
2222

23-
def __init__(self, component, test_config, bundle_manifest, work_dir):
23+
def __init__(self, component, test_config, bundle_manifest, work_dir, s3_bucket_name):
2424
self.component = component
2525
self.bundle_manifest = bundle_manifest
2626
self.work_dir = work_dir
2727
self.test_config = test_config
28+
self.s3_bucket_name = s3_bucket_name
2829
self.script_finder = ScriptFinder()
2930
self.repo = GitRepository(
3031
self.component.repository,
@@ -74,7 +75,7 @@ def _is_security_enabled(self, config):
7475

7576
def _setup_cluster_and_execute_test_config(self, config):
7677
security = self._is_security_enabled(config)
77-
with LocalTestCluster.create(self.work_dir, self.bundle_manifest, security) as (test_cluster_endpoint, test_cluster_port):
78+
with LocalTestCluster.create(self.work_dir, self.bundle_manifest, security, self.s3_bucket_name) as (test_cluster_endpoint, test_cluster_port):
7879
logging.info("component name: " + self.component.name)
7980
os.chdir(self.work_dir)
8081
# TODO: (Create issue) Since plugins don't have integtest.sh in version branch, hardcoded it to main
@@ -85,7 +86,7 @@ def _execute_integtest_sh(self, endpoint, port, security):
8586
self.component.name, self.repo.dir
8687
)
8788
if os.path.exists(script):
88-
cmd = f"sh {script} -b {endpoint} -p {port} -s {str(security).lower()}"
89+
cmd = f"{script} -b {endpoint} -p {port} -s {str(security).lower()} -v {self.bundle_manifest.build.version}"
8990
(status, stdout, stderr) = execute(cmd, self.repo.dir, True, False)
9091
else:
9192
logging.info(

bundle-workflow/src/test_workflow/integ_test/local_test_cluster.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
import os
99
import subprocess
1010
import time
11-
import urllib.request
1211

1312
import requests
1413

14+
from aws.s3_bucket import S3Bucket
15+
from manifests.bundle_manifest import BundleManifest
1516
from test_workflow.test_cluster import ClusterCreationException, TestCluster
1617

1718

@@ -20,11 +21,12 @@ class LocalTestCluster(TestCluster):
2021
Represents an on-box test cluster. This class downloads a bundle (from a BundleManifest) and runs it as a background process.
2122
"""
2223

23-
def __init__(self, work_dir, bundle_manifest, security_enabled):
24+
def __init__(self, work_dir, bundle_manifest, security_enabled, s3_bucket_name):
2425
self.manifest = bundle_manifest
2526
self.work_dir = os.path.join(work_dir, "local-test-cluster")
2627
os.makedirs(self.work_dir, exist_ok=True)
2728
self.security_enabled = security_enabled
29+
self.bucket_name = s3_bucket_name
2830
self.process = None
2931

3032
def create_cluster(self):
@@ -59,15 +61,20 @@ def destroy(self):
5961
def url(self, path=""):
6062
return f'{"https" if self.security_enabled else "http"}://{self.endpoint()}:{self.port()}{path}'
6163

64+
def __download_tarball_from_s3(self):
65+
s3_path = BundleManifest.get_tarball_relative_location(
66+
self.manifest.build.id, self.manifest.build.version, self.manifest.build.architecture)
67+
S3Bucket(self.bucket_name).download_file(s3_path, self.work_dir)
68+
return BundleManifest.get_tarball_name(self.manifest.build.version, self.manifest.build.architecture)
69+
6270
def download(self):
6371
logging.info(f"Creating local test cluster in {self.work_dir}")
6472
os.chdir(self.work_dir)
65-
logging.info(f"Downloading bundle from {self.manifest.build.location}")
66-
urllib.request.urlretrieve(self.manifest.build.location, "bundle.tgz")
67-
logging.info(f'Downloaded bundle to {os.path.realpath("bundle.tgz")}')
68-
73+
logging.info("Downloading bundle from s3")
74+
bundle_name = self.__download_tarball_from_s3()
75+
logging.info(f'Downloaded bundle to {os.path.realpath(bundle_name)}')
6976
logging.info("Unpacking")
70-
subprocess.check_call("tar -xzf bundle.tgz", shell=True)
77+
subprocess.check_call(f"tar -xzf {bundle_name}", shell=True)
7178
logging.info("Unpacked")
7279

7380
def disable_security(self, dir):

bundle-workflow/src/test_workflow/utils/__init__.py

Whitespace-only changes.

bundle-workflow/test.sh

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,13 @@
99
set -e
1010

1111
DIR="$(dirname "$0")"
12-
"$DIR/run.sh" "$DIR/src/test.py" $@
12+
case $1 in
13+
"integ-test")
14+
echo "${@:2}"
15+
"$DIR/run.sh" "$DIR/src/run_integ_test.py" "${@:2}"
16+
;;
17+
*)
18+
echo "Invalid Test suite"
19+
;;
20+
esac
21+

0 commit comments

Comments
 (0)