diff --git a/scripts/modules/aux_services.py b/scripts/modules/aux_services.py index 0e300d469..8319d40ff 100644 --- a/scripts/modules/aux_services.py +++ b/scripts/modules/aux_services.py @@ -15,6 +15,8 @@ def build_candidate_manifest(self): image = self.docker_name if self.oss: image += "-oss" + if self.ubi8: + image += "-ubi8" key = "{image}-{version}-docker-image.tar.gz".format( image=image, version=version, diff --git a/scripts/modules/beats.py b/scripts/modules/beats.py index 8a984ee28..9ac34215a 100644 --- a/scripts/modules/beats.py +++ b/scripts/modules/beats.py @@ -95,6 +95,8 @@ def build_candidate_manifest(self): image = self.docker_name if self.oss: image += "-oss" + if self.ubi8: + image += "-ubi8" key = "{image}-{version}-docker-image.tar.gz".format( image=image, diff --git a/scripts/modules/cli.py b/scripts/modules/cli.py index 05e0d828f..87a328d9a 100644 --- a/scripts/modules/cli.py +++ b/scripts/modules/cli.py @@ -169,6 +169,8 @@ def __init__(self, argv=None, services=None): self.args = parser.parse_args(argv) + self.validate_options(self.args, parser) + # py3 if not hasattr(self.args, "func"): parser.error("command required") @@ -340,6 +342,14 @@ def init_start_parser(self, parser, services, argv=None): default=False, ) + parser.add_argument( + '--ubi8', + action='store_true', + help='use ubi8 container images', + dest='ubi8', + default=False, + ) + parser.add_argument( "--apm-server-url", action="store", @@ -488,6 +498,13 @@ def store_options(self, parser): for choice, subparser in subparsers_action.choices.items(): self.available_options.add(choice) + def validate_options(self, args, parser): + """ + Helper method to validate if certain options are compatible or not. + """ + if hasattr(self.args, "oss") and hasattr(self.args, "ubi8") and args.oss and args.ubi8: + parser.error("oss and ubi8 options are incompatible. Choose one of them instead.") + # # handlers # diff --git a/scripts/modules/elastic_stack.py b/scripts/modules/elastic_stack.py index 66014ccff..5a079d044 100644 --- a/scripts/modules/elastic_stack.py +++ b/scripts/modules/elastic_stack.py @@ -425,6 +425,8 @@ def build_candidate_manifest(self): image = self.docker_name if self.oss: image += "-oss" + if self.ubi8: + image += "-ubi8" key = "{image}-{version}-docker-image.tar.gz".format( image=image, diff --git a/scripts/modules/service.py b/scripts/modules/service.py index c2a7130cc..3f9f7f24a 100644 --- a/scripts/modules/service.py +++ b/scripts/modules/service.py @@ -38,6 +38,7 @@ def __init__(self, **options): self._oss = options.get(self.option_name() + "_oss") or options.get("oss") self._release = options.get(self.option_name() + "_release") or options.get("release") self._snapshot = options.get(self.option_name() + "_snapshot") or options.get("snapshot") + self._ubi8 = options.get(self.option_name() + "_ubi8") or options.get("ubi8") # version is service specific or stack or default self._version = options.get(self.option_name() + "_version") or options.get("version", DEFAULT_STACK_VERSION) @@ -69,6 +70,8 @@ def default_image(self, version_override=None): image = "/".join((self.docker_registry, self.docker_path, self.docker_name)) if self.oss: image += "-oss" + if self.ubi8: + image += "-ubi8" image += ":" + (version_override or self.version) # no command line option for setting snapshot, snapshot == no bc and not release if self.snapshot or not (any((self.bc, self.release))): @@ -107,6 +110,10 @@ def option_name(cls): def oss(self): return self._oss + @property + def ubi8(self): + return self._ubi8 + @staticmethod def publish_port(external, internal=None, expose=False): addr = "" if expose else "127.0.0.1:" @@ -175,6 +182,8 @@ def build_candidate_manifest(self): image = self.docker_name if self.oss: image += "-oss" + if self.ubi8: + image += "-ubi8" key = "{image}-{version}-docker-image.tar.gz".format( image=image, version=version, @@ -205,7 +214,7 @@ def add_arguments(cls, parser): dest=cls.option_name() + "_" + image_detail_key, help="stack {} override".format(image_detail_key), ) - for image_detail_key in ("oss", "release", "snapshot"): + for image_detail_key in ("oss", "release", "snapshot", "ubi8"): parser.add_argument( "--" + cls.name() + "-" + image_detail_key, action="store_true", diff --git a/scripts/tests/localsetup_tests.py b/scripts/tests/localsetup_tests.py index d0a7fba7d..3bc3b755d 100644 --- a/scripts/tests/localsetup_tests.py +++ b/scripts/tests/localsetup_tests.py @@ -1366,6 +1366,62 @@ def test_start_bc_with_release(self, mock_load_images, mock_resolve_bc): }, image_cache_dir) + @mock.patch(service.__name__ + ".resolve_bc") + @mock.patch(cli.__name__ + ".load_images") + def test_start_bc_ubi8(self, mock_load_images, mock_resolve_bc): + mock_resolve_bc.return_value = { + "projects": { + "elasticsearch": { + "packages": { + "elasticsearch-ubi8-7.10.0-docker-image.tar.gz": { + "url": "https://staging.elastic.co/.../elasticsearch-ubi8-7.10.0-docker-image.tar.gz", + "type": "docker" + }, + }, + }, + "kibana": { + "packages": { + "kibana-ubi8-7.10.0-docker-image.tar.gz": { + "url": "https://staging.elastic.co/.../kibana-ubi8-7.10.0-docker-image.tar.gz", + "type": "docker" + }, + }, + }, + "apm-server": { + "packages": { + "apm-server-ubi8-7.10.0-docker-image.tar.gz": { + "url": "https://staging.elastic.co/.../apm-server-ubi8-7.10.0-docker-image.tar.gz", + "type": "docker" + }, + }, + }, + }, + } + docker_compose_yml = stringIO() + image_cache_dir = "/foo" + version = "7.10.0" + bc = "abcd1234" + self.assertNotIn(version, LocalSetup.SUPPORTED_VERSIONS) + setup = LocalSetup(argv=self.common_setup_args + [ + version, "--ubi8", "--bc", bc, "--image-cache-dir", image_cache_dir]) + setup.set_docker_compose_path(docker_compose_yml) + setup() + docker_compose_yml.seek(0) + got = yaml.load(docker_compose_yml) + services = got["services"] + self.assertEqual( + "docker.elastic.co/elasticsearch/elasticsearch-ubi8:{}".format(version), + services["elasticsearch"]["image"] + ) + self.assertEqual("docker.elastic.co/kibana/kibana-ubi8:{}".format(version), services["kibana"]["image"]) + mock_load_images.assert_called_once_with( + { + "https://staging.elastic.co/.../elasticsearch-ubi8-7.10.0-docker-image.tar.gz", + "https://staging.elastic.co/.../kibana-ubi8-7.10.0-docker-image.tar.gz", + "https://staging.elastic.co/.../apm-server-ubi8-7.10.0-docker-image.tar.gz", + }, + image_cache_dir) + @mock.patch(service.__name__ + ".resolve_bc") def test_docker_download_image_url(self, mock_resolve_bc): mock_resolve_bc.return_value = { diff --git a/scripts/tests/service_tests.py b/scripts/tests/service_tests.py index 681afe521..9f32cec31 100644 --- a/scripts/tests/service_tests.py +++ b/scripts/tests/service_tests.py @@ -440,6 +440,12 @@ def test_oss_release(self): apm_server["image"], "docker.elastic.co/apm/apm-server-oss:6.3.100" ) + def test_ubi8_snapshot(self): + apm_server = ApmServer(version="8.0.0", ubi8=True, snapshot=True).render()["apm-server"] + self.assertEqual( + apm_server["image"], "docker.elastic.co/apm/apm-server-ubi8:8.0.0-SNAPSHOT" + ) + def test_api_key_auth(self): apm_server = ApmServer(version="7.6.100", apm_server_api_key_auth=True).render()["apm-server"] self.assertIn("apm-server.api_key.enabled=true", apm_server["command"]) @@ -721,6 +727,16 @@ def test_apm_server_build_oss(self): 'apm_server_repo': 'foo.git'}, 'context': 'docker/apm-server'}) + def test_apm_server_build_ubi8(self): + apm_server = ApmServer(version="7.9.2", apm_server_build="foo.git", release=True, ubi8=True).render()["apm-server"] + self.assertIsNone(apm_server.get("image")) + self.assertDictEqual(apm_server["build"], { + 'args': {'apm_server_base_image': 'docker.elastic.co/apm/apm-server-ubi8:7.9.2', + 'apm_server_binary': 'apm-server', + 'apm_server_branch_or_commit': 'master', + 'apm_server_repo': 'foo.git'}, + 'context': 'docker/apm-server'}) + def test_apm_server_count(self): render = ApmServer(version="6.4.100", apm_server_count=2).render() apm_server_lb = render["apm-server"] @@ -839,6 +855,16 @@ def test_6_2_oss_release(self): "xpack.security.enabled set while oss" ) + def test_7_10_ubi8_release(self): + elasticsearch = Elasticsearch(version="7.10.0", ubi8=True, release=True).render()["elasticsearch"] + self.assertEqual( + elasticsearch["image"], "docker.elastic.co/elasticsearch/elasticsearch-ubi8:7.10.0" + ) + self.assertTrue( + any(e.startswith("xpack.security.enabled=") for e in elasticsearch["environment"]), + "xpack.security.enabled set while oss" + ) + def test_6_3_snapshot(self): elasticsearch = Elasticsearch(version="6.3.100", snapshot=True).render()["elasticsearch"] self.assertEqual( @@ -1091,6 +1117,10 @@ def test_kibana_snapshot(self): kibana = Kibana(version="7.3.0", kibana_snapshot=True, kibana_version="7.3.0").render()["kibana"] self.assertEqual("docker.elastic.co/kibana/kibana:7.3.0-SNAPSHOT", kibana["image"]) + def test_kibana_ubi8(self): + kibana = Kibana(version="7.10.0", release=True, kibana_ubi8=True, kibana_version="7.10.0").render()["kibana"] + self.assertEqual("docker.elastic.co/kibana/kibana-ubi8:7.10.0", kibana["image"]) + def test_kibana_login_assistance_message(self): kibana = Kibana(version="7.6.0", xpack_secure=True, kibana_version="7.6.0").render()["kibana"] self.assertIn("Login details: `admin/changeme`.", kibana['environment']["XPACK_SECURITY_LOGINASSISTANCEMESSAGE"]) @@ -1181,6 +1211,9 @@ def test_logstash_elasticsearch_urls(self): self.assertTrue("elasticsearch" in logstash['depends_on']) self.assertEqual("elasticsearch01:9200,elasticsearch02:9200", logstash['environment']["ELASTICSEARCH_URL"]) + def test_logstash_ubi8(self): + logstash = Logstash(version="7.10.0", release=True, ubi8=True).render()["logstash"] + self.assertEqual("docker.elastic.co/logstash/logstash-ubi8:7.10.0", logstash['image']) class MetricbeatServiceTest(ServiceTest): def test_metricbeat(self): diff --git a/tests/versions/apm_server.yml b/tests/versions/apm_server.yml index c5c36eced..4df1d03e3 100644 --- a/tests/versions/apm_server.yml +++ b/tests/versions/apm_server.yml @@ -1,3 +1,4 @@ APM_SERVER: - master - master --oss + - master --ubi8