From 12c76885145a3d9660615c17b16db8353e1daadc Mon Sep 17 00:00:00 2001 From: Maggie Neterval Date: Mon, 11 May 2020 14:34:17 -0400 Subject: [PATCH] refactor(deploy): Make kubectl deployer the only option for a distributed installation on Kubernetes (#1672) * refactor(deploy): remove clouddriver-kubernetes dependency from KubernetesService KubernetesService currently calls out to clouddriver-kubernetes-v1 to assemble an image registry, repository, and tag into a KubernetesImageDescription object, and then assemble those components into a Docker image ID. Since clouddriver-kubernetes-v1 will not be included in the next Clouddriver release, let's instead include the relevant string formatting logic inline. * refactor(kubernetes): remove Kubernetes V1 account kubeconfig validation The legacy Kubernetes (V1) provider is deprecated, and will not be included in Spinnaker 1.21. Given that no new legacy accounts should be added, let's remove the V1-specific kube config validation that we never applied to V2 accounts anyway. This will unblock us from completely decoupling Halyard's distributed installation and Clouddriver's Kubernetes provider. This commit also updates my TODO to remove the remaining V1 validation logic when no supported Spinnaker release includes the V1 provider (tracking this work in this [GitHub issue](https://github.com/spinnaker/spinnaker/issues/5749)). * refactor(deploy): Make kubectl deployer the only option for a distributed installation on Kubernetes Spinnaker 1.21 will not include support for using legacy (V1) accounts to deploy to Kubernetes. The next release of Halyard will not include support for using a legacy (V1) account to deploy Spinnaker itself using Halyard. It should be relatively straightforward for users to migrate from the V1 deployer to the kubectl deployer, and can be done independently of migrating any pipelines or other Spinnaker accounts to the V2 provider. Given that we don't publish a Halyard changelog, I will be sure to communicate this in the #halyard Slack channel when we do the next Halyard release. * refactor(deps): remove dependency on clouddriver-kubernetes The previous commits removed all clients of clouddriver-kubernetes and clouddriver-kubernetes-v1. Moving forward, this will prevent the class of bug where contributors do not realize that breaking changes to Clouddriver could impact Halyard (at least in the Kubernetes provider). --- halyard-config/halyard-config.gradle | 1 - .../KubernetesAccountValidator.java | 126 +-- halyard-deploy/halyard-deploy.gradle | 2 - .../deployment/v1/ServiceProviderFactory.java | 15 +- .../deploy/services/v1/DeployService.java | 15 +- .../kubernetes/KubernetesService.java | 16 +- ...bernetesV1ClouddriverBootstrapService.java | 67 -- .../v1/KubernetesV1ClouddriverService.java | 74 -- .../v1/KubernetesV1DeckService.java | 89 -- ...netesV1DistributedLogCollectorFactory.java | 87 -- .../v1/KubernetesV1DistributedService.java | 878 ------------------ ...ubernetesV1DistributedServiceDelegate.java | 47 - ...ubernetesV1DistributedServiceProvider.java | 79 -- .../v1/KubernetesV1EchoService.java | 60 -- .../v1/KubernetesV1FiatService.java | 60 -- .../v1/KubernetesV1Front50Service.java | 74 -- .../v1/KubernetesV1GateService.java | 58 -- .../v1/KubernetesV1IgorService.java | 60 -- .../v1/KubernetesV1KayentaService.java | 72 -- .../KubernetesV1MonitoringDaemonService.java | 49 - .../v1/KubernetesV1OrcaBootstrapService.java | 67 -- .../v1/KubernetesV1OrcaService.java | 61 -- .../v1/KubernetesV1ProviderUtils.java | 356 ------- .../v1/KubernetesV1RedisBootstrapService.java | 66 -- .../v1/KubernetesV1RedisService.java | 105 --- .../v1/KubernetesV1RoscoService.java | 61 -- .../kubernetes/v1/ResourceBuilder.java | 180 ---- .../KubernetesV1DistributedServiceSpec.groovy | 303 ------ .../kubernetes/ResourceBuilderSpec.groovy | 77 -- 29 files changed, 20 insertions(+), 3185 deletions(-) delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverBootstrapService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DeckService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedLogCollectorFactory.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceDelegate.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceProvider.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1EchoService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1FiatService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1Front50Service.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1GateService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1IgorService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1KayentaService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1MonitoringDaemonService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaBootstrapService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ProviderUtils.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisBootstrapService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RoscoService.java delete mode 100644 halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/ResourceBuilder.java delete mode 100644 halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesV1DistributedServiceSpec.groovy delete mode 100644 halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/ResourceBuilderSpec.groovy diff --git a/halyard-config/halyard-config.gradle b/halyard-config/halyard-config.gradle index ac9dea176c..820e61b127 100644 --- a/halyard-config/halyard-config.gradle +++ b/halyard-config/halyard-config.gradle @@ -4,7 +4,6 @@ dependencies { implementation "com.netflix.spinnaker.clouddriver:clouddriver-docker:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-google:$clouddriverVersion" - implementation "com.netflix.spinnaker.clouddriver:clouddriver-kubernetes-v1:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-appengine:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-azure:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-cloudfoundry:$clouddriverVersion" diff --git a/halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/validate/v1/providers/kubernetes/KubernetesAccountValidator.java b/halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/validate/v1/providers/kubernetes/KubernetesAccountValidator.java index 8d30a08e53..da2e72bdc9 100644 --- a/halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/validate/v1/providers/kubernetes/KubernetesAccountValidator.java +++ b/halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/validate/v1/providers/kubernetes/KubernetesAccountValidator.java @@ -21,34 +21,23 @@ import static com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.FATAL; import static com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.WARNING; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.security.KubernetesConfigParser; import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; import com.netflix.spinnaker.halyard.config.model.v1.node.Node; import com.netflix.spinnaker.halyard.config.model.v1.node.Provider; import com.netflix.spinnaker.halyard.config.model.v1.node.Validator; import com.netflix.spinnaker.halyard.config.model.v1.providers.containers.DockerRegistryReference; import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.config.problem.v1.ConfigProblemBuilder; import com.netflix.spinnaker.halyard.config.problem.v1.ConfigProblemSetBuilder; import com.netflix.spinnaker.halyard.core.job.v1.JobExecutor; import com.netflix.spinnaker.halyard.core.job.v1.JobRequest; import com.netflix.spinnaker.halyard.core.job.v1.JobStatus; import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskInterrupted; -import io.fabric8.kubernetes.api.model.NamedContext; -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.DefaultKubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.internal.KubeConfigUtils; -import java.io.IOException; -import java.nio.file.Path; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; @Component @@ -56,13 +45,12 @@ public class KubernetesAccountValidator extends Validator { @Override public void validate(ConfigProblemSetBuilder psBuilder, KubernetesAccount account) { switch (account.getProviderVersion()) { - // TODO(mneterval): remove all V1-only validators after 1.21 is released + // TODO(mneterval): remove all V1-only validators after 1.23 is released case V1: addV1RemovalWarning(psBuilder, account); validateV1KindConfig(psBuilder, account); validateCacheThreads(psBuilder, account); validateV1DockerRegistries(psBuilder, account); - validateKubeconfig(psBuilder, account); validateOnlySpinnakerConfig(psBuilder, account); case V2: validateKindConfig(psBuilder, account); @@ -189,118 +177,6 @@ private void validateCacheThreads(ConfigProblemSetBuilder psBuilder, KubernetesA } } - private void validateKubeconfig(ConfigProblemSetBuilder psBuilder, KubernetesAccount account) { - io.fabric8.kubernetes.api.model.Config kubeconfig; - String context = account.getContext(); - String cluster = account.getCluster(); - String user = account.getUser(); - List namespaces = account.getNamespaces(); - List omitNamespaces = account.getOmitNamespaces(); - - // This indicates if a first pass at the config looks OK. If we don't see any serious problems, - // we'll do one last check - // against the requested kubernetes cluster to ensure that we can run spinnaker. - boolean smoketest = true; - - boolean namespacesProvided = namespaces != null && !namespaces.isEmpty(); - boolean omitNamespacesProvided = omitNamespaces != null && !omitNamespaces.isEmpty(); - - if (namespacesProvided && omitNamespacesProvided) { - psBuilder.addProblem( - ERROR, "At most one of \"namespaces\" and \"omitNamespaces\" can be supplied."); - smoketest = false; - } - - // TODO(lwander) find a good resource / list of resources for generating kubeconfig files to - // link to here. - try { - String kubeconfigContents = validatingFileDecrypt(psBuilder, account.getKubeconfigFile()); - if (kubeconfigContents == null) { - return; - } - - kubeconfig = KubeConfigUtils.parseConfigFromString(kubeconfigContents); - } catch (IOException e) { - psBuilder.addProblem(ERROR, e.getMessage()); - return; - } - - if (context != null && !context.isEmpty()) { - Optional namedContext = - kubeconfig.getContexts().stream().filter(c -> c.getName().equals(context)).findFirst(); - - if (!namedContext.isPresent()) { - psBuilder - .addProblem( - ERROR, - "Context \"" - + context - + "\" not found in kubeconfig \"" - + account.getKubeconfigFile() - + "\".", - "context") - .setRemediation( - "Either add this context to your kubeconfig, rely on the default context, or pick another kubeconfig file."); - smoketest = false; - } - } else { - String currentContext = kubeconfig.getCurrentContext(); - if (StringUtils.isEmpty(currentContext)) { - psBuilder - .addProblem( - ERROR, - "You have not specified a Kubernetes context, and your kubeconfig \"" - + account.getKubeconfigFile() - + "\" has no current-context.", - "context") - .setRemediation( - "Either specify a context in your halconfig, or set a current-context in your kubeconfig."); - smoketest = false; - } else { - psBuilder - .addProblem( - WARNING, - "You have not specified a Kubernetes context in your halconfig, Spinnaker will use \"" - + currentContext - + "\" instead.", - "context") - .setRemediation( - "We recommend explicitly setting a context in your halconfig, to ensure changes to your kubeconfig won't break your deployment."); - } - } - - if (smoketest) { - Path kubeconfigPath = validatingFileDecryptPath(account.getKubeconfigFile()); - Config config = - KubernetesConfigParser.parse( - kubeconfigPath != null ? kubeconfigPath.toString() : null, - context, - cluster, - user, - namespaces, - false); - try { - KubernetesClient client = new DefaultKubernetesClient(config); - - client.namespaces().list(); - } catch (Exception e) { - ConfigProblemBuilder pb = - psBuilder.addProblem( - ERROR, - "Unable to communicate with your Kubernetes cluster: " + e.getMessage() + "."); - - if (e.getMessage().contains("Token may have expired")) { - pb.setRemediation( - "If you downloaded these keys with gcloud, it's possible they are in the wrong format. To fix this, run \n\n" - + "gcloud config set container/use_client_certificate true\n\ngcloud container clusters get-credentials $CLUSTERNAME"); - } else { - pb.setRemediation( - "Unable to authenticate with your Kubernetes cluster. Try using kubectl to verify your credentials."); - } - } - } - } - public void ensureKubectlExists(ConfigProblemSetBuilder p) { JobExecutor jobExecutor = DaemonTaskHandler.getJobExecutor(); JobRequest request = diff --git a/halyard-deploy/halyard-deploy.gradle b/halyard-deploy/halyard-deploy.gradle index ef6cd7b572..70da9ab8ed 100644 --- a/halyard-deploy/halyard-deploy.gradle +++ b/halyard-deploy/halyard-deploy.gradle @@ -5,8 +5,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-web' implementation "com.netflix.spinnaker.clouddriver:clouddriver-core:$clouddriverVersion" - implementation "com.netflix.spinnaker.clouddriver:clouddriver-kubernetes:$clouddriverVersion" - implementation "com.netflix.spinnaker.clouddriver:clouddriver-kubernetes-v1:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-google:$clouddriverVersion" implementation "com.netflix.spinnaker.clouddriver:clouddriver-security:$clouddriverVersion" implementation "com.netflix.spinnaker.kork:kork-secrets" diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/deployment/v1/ServiceProviderFactory.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/deployment/v1/ServiceProviderFactory.java index c8b27bb9f2..6984e53b4d 100644 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/deployment/v1/ServiceProviderFactory.java +++ b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/deployment/v1/ServiceProviderFactory.java @@ -27,7 +27,6 @@ import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerServiceProvider; import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.bake.debian.BakeDebianServiceProvider; import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.google.GoogleDistributedServiceProvider; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1.KubernetesV1DistributedServiceProvider; import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v2.KubectlServiceProvider; import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.local.debian.LocalDebianServiceProvider; import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.local.git.LocalGitServiceProvider; @@ -38,8 +37,6 @@ public class ServiceProviderFactory { @Autowired AccountService accountService; - @Autowired KubernetesV1DistributedServiceProvider kubernetesV1DistributedServiceProvider; - @Autowired KubectlServiceProvider kubectlServiceProvider; @Autowired GoogleDistributedServiceProvider googleDistributedServiceProvider; @@ -89,14 +86,12 @@ private SpinnakerServiceProvider createDeployableServiceProvider( switch (providerType) { case KUBERNETES: - switch (account.getProviderVersion()) { - case V1: - return kubernetesV1DistributedServiceProvider; - case V2: - return kubectlServiceProvider; - default: - return kubernetesV1DistributedServiceProvider; + if (account.getProviderVersion() == Provider.ProviderVersion.V1) { + throw new HalException( + Problem.Severity.FATAL, + "Distributed deployment is only available for standard Kubernetes (V2) accounts."); } + return kubectlServiceProvider; case GOOGLE: return googleDistributedServiceProvider; default: diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/services/v1/DeployService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/services/v1/DeployService.java index 9e10c48cb2..c0f661b28c 100644 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/services/v1/DeployService.java +++ b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/services/v1/DeployService.java @@ -16,7 +16,7 @@ package com.netflix.spinnaker.halyard.deploy.services.v1; -import static com.netflix.spinnaker.halyard.config.model.v1.node.Provider.ProviderVersion.V2; +import static com.netflix.spinnaker.halyard.config.model.v1.node.Provider.ProviderVersion.V1; import static com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.FATAL; import com.netflix.spinnaker.halyard.config.config.v1.HalconfigDirectoryStructure; @@ -38,7 +38,6 @@ import com.netflix.spinnaker.halyard.deploy.deployment.v1.DeployOption; import com.netflix.spinnaker.halyard.deploy.deployment.v1.Deployer; import com.netflix.spinnaker.halyard.deploy.deployment.v1.DeploymentDetails; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.DistributedDeployer; import com.netflix.spinnaker.halyard.deploy.deployment.v1.KubectlDeployer; import com.netflix.spinnaker.halyard.deploy.deployment.v1.LocalDeployer; import com.netflix.spinnaker.halyard.deploy.deployment.v1.LocalGitDeployer; @@ -64,8 +63,6 @@ public class DeployService { @Autowired AccountService accountService; - @Autowired DistributedDeployer distributedDeployer; - @Autowired KubectlDeployer kubectlDeployer; @Autowired LocalDeployer localDeployer; @@ -358,11 +355,13 @@ private Deployer getDeployer(DeploymentConfiguration deploymentConfiguration) { Provider.ProviderType providerType = ((Provider) account.getParent()).providerType(); if (providerType == Provider.ProviderType.KUBERNETES - && account.getProviderVersion() == V2) { - return kubectlDeployer; - } else { - return distributedDeployer; + && account.getProviderVersion() == V1) { + throw new HalException( + Problem.Severity.FATAL, + "Distributed deployment is only available for standard Kubernetes (V2) accounts."); } + + return kubectlDeployer; default: throw new IllegalArgumentException("Unrecognized deployment type " + type); } diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesService.java index f3d9a3df2e..f719904fff 100644 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesService.java +++ b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesService.java @@ -18,8 +18,7 @@ import static com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment.ImageVariant.SLIM; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.KubernetesUtil; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesImageDescription; +import com.google.common.base.Strings; import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment.ImageVariant; import com.netflix.spinnaker.halyard.core.registry.v1.Versions; @@ -51,12 +50,11 @@ default String getArtifactId(DeploymentConfiguration deploymentConfiguration) { tag = String.format("%s-%s", version, imageVariant.getContainerSuffix()); } - KubernetesImageDescription image = - KubernetesImageDescription.builder() - .registry(getDockerRegistry(deploymentName, getArtifact())) - .repository(artifactName) - .tag(tag) - .build(); - return KubernetesUtil.getImageId(image); + String registry = getDockerRegistry(deploymentName, getArtifact()); + if (!Strings.isNullOrEmpty(registry)) { + return String.format("%s/%s:%s", registry, artifactName, tag); + } else { + return String.format("%s:%s", artifactName, tag); + } } } diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverBootstrapService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverBootstrapService.java deleted file mode 100644 index 144bcb8776..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverBootstrapService.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ClouddriverBootstrapService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ClouddriverService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.ArrayList; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1ClouddriverBootstrapService extends ClouddriverBootstrapService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - List profiles = new ArrayList<>(); - profiles.add("bootstrap"); - profiles.add("bootstrap-local"); - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(profiles); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setMonitored(false) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(10); - final boolean requiredToBootstrap = true; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverService.java deleted file mode 100644 index 8db95ae818..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ClouddriverService.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ClouddriverService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1ClouddriverService extends ClouddriverService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public List getProfiles( - DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) { - List profiles = super.getProfiles(deploymentConfiguration, endpoints); - generateAwsProfile(deploymentConfiguration, endpoints, getRootHomeDirectory()) - .ifPresent(profiles::add); - generateAwsProfile(deploymentConfiguration, endpoints, getHomeDirectory()) - .ifPresent(profiles::add); - return profiles; - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(4); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DeckService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DeckService.java deleted file mode 100644 index 41a6f1d3e0..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DeckService.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.deck.DeckDockerProfileFactory; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.DeckService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1DeckService extends DeckService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Autowired DeckDockerProfileFactory deckDockerProfileFactory; - - private final String settingsPath = "/opt/spinnaker/config"; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(deploymentConfiguration.getSecurity().getUiSecurity()); - settings - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(kubernetesSharedServiceSettings.getDeployLocation()) - .setEnabled(true); - return settings; - } - - @Override - protected Optional customProfileOutputPath(String profileName) { - if (profileName.equals("settings.js") || profileName.equals("settings-local.js")) { - return Optional.of(Paths.get(settingsPath, profileName).toString()); - } else { - return Optional.empty(); - } - } - - @Override - public List getProfiles( - DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) { - List result = new ArrayList<>(); - String filename = "settings.js"; - String path = Paths.get(settingsPath, filename).toString(); - result.add( - deckDockerProfileFactory.getProfile(filename, path, deploymentConfiguration, endpoints)); - return result; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedLogCollectorFactory.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedLogCollectorFactory.java deleted file mode 100644 index d7acfb45cc..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedLogCollectorFactory.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.config.v1.HalconfigDirectoryStructure; -import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.SidecarService; -import java.io.File; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class KubernetesV1DistributedLogCollectorFactory { - public DistributedLogCollector build(HasServiceSettings service) { - return new KubernetesDistributedLogCollector<>(service); - } - - @Autowired HalconfigDirectoryStructure directoryStructure; - - private class KubernetesDistributedLogCollector - extends DistributedLogCollector { - KubernetesDistributedLogCollector(HasServiceSettings service) { - super(service); - } - - @Override - protected HalconfigDirectoryStructure getDirectoryStructure() { - return directoryStructure; - } - - @Override - protected void collectInstanceLogs( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings, - File instanceOutputDir, - String instanceId) { - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - DaemonTaskHandler.newStage("Reading " + getService().getCanonicalName() + " logs"); - DaemonTaskHandler.message("Reading container " + getServiceName() + "'s logs"); - KubernetesV1ProviderUtils.storeInstanceLogs( - DaemonTaskHandler.getJobExecutor(), - details, - settings.getLocation(), - instanceId, - getServiceName(), - instanceOutputDir); - - DistributedService service = (DistributedService) getService(); - - for (Object rawSidecarService : service.getSidecars(runtimeSettings)) { - SidecarService sidecarService = (SidecarService) rawSidecarService; - String sidecarName = sidecarService.getService().getServiceName(); - DaemonTaskHandler.message("Reading container " + sidecarName + "'s logs"); - KubernetesV1ProviderUtils.storeInstanceLogs( - DaemonTaskHandler.getJobExecutor(), - details, - settings.getLocation(), - instanceId, - sidecarName, - instanceOutputDir); - } - } - } -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedService.java deleted file mode 100644 index b876a0e9bb..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedService.java +++ /dev/null @@ -1,878 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.netflix.frigga.Names; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.KubernetesUtil; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.loadbalancer.KubernetesLoadBalancerDescription; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.loadbalancer.KubernetesNamedServicePort; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.DeployKubernetesAtomicOperationDescription; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesContainerDescription; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesContainerPort; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesEnvVar; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesHandler; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesHandlerType; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesHttpGetAction; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesImageDescription; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesProbe; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesResourceDescription; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesSecretVolumeSource; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesTcpSocketAction; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesVolumeMount; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesVolumeSource; -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesVolumeSourceType; -import com.netflix.spinnaker.halyard.config.model.v1.node.CustomSizing; -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment; -import com.netflix.spinnaker.halyard.config.model.v1.node.Provider; -import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.core.error.v1.HalException; -import com.netflix.spinnaker.halyard.core.job.v1.JobExecutor; -import com.netflix.spinnaker.halyard.core.job.v1.JobRequest; -import com.netflix.spinnaker.halyard.core.job.v1.JobStatus; -import com.netflix.spinnaker.halyard.core.problem.v1.Problem; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails; -import com.netflix.spinnaker.halyard.deploy.services.v1.ArtifactService; -import com.netflix.spinnaker.halyard.deploy.services.v1.GenerateService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.RunningServiceDetails; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.RunningServiceDetails.Instance; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ConfigSource; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.LogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceInterfaceFactory; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerMonitoringDaemonService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.SidecarService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesService; -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.ContainerStatus; -import io.fabric8.kubernetes.api.model.LocalObjectReference; -import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.SecretVolumeSourceBuilder; -import io.fabric8.kubernetes.api.model.ServiceBuilder; -import io.fabric8.kubernetes.api.model.ServicePortBuilder; -import io.fabric8.kubernetes.api.model.Volume; -import io.fabric8.kubernetes.api.model.VolumeBuilder; -import io.fabric8.kubernetes.api.model.apps.ReplicaSet; -import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import java.io.File; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.springframework.util.SocketUtils; - -public interface KubernetesV1DistributedService - extends DistributedService, - LogCollector>, - KubernetesService { - ArtifactService getArtifactService(); - - ServiceInterfaceFactory getServiceInterfaceFactory(); - - ObjectMapper getObjectMapper(); - - default String getRootHomeDirectory() { - return "/root"; - } - - default String getHomeDirectory() { - return "/home/spinnaker"; - } - - default JobExecutor getJobExecutor() { - return DaemonTaskHandler.getJobExecutor(); - } - - default String getNamespace(ServiceSettings settings) { - return getRegion(settings); - } - - default String buildAddress(String namespace) { - return String.join(".", getServiceName(), namespace); - } - - default List getImagePullSecrets(ServiceSettings settings) { - List imagePullSecrets = new ArrayList<>(); - if (settings.getKubernetes().getImagePullSecrets() != null) { - for (String imagePullSecret : settings.getKubernetes().getImagePullSecrets()) { - imagePullSecrets.add(new LocalObjectReference(imagePullSecret)); - } - } - return imagePullSecrets; - } - - default Provider.ProviderType getProviderType() { - return Provider.ProviderType.KUBERNETES; - } - - default List getHealthProviders() { - List healthProviders = new ArrayList<>(); - healthProviders.add("KubernetesContainer"); - healthProviders.add("KubernetesPod"); - return healthProviders; - } - - default Map> getAvailabilityZones(ServiceSettings settings) { - String namespace = getNamespace(settings); - List zones = new ArrayList<>(); - zones.add(namespace); - Map> availabilityZones = new HashMap<>(); - availabilityZones.put(namespace, zones); - return availabilityZones; - } - - default void resizeVersion( - AccountDeploymentDetails details, - ServiceSettings settings, - int version, - int targetSize) { - String name = getVersionedName(version); - String namespace = getNamespace(settings); - KubernetesV1ProviderUtils.resize(details, namespace, name, targetSize); - } - - @Override - default Map buildRollbackPipeline( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - Map pipeline = - DistributedService.super.buildRollbackPipeline(details, runtimeSettings); - - List> stages = (List>) pipeline.get("stages"); - assert (stages != null && !stages.isEmpty()); - - for (Map stage : stages) { - stage.put("namespaces", Collections.singletonList(getNamespace(settings))); - stage.put("interestingHealthProviderNames", Collections.singletonList("KubernetesService")); - stage.remove("region"); - } - - return pipeline; - } - - default Map getLoadBalancerDescription( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - int port = settings.getPort(); - String accountName = details.getAccount().getName(); - - KubernetesLoadBalancerDescription description = new KubernetesLoadBalancerDescription(); - - String namespace = getNamespace(settings); - String name = getServiceName(); - Names parsedName = Names.parseName(name); - description.setApp(parsedName.getApp()); - description.setStack(parsedName.getStack()); - description.setDetail(parsedName.getDetail()); - - description.setName(name); - description.setNamespace(namespace); - description.setAccount(accountName); - - KubernetesNamedServicePort servicePort = new KubernetesNamedServicePort(); - servicePort.setPort(port); - servicePort.setTargetPort(port); - servicePort.setName("http"); - servicePort.setProtocol("TCP"); - - KubernetesNamedServicePort monitoringPort = new KubernetesNamedServicePort(); - monitoringPort.setPort(8008); - monitoringPort.setTargetPort(8008); - monitoringPort.setName("monitoring"); - monitoringPort.setProtocol("TCP"); - - List servicePorts = new ArrayList<>(); - servicePorts.add(servicePort); - servicePorts.add(monitoringPort); - description.setPorts(servicePorts); - - return getObjectMapper().convertValue(description, new TypeReference>() {}); - } - - default List stageProfiles( - AccountDeploymentDetails details, - GenerateService.ResolvedConfiguration resolvedConfiguration) { - SpinnakerService thisService = getService(); - ServiceSettings thisServiceSettings = resolvedConfiguration.getServiceSettings(thisService); - SpinnakerRuntimeSettings runtimeSettings = resolvedConfiguration.getRuntimeSettings(); - Integer version = getRunningServiceDetails(details, runtimeSettings).getLatestEnabledVersion(); - if (version == null) { - version = 0; - } else { - version++; - } - - String namespace = getNamespace(thisServiceSettings); - KubernetesV1ProviderUtils.createNamespace(details, namespace); - - String name = getServiceName(); - Map env = new HashMap<>(); - List configSources = new ArrayList<>(); - - Map serviceProfiles = - resolvedConfiguration.getProfilesForService(thisService.getType()); - Set requiredFiles = new HashSet<>(); - - for (SidecarService sidecarService : getSidecars(runtimeSettings)) { - for (Profile profile : - sidecarService.getSidecarProfiles(resolvedConfiguration, thisService)) { - if (profile == null) { - throw new HalException( - Problem.Severity.FATAL, - "Service " - + sidecarService.getService().getCanonicalName() - + " is required but was not supplied for deployment."); - } - - serviceProfiles.put(profile.getName(), profile); - requiredFiles.addAll(profile.getRequiredFiles()); - } - } - - Map> collapseByDirectory = new HashMap<>(); - - for (Map.Entry entry : serviceProfiles.entrySet()) { - Profile profile = entry.getValue(); - String mountPoint = Paths.get(profile.getOutputFile()).getParent().toString(); - Set profiles = collapseByDirectory.getOrDefault(mountPoint, new HashSet<>()); - profiles.add(profile); - requiredFiles.addAll(profile.getRequiredFiles()); - collapseByDirectory.put(mountPoint, profiles); - } - - String stagingPath = getSpinnakerStagingPath(details.getDeploymentName()); - if (!requiredFiles.isEmpty()) { - String secretName = KubernetesV1ProviderUtils.componentDependencies(name, version); - String mountPoint = null; - for (String file : requiredFiles) { - String nextMountPoint = Paths.get(file).getParent().toString(); - if (mountPoint == null) { - mountPoint = nextMountPoint; - } - assert (mountPoint.equals(nextMountPoint)); - } - - Set> pairs = - requiredFiles.stream() - .map( - f -> { - return new ImmutablePair<>(new File(f), new File(f).getName()); - }) - .collect(Collectors.toSet()); - - KubernetesV1ProviderUtils.upsertSecret(details, pairs, secretName, namespace); - configSources.add(new ConfigSource().setId(secretName).setMountPath(mountPoint)); - } - - int ind = 0; - for (Map.Entry> entry : collapseByDirectory.entrySet()) { - env.clear(); - String mountPoint = entry.getKey(); - Set profiles = entry.getValue(); - env.putAll( - profiles.stream() - .reduce( - new HashMap<>(), - (acc, profile) -> { - acc.putAll(profile.getEnv()); - return acc; - }, - (a, b) -> { - a.putAll(b); - return a; - })); - - String secretName = KubernetesV1ProviderUtils.componentSecret(name + ind, version); - ind += 1; - - Set> pairs = - profiles.stream() - .map( - p -> { - return new ImmutablePair<>( - new File(stagingPath, p.getName()), new File(p.getOutputFile()).getName()); - }) - .collect(Collectors.toSet()); - - KubernetesV1ProviderUtils.upsertSecret(details, pairs, secretName, namespace); - configSources.add(new ConfigSource().setId(secretName).setMountPath(mountPoint).setEnv(env)); - } - - return configSources; - } - - default Map getServerGroupDescription( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings, - List configSources) { - DeployKubernetesAtomicOperationDescription description = - new DeployKubernetesAtomicOperationDescription(); - SpinnakerMonitoringDaemonService monitoringService = getMonitoringDaemonService(); - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - DeploymentEnvironment deploymentEnvironment = - details.getDeploymentConfiguration().getDeploymentEnvironment(); - String accountName = details.getAccount().getName(); - String namespace = getNamespace(settings); - String name = getServiceName(); - Names parsedName = Names.parseName(name); - - description.setNamespace(namespace); - description.setAccount(accountName); - - description.setApplication(parsedName.getApp()); - description.setStack(parsedName.getStack()); - description.setFreeFormDetails(parsedName.getDetail()); - - List volumeSources = new ArrayList<>(); - for (ConfigSource configSource : configSources) { - KubernetesVolumeSource volumeSource = new KubernetesVolumeSource(); - volumeSource.setName(configSource.getId()); - volumeSource.setType(KubernetesVolumeSourceType.Secret); - KubernetesSecretVolumeSource secretVolumeSource = new KubernetesSecretVolumeSource(); - secretVolumeSource.setSecretName(configSource.getId()); - volumeSource.setSecret(secretVolumeSource); - volumeSources.add(volumeSource); - } - - description.setVolumeSources(volumeSources); - description.setPodAnnotations(settings.getKubernetes().getPodAnnotations()); - description.setNodeSelector(deploymentEnvironment.getNodeSelectors()); - - List loadBalancers = new ArrayList<>(); - loadBalancers.add(name); - description.setLoadBalancers(loadBalancers); - - List containers = new ArrayList<>(); - ServiceSettings serviceSettings = runtimeSettings.getServiceSettings(getService()); - KubernetesContainerDescription container = - buildContainer(name, serviceSettings, configSources, deploymentEnvironment, description); - containers.add(container); - - ServiceSettings monitoringSettings = runtimeSettings.getServiceSettings(monitoringService); - if (monitoringSettings.getEnabled() && serviceSettings.getMonitored()) { - serviceSettings = runtimeSettings.getServiceSettings(monitoringService); - container = - buildContainer( - monitoringService.getServiceName(), - serviceSettings, - configSources, - deploymentEnvironment, - description); - containers.add(container); - } - - description.setContainers(containers); - - return getObjectMapper().convertValue(description, new TypeReference>() {}); - } - - default KubernetesHandler buildProbeHandler(int port, String scheme, String healthEndpoint) { - KubernetesHandler handler = new KubernetesHandler(); - if (healthEndpoint != null) { - handler.setType(KubernetesHandlerType.HTTP); - KubernetesHttpGetAction action = new KubernetesHttpGetAction(); - action.setPath(healthEndpoint); - action.setPort(port); - action.setUriScheme(scheme); - handler.setHttpGetAction(action); - } else { - handler.setType(KubernetesHandlerType.TCP); - KubernetesTcpSocketAction action = new KubernetesTcpSocketAction(); - action.setPort(port); - handler.setTcpSocketAction(action); - } - return handler; - } - - default KubernetesContainerDescription buildContainer( - String name, - ServiceSettings settings, - List configSources, - DeploymentEnvironment deploymentEnvironment, - DeployKubernetesAtomicOperationDescription description) { - KubernetesContainerDescription container = new KubernetesContainerDescription(); - String healthEndpoint = settings.getHealthEndpoint(); - int port = settings.getPort(); - String scheme = settings.getScheme(); - if (StringUtils.isNotEmpty(scheme)) { - scheme = scheme.toUpperCase(); - } else { - scheme = null; - } - - KubernetesProbe readinessProbe = new KubernetesProbe(); - KubernetesHandler readinessHandler = buildProbeHandler(port, scheme, healthEndpoint); - readinessProbe.setHandler(readinessHandler); - container.setReadinessProbe(readinessProbe); - - DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig = - deploymentEnvironment.getLivenessProbeConfig(); - if (livenessProbeConfig != null - && livenessProbeConfig.isEnabled() - && livenessProbeConfig.getInitialDelaySeconds() != null) { - KubernetesProbe livenessProbe = new KubernetesProbe(); - KubernetesHandler livenessHandler = buildProbeHandler(port, scheme, healthEndpoint); - livenessProbe.setHandler(livenessHandler); - livenessProbe.setInitialDelaySeconds(livenessProbeConfig.getInitialDelaySeconds()); - container.setLivenessProbe(livenessProbe); - } - - applyCustomSize(container, deploymentEnvironment, name, description); - - KubernetesImageDescription imageDescription = - KubernetesUtil.buildImageDescription(settings.getArtifactId()); - container.setImageDescription(imageDescription); - container.setName(name); - - List ports = new ArrayList<>(); - KubernetesContainerPort containerPort = new KubernetesContainerPort(); - containerPort.setContainerPort(port); - ports.add(containerPort); - container.setPorts(ports); - - List volumeMounts = new ArrayList<>(); - for (ConfigSource configSource : configSources) { - KubernetesVolumeMount volumeMount = new KubernetesVolumeMount(); - volumeMount.setName(configSource.getId()); - volumeMount.setMountPath(configSource.getMountPath()); - volumeMounts.add(volumeMount); - } - - container.setVolumeMounts(volumeMounts); - - List envVars = new ArrayList<>(); - settings - .getEnv() - .forEach( - (k, v) -> { - KubernetesEnvVar envVar = new KubernetesEnvVar(); - envVar.setName(k); - envVar.setValue(v); - - envVars.add(envVar); - }); - - configSources.forEach( - c -> { - c.getEnv() - .entrySet() - .forEach( - envEntry -> { - KubernetesEnvVar envVar = new KubernetesEnvVar(); - envVar.setName(envEntry.getKey()); - envVar.setValue(envEntry.getValue()); - envVars.add(envVar); - }); - }); - - container.setEnvVars(envVars); - - return container; - } - - default void applyCustomSize( - KubernetesContainerDescription container, - DeploymentEnvironment deploymentEnvironment, - String componentName, - DeployKubernetesAtomicOperationDescription description) { - Map componentSizing = deploymentEnvironment.getCustomSizing().get(componentName); - - if (componentSizing != null) { - - if (componentSizing.get("requests") != null) { - container.setRequests(retrieveKubernetesResourceDescription(componentSizing, "requests")); - } - - if (componentSizing.get("limits") != null) { - container.setLimits(retrieveKubernetesResourceDescription(componentSizing, "limits")); - } - - if (componentSizing.get("replicas") != null) { - description.setTargetSize(retrieveKubernetesTargetSize(componentSizing)); - } - } - - /* TODO(lwander) this needs work - SizingTranslation.ServiceSize serviceSize = sizingTranslation.getServiceSize(deploymentEnvironment.getSize(), service); - */ - } - - default KubernetesResourceDescription retrieveKubernetesResourceDescription( - Map componentSizing, String resourceType) { - KubernetesResourceDescription requests = new KubernetesResourceDescription(); - requests.setCpu(CustomSizing.stringOrNull(componentSizing.get(resourceType).get("cpu"))); - requests.setMemory(CustomSizing.stringOrNull(componentSizing.get(resourceType).get("memory"))); - return requests; - } - - default Integer retrieveKubernetesTargetSize(Map componentSizing) { - return (componentSizing != null && componentSizing.get("replicas") != null) - ? (Integer) componentSizing.get("replicas") - : 1; - } - - default void ensureRunning( - AccountDeploymentDetails details, - GenerateService.ResolvedConfiguration resolvedConfiguration, - List configSources, - boolean recreate) { - ServiceSettings settings = resolvedConfiguration.getServiceSettings(getService()); - SpinnakerRuntimeSettings runtimeSettings = resolvedConfiguration.getRuntimeSettings(); - String namespace = getNamespace(settings); - String serviceName = getServiceName(); - String replicaSetName = serviceName + "-v000"; - int port = settings.getPort(); - - SpinnakerMonitoringDaemonService monitoringService = getMonitoringDaemonService(); - ServiceSettings monitoringSettings = runtimeSettings.getServiceSettings(monitoringService); - - KubernetesClient client = KubernetesV1ProviderUtils.getClient(details); - KubernetesV1ProviderUtils.createNamespace(details, namespace); - - Map serviceSelector = new HashMap<>(); - serviceSelector.put("load-balancer-" + serviceName, "true"); - - Map replicaSetSelector = new HashMap<>(); - replicaSetSelector.put("replication-controller", replicaSetName); - - Map podLabels = new HashMap<>(); - podLabels.putAll(replicaSetSelector); - podLabels.putAll(serviceSelector); - - Map serviceLabels = new HashMap<>(); - serviceLabels.put("app", "spin"); - serviceLabels.put("stack", getCanonicalName()); - - ServiceBuilder serviceBuilder = new ServiceBuilder(); - serviceBuilder = - serviceBuilder - .withNewMetadata() - .withName(serviceName) - .withNamespace(namespace) - .withLabels(serviceLabels) - .endMetadata() - .withNewSpec() - .withSelector(serviceSelector) - .withPorts( - new ServicePortBuilder().withPort(port).withName("http").build(), - new ServicePortBuilder() - .withPort(monitoringSettings.getPort()) - .withName("monitoring") - .build()) - .endSpec(); - - boolean create = true; - if (client.services().inNamespace(namespace).withName(serviceName).get() != null) { - if (recreate) { - client.services().inNamespace(namespace).withName(serviceName).delete(); - } else { - create = false; - } - } - - if (create) { - client.services().inNamespace(namespace).create(serviceBuilder.build()); - } - - List containers = new ArrayList<>(); - DeploymentEnvironment deploymentEnvironment = - details.getDeploymentConfiguration().getDeploymentEnvironment(); - containers.add( - ResourceBuilder.buildContainer( - serviceName, settings, configSources, deploymentEnvironment)); - - for (SidecarService sidecarService : getSidecars(runtimeSettings)) { - String sidecarName = sidecarService.getService().getServiceName(); - ServiceSettings sidecarSettings = - resolvedConfiguration.getServiceSettings(sidecarService.getService()); - containers.add( - ResourceBuilder.buildContainer( - sidecarName, sidecarSettings, configSources, deploymentEnvironment)); - } - - List volumes = - configSources.stream() - .map( - c -> { - return new VolumeBuilder() - .withName(c.getId()) - .withSecret(new SecretVolumeSourceBuilder().withSecretName(c.getId()).build()) - .build(); - }) - .collect(Collectors.toList()); - - ReplicaSetBuilder replicaSetBuilder = new ReplicaSetBuilder(); - List imagePullSecrets = getImagePullSecrets(settings); - Map componentSizing = deploymentEnvironment.getCustomSizing().get(serviceName); - - replicaSetBuilder = - replicaSetBuilder - .withNewMetadata() - .withName(replicaSetName) - .withNamespace(namespace) - .endMetadata() - .withNewSpec() - .withReplicas(retrieveKubernetesTargetSize(componentSizing)) - .withNewSelector() - .withMatchLabels(replicaSetSelector) - .endSelector() - .withNewTemplate() - .withNewMetadata() - .withAnnotations(settings.getKubernetes().getPodAnnotations()) - .withLabels(podLabels) - .endMetadata() - .withNewSpec() - .withContainers(containers) - .withTerminationGracePeriodSeconds(5L) - .withVolumes(volumes) - .withImagePullSecrets(imagePullSecrets) - .endSpec() - .endTemplate() - .endSpec(); - - create = true; - if (client.extensions().replicaSets().inNamespace(namespace).withName(replicaSetName).get() - != null) { - if (recreate) { - client.extensions().replicaSets().inNamespace(namespace).withName(replicaSetName).delete(); - - RunningServiceDetails runningServiceDetails = - getRunningServiceDetails(details, runtimeSettings); - while (runningServiceDetails.getLatestEnabledVersion() != null) { - DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(5)); - runningServiceDetails = getRunningServiceDetails(details, runtimeSettings); - } - } else { - create = false; - } - } - - if (create) { - client.extensions().replicaSets().inNamespace(namespace).create(replicaSetBuilder.build()); - } - - RunningServiceDetails runningServiceDetails = - getRunningServiceDetails(details, runtimeSettings); - Integer version = runningServiceDetails.getLatestEnabledVersion(); - while (version == null - || runningServiceDetails.getInstances().get(version).stream() - .anyMatch(i -> !(i.isHealthy() && i.isRunning()))) { - DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(5)); - runningServiceDetails = getRunningServiceDetails(details, runtimeSettings); - version = runningServiceDetails.getLatestEnabledVersion(); - } - } - - @Override - default RunningServiceDetails getRunningServiceDetails( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - RunningServiceDetails res = new RunningServiceDetails(); - - KubernetesClient client = KubernetesV1ProviderUtils.getClient(details); - String name = getServiceName(); - String namespace = getNamespace(settings); - - RunningServiceDetails.LoadBalancer lb = new RunningServiceDetails.LoadBalancer(); - lb.setExists(client.services().inNamespace(namespace).withName(name).get() != null); - res.setLoadBalancer(lb); - - List pods = - client - .pods() - .inNamespace(namespace) - .withLabel("load-balancer-" + name, "true") - .list() - .getItems(); - pods.addAll( - client - .pods() - .inNamespace(namespace) - .withLabel("load-balancer-" + name, "false") - .list() - .getItems()); - - Map> instances = res.getInstances(); - for (Pod pod : pods) { - String podName = pod.getMetadata().getName(); - String serverGroupName = podName.substring(0, podName.lastIndexOf("-")); - Names parsedName = Names.parseName(serverGroupName); - Integer version = parsedName.getSequence(); - if (version == null) { - throw new IllegalStateException( - "Server group for service " - + getServiceName() - + " has unknown sequence (" - + serverGroupName - + ")"); - } - - String location = pod.getMetadata().getNamespace(); - String id = pod.getMetadata().getName(); - - Instance instance = new Instance().setId(id).setLocation(location); - List containerStatuses = pod.getStatus().getContainerStatuses(); - if (!containerStatuses.isEmpty() - && containerStatuses.stream().allMatch(ContainerStatus::getReady)) { - instance.setHealthy(true); - } - - if (!containerStatuses.isEmpty() - && containerStatuses.stream() - .allMatch( - s -> s.getState().getRunning() != null && s.getState().getTerminated() == null)) { - instance.setRunning(true); - } - - List knownInstances = instances.getOrDefault(version, new ArrayList<>()); - knownInstances.add(instance); - instances.put(version, knownInstances); - } - - List replicaSets = - client.extensions().replicaSets().inNamespace(settings.getLocation()).list().getItems(); - for (ReplicaSet rs : replicaSets) { - String rsName = rs.getMetadata().getName(); - Names parsedRsName = Names.parseName(rsName); - if (!parsedRsName.getCluster().equals(getServiceName())) { - continue; - } - - instances.computeIfAbsent(parsedRsName.getSequence(), i -> new ArrayList<>()); - } - - return res; - } - - @Override - default S connectToInstance( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings, - SpinnakerService sidecar, - String instanceId) { - ServiceSettings settings = runtimeSettings.getServiceSettings(sidecar); - String namespace = getNamespace(settings); - int localPort = SocketUtils.findAvailableTcpPort(); - int targetPort = settings.getPort(); - List command = - KubernetesV1ProviderUtils.kubectlPortForwardCommand( - details, namespace, instanceId, targetPort, localPort); - JobRequest request = new JobRequest().setTokenizedCommand(command); - String jobId = getJobExecutor().startJob(request); - - // Wait for the proxy to spin up. - DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(5)); - - JobStatus status = getJobExecutor().updateJob(jobId); - - // This should be a long-running job. - if (status.getState() == JobStatus.State.COMPLETED) { - throw new HalException( - Problem.Severity.FATAL, - "Unable to establish a proxy against " - + getServiceName() - + ":\n" - + status.getStdOut() - + "\n" - + status.getStdErr()); - } - - return getServiceInterfaceFactory() - .createService(settings.getScheme() + "://localhost:" + localPort, sidecar); - } - - @Override - default S connectToService( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings, - SpinnakerService service) { - ServiceSettings settings = runtimeSettings.getServiceSettings(service); - - KubernetesV1ProviderUtils.Proxy proxy = - KubernetesV1ProviderUtils.openProxy(getJobExecutor(), details); - String endpoint = - KubernetesV1ProviderUtils.proxyServiceEndpoint( - proxy, getNamespace(settings), getServiceName(), settings.getPort()) - .toString(); - - return getServiceInterfaceFactory().createService(endpoint, service); - } - - default String connectCommand( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings, - int localPort) { - ServiceSettings settings = runtimeSettings.getServiceSettings(getService()); - RunningServiceDetails runningServiceDetails = - getRunningServiceDetails(details, runtimeSettings); - Map> instances = runningServiceDetails.getInstances(); - Integer latest = runningServiceDetails.getLatestEnabledVersion(); - String namespace = getNamespace(settings); - - List latestInstances = instances.get(latest); - if (latestInstances == null || latestInstances.isEmpty()) { - throw new HalException( - Problem.Severity.FATAL, - "No instances running in latest server group for service " - + getServiceName() - + " in namespace " - + namespace); - } - - return String.join( - " ", - KubernetesV1ProviderUtils.kubectlPortForwardCommand( - details, namespace, latestInstances.get(0).getId(), settings.getPort(), localPort)); - } - - default String connectCommand( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - return connectCommand( - details, runtimeSettings, runtimeSettings.getServiceSettings(getService()).getPort()); - } - - default void deleteVersion( - AccountDeploymentDetails details, - ServiceSettings settings, - Integer version) { - String name = getVersionedName(version); - String namespace = getNamespace(settings); - KubernetesV1ProviderUtils.deleteReplicaSet(details, namespace, name); - } -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceDelegate.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceDelegate.java deleted file mode 100644 index 85ecc644eb..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceDelegate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.config.v1.ArtifactSourcesConfig; -import com.netflix.spinnaker.halyard.core.registry.v1.BillOfMaterials; -import com.netflix.spinnaker.halyard.deploy.services.v1.ArtifactService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceInterfaceFactory; -import lombok.Getter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class KubernetesV1DistributedServiceDelegate { - @Autowired ArtifactSourcesConfig artifactSourcesConfig; - - @Autowired @Getter KubernetesV1DistributedLogCollectorFactory logCollectorFactory; - - public String getDockerRegistry(String deploymentName, SpinnakerArtifact artifact) { - BillOfMaterials.ArtifactSources artifactSources = - artifactService.getArtifactSources(deploymentName, artifact); - return artifactSourcesConfig.mergeWithBomSources(artifactSources).getDockerRegistry(); - } - - @Autowired @Getter ArtifactService artifactService; - - @Autowired @Getter ServiceInterfaceFactory serviceInterfaceFactory; - - @Autowired @Getter KubernetesV1MonitoringDaemonService monitoringDaemonService; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceProvider.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceProvider.java deleted file mode 100644 index c0852a9ad4..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1DistributedServiceProvider.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.core.RemoteAction; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedServiceProvider; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class KubernetesV1DistributedServiceProvider - extends DistributedServiceProvider { - @Autowired KubernetesV1ClouddriverBootstrapService clouddriverBootstrapService; - - @Autowired KubernetesV1ClouddriverService clouddriverService; - - @Autowired KubernetesV1DeckService deckService; - - @Autowired KubernetesV1EchoService echoService; - - @Autowired KubernetesV1FiatService fiatService; - - @Autowired KubernetesV1Front50Service front50Service; - - @Autowired KubernetesV1GateService gateService; - - @Autowired KubernetesV1IgorService igorService; - - @Autowired KubernetesV1KayentaService kayentaService; - - @Autowired KubernetesV1MonitoringDaemonService monitoringDaemonService; - - @Autowired KubernetesV1OrcaBootstrapService orcaBootstrapService; - - @Autowired KubernetesV1OrcaService orcaService; - - @Autowired KubernetesV1RedisBootstrapService redisBootstrapService; - - @Autowired KubernetesV1RedisService redisService; - - @Autowired KubernetesV1RoscoService roscoService; - - // For serialization - public KubernetesV1DistributedServiceProvider() {} - - @Override - public RemoteAction clean( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(details.getDeploymentConfiguration()); - KubernetesV1ProviderUtils.kubectlDeleteNamespaceCommand( - DaemonTaskHandler.getJobExecutor(), - details, - kubernetesSharedServiceSettings.getDeployLocation()); - return new RemoteAction(); - } -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1EchoService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1EchoService.java deleted file mode 100644 index b1dfcc0a48..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1EchoService.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.EchoService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1EchoService extends EchoService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1FiatService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1FiatService.java deleted file mode 100644 index 284c048746..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1FiatService.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.FiatService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1FiatService extends FiatService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(deploymentConfiguration.getSecurity().getAuthz().isEnabled()); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1Front50Service.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1Front50Service.java deleted file mode 100644 index 5d9cf284b4..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1Front50Service.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.Front50Service; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1Front50Service extends Front50Service - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public List getProfiles( - DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) { - List profiles = super.getProfiles(deploymentConfiguration, endpoints); - generateAwsProfile(deploymentConfiguration, endpoints, getRootHomeDirectory()) - .ifPresent(profiles::add); - generateAwsProfile(deploymentConfiguration, endpoints, getHomeDirectory()) - .ifPresent(profiles::add); - return profiles; - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(4); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1GateService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1GateService.java deleted file mode 100644 index 8220b2a775..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1GateService.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.GateService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1GateService extends GateService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(deploymentConfiguration.getSecurity().getApiSecurity()); - settings - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(kubernetesSharedServiceSettings.getDeployLocation()) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1IgorService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1IgorService.java deleted file mode 100644 index 207796fbe9..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1IgorService.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.IgorService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1IgorService extends IgorService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1KayentaService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1KayentaService.java deleted file mode 100644 index 0eb92ccf5a..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1KayentaService.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.profile.Profile; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.KayentaService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1KayentaService extends KayentaService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public List getProfiles( - DeploymentConfiguration deploymentConfiguration, SpinnakerRuntimeSettings endpoints) { - List profiles = super.getProfiles(deploymentConfiguration, endpoints); - generateAwsProfile(deploymentConfiguration, endpoints, getRootHomeDirectory()) - .ifPresent(profiles::add); - generateAwsProfile(deploymentConfiguration, endpoints, getHomeDirectory()) - .ifPresent(profiles::add); - return profiles; - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(deploymentConfiguration.getCanary().isEnabled()); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1MonitoringDaemonService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1MonitoringDaemonService.java deleted file mode 100644 index e3b7b33856..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1MonitoringDaemonService.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerMonitoringDaemonService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1MonitoringDaemonService extends SpinnakerMonitoringDaemonService - implements KubernetesService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - settings - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(kubernetesSharedServiceSettings.getDeployLocation()) - .setEnabled(deploymentConfiguration.getMetricStores().isEnabled()); - return settings; - } -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaBootstrapService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaBootstrapService.java deleted file mode 100644 index 77011c0506..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaBootstrapService.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.OrcaBootstrapService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.OrcaService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.ArrayList; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1OrcaBootstrapService extends OrcaBootstrapService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - List profiles = new ArrayList<>(); - profiles.add("bootstrap"); - profiles.add("bootstrap-local"); - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(profiles); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setMonitored(false) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(10); - final boolean requiredToBootstrap = true; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaService.java deleted file mode 100644 index 39ea1f15cc..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1OrcaService.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.OrcaService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1OrcaService extends OrcaService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(1); - final boolean requiredToBootstrap = false; - final boolean stateful = true; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ProviderUtils.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ProviderUtils.java deleted file mode 100644 index a3714b4dbc..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1ProviderUtils.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.clouddriver.kubernetes.v1.security.KubernetesConfigParser; -import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.core.error.v1.HalException; -import com.netflix.spinnaker.halyard.core.job.v1.JobExecutor; -import com.netflix.spinnaker.halyard.core.job.v1.JobRequest; -import com.netflix.spinnaker.halyard.core.job.v1.JobStatus; -import com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskInterrupted; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails; -import io.fabric8.kubernetes.api.model.NamespaceBuilder; -import io.fabric8.kubernetes.api.model.SecretBuilder; -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.DefaultKubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClient; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.Data; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.http.client.utils.URIBuilder; - -class KubernetesV1ProviderUtils { - // Map from deployment name -> the port & job managing the connection. - private static ConcurrentHashMap proxyMap = new ConcurrentHashMap<>(); - - @Data - static class Proxy { - String jobId; - Integer port; - - static String buildKey(String deployment) { - return String.format("%d:%s", Thread.currentThread().getId(), deployment); - } - } - - static URI proxyServiceEndpoint( - Proxy proxy, String namespace, String serviceName, int servicePort) { - try { - return new URIBuilder() - .setPort(proxy.getPort()) - .setHost("localhost") - .setScheme("http") - .setPath( - "/api/v1/namespaces/" - + namespace - + "/services/" - + serviceName - + ":" - + servicePort - + "/proxy") - .build(); - } catch (URISyntaxException e) { - throw new HalException(Severity.FATAL, "Malformed service details: " + e.getMessage()); - } - } - - static Proxy openProxy( - JobExecutor jobExecutor, AccountDeploymentDetails details) { - KubernetesAccount account = details.getAccount(); - Proxy proxy = proxyMap.getOrDefault(Proxy.buildKey(details.getDeploymentName()), new Proxy()); - String jobId = proxy.jobId; - if (StringUtils.isEmpty(jobId) || !jobExecutor.jobExists(jobId)) { - DaemonTaskHandler.newStage( - "Connecting to the Kubernetes cluster in account \"" + account.getName() + "\""); - List command = kubectlAccountCommand(details); - command.add("proxy"); - command.add("--port=0"); // select a random port - JobRequest request = new JobRequest().setTokenizedCommand(command); - - proxy.jobId = jobExecutor.startJob(request); - - JobStatus status = jobExecutor.updateJob(proxy.jobId); - - while (status == null) { - DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(2)); - status = jobExecutor.updateJob(proxy.jobId); - } - - // This should be a long-running job. - if (status.getState() == JobStatus.State.COMPLETED) { - throw new HalException( - Severity.FATAL, - "Unable to establish a proxy against account " - + account.getName() - + ":\n" - + status.getStdOut() - + "\n" - + status.getStdErr()); - } - - String connectionMessage = status.getStdOut(); - Pattern portPattern = Pattern.compile(":(\\d+)"); - Matcher matcher = portPattern.matcher(connectionMessage); - if (matcher.find()) { - proxy.setPort(Integer.valueOf(matcher.group(1))); - proxyMap.put(Proxy.buildKey(details.getDeploymentName()), proxy); - DaemonTaskHandler.message( - "Connected to kubernetes cluster for account " - + account.getName() - + " on port " - + proxy.getPort()); - DaemonTaskHandler.message( - "View the kube ui on http://localhost:" + proxy.getPort() + "/ui/"); - } else { - throw new HalException( - Severity.FATAL, - "Could not parse connection information from:\n" - + connectionMessage - + "(" - + status.getStdErr() - + ")"); - } - } - - return proxy; - } - - static KubernetesClient getClient(AccountDeploymentDetails details) { - KubernetesAccount account = details.getAccount(); - Config config = - KubernetesConfigParser.parse( - account.getKubeconfigFile(), - account.getContext(), - account.getCluster(), - account.getUser(), - account.getNamespaces(), - account.usesServiceAccount()); - - return new DefaultKubernetesClient(config); - } - - static void resize( - AccountDeploymentDetails details, - String namespace, - String replicaSetName, - int targetSize) { - KubernetesClient client = getClient(details); - client - .extensions() - .replicaSets() - .inNamespace(namespace) - .withName(replicaSetName) - .scale(targetSize); - } - - static void upsertSecret( - AccountDeploymentDetails details, - Set> files, - String secretName, - String namespace) { - KubernetesClient client = getClient(details); - - if (client.secrets().inNamespace(namespace).withName(secretName).get() != null) { - client.secrets().inNamespace(namespace).withName(secretName).delete(); - } - - Map secretContents = new HashMap<>(); - - files.forEach( - pair -> { - try { - File file = pair.getLeft(); - String name = pair.getRight(); - String data = - new String( - Base64.getEncoder().encode(IOUtils.toByteArray(new FileInputStream(file)))); - - secretContents.putIfAbsent(name, data); - } catch (IOException e) { - throw new HalException( - Severity.ERROR, "Unable to read contents of \"" + pair.getLeft() + "\": " + e); - } - }); - - SecretBuilder secretBuilder = new SecretBuilder(); - secretBuilder = - secretBuilder - .withNewMetadata() - .withName(secretName) - .withNamespace(namespace) - .endMetadata() - .withData(secretContents); - - client.secrets().inNamespace(namespace).create(secretBuilder.build()); - } - - static void createNamespace( - AccountDeploymentDetails details, String namespace) { - KubernetesClient client = getClient(details); - if (client.namespaces().withName(namespace).get() == null) { - client - .namespaces() - .create( - new NamespaceBuilder().withNewMetadata().withName(namespace).endMetadata().build()); - } - } - - static void deleteReplicaSet( - AccountDeploymentDetails details, String namespace, String name) { - getClient(details).extensions().replicaSets().inNamespace(namespace).withName(name).delete(); - } - - private static String halSecret(String name, Integer version, String component) { - return String.join("-", "hal", name, version + "", component); - } - - static String componentSecret(String name, Integer version) { - return halSecret(name, version, "profiles"); - } - - static String componentMonitoring(String name, Integer version) { - return halSecret(name, version, "monitoring"); - } - - static String componentRegistry(String name, Integer version) { - return halSecret(name, version, "registry"); - } - - static String componentDependencies(String name, Integer version) { - return halSecret(name, version, "dependencies"); - } - - static List kubectlPortForwardCommand( - AccountDeploymentDetails details, - String namespace, - String instance, - int targetPort, - int localPort) { - List command = kubectlAccountCommand(details); - command.add("--namespace"); - command.add(namespace); - - command.add("port-forward"); - command.add(instance); - - command.add(localPort + ":" + targetPort); - return command; - } - - static void kubectlDeleteNamespaceCommand( - JobExecutor jobExecutor, - AccountDeploymentDetails details, - String namespace) { - List command = kubectlAccountCommand(details); - command.add("delete"); - command.add("namespace"); - command.add(namespace); - JobRequest request = new JobRequest().setTokenizedCommand(command); - - try { - jobExecutor.backoffWait(jobExecutor.startJob(request)); - } catch (InterruptedException e) { - throw new DaemonTaskInterrupted(e); - } - } - - static void storeInstanceLogs( - JobExecutor jobExecutor, - AccountDeploymentDetails details, - String namespace, - String instanceName, - String containerName, - File outputFile) { - List command = kubectlAccountCommand(details); - command.add("--namespace"); - command.add(namespace); - command.add("logs"); - command.add(instanceName); - command.add(containerName); - - JobRequest request = new JobRequest().setTokenizedCommand(command); - - JobStatus status; - try { - status = jobExecutor.backoffWait(jobExecutor.startJob(request)); - } catch (InterruptedException e) { - throw new DaemonTaskInterrupted(e); - } - - try { - IOUtils.write( - status.getStdOut().getBytes(), new FileOutputStream(new File(outputFile, containerName))); - } catch (IOException e) { - throw new HalException(Severity.FATAL, "Unable to store logs: " + e.getMessage(), e); - } - } - - private static List kubectlAccountCommand( - AccountDeploymentDetails details) { - KubernetesAccount account = details.getAccount(); - List command = new ArrayList<>(); - command.add("kubectl"); - - String context = account.getContext(); - if (context != null && !context.isEmpty()) { - command.add("--context"); - command.add(context); - } - - String cluster = account.getCluster(); - if (cluster != null && !cluster.isEmpty()) { - command.add("--cluster"); - command.add(cluster); - } - - String user = account.getUser(); - if (user != null && !user.isEmpty()) { - command.add("--user"); - command.add(user); - } - - String kubeconfig = account.getKubeconfigFile(); - if (kubeconfig != null && !kubeconfig.isEmpty()) { - command.add("--kubeconfig"); - command.add(kubeconfig); - } - - return command; - } -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisBootstrapService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisBootstrapService.java deleted file mode 100644 index ce0f99860f..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisBootstrapService.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.RedisBootstrapService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import redis.clients.jedis.Jedis; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1RedisBootstrapService extends RedisBootstrapService - implements KubernetesV1DistributedService { - private static final String artifactId = "gcr.io/kubernetes-spinnaker/redis-cluster:v2"; - - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(artifactId) - .setLocation(location) - .setSafeToUpdate( - true) // It's OK to flush this redis fully since we generally redeploy bootstrap - // clouddriver & orca - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(20); - final boolean requiredToBootstrap = true; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisService.java deleted file mode 100644 index 57698342a5..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RedisService.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount; -import com.netflix.spinnaker.halyard.core.error.v1.HalException; -import com.netflix.spinnaker.halyard.core.job.v1.JobRequest; -import com.netflix.spinnaker.halyard.core.job.v1.JobStatus; -import com.netflix.spinnaker.halyard.core.problem.v1.Problem; -import com.netflix.spinnaker.halyard.core.tasks.v1.DaemonTaskHandler; -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.RedisService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import redis.clients.jedis.Jedis; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1RedisService extends RedisService - implements KubernetesV1DistributedService { - private static final String artifactId = "gcr.io/kubernetes-spinnaker/redis-cluster:v2"; - - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Jedis connectToPrimaryService( - AccountDeploymentDetails details, - SpinnakerRuntimeSettings runtimeSettings) { - ServiceSettings settings = runtimeSettings.getServiceSettings(this); - List command = - Arrays.stream(connectCommand(details, runtimeSettings).split(" ")) - .collect(Collectors.toList()); - JobRequest request = new JobRequest().setTokenizedCommand(command); - String jobId = getJobExecutor().startJob(request); - // Wait for the proxy to spin up. - - DaemonTaskHandler.safeSleep(TimeUnit.SECONDS.toMillis(5)); - - JobStatus status = getJobExecutor().updateJob(jobId); - - // This should be a long-running job. - if (status.getState() == JobStatus.State.COMPLETED) { - throw new HalException( - Problem.Severity.FATAL, - "Unable to establish a proxy against Redis:\n" - + status.getStdOut() - + "\n" - + status.getStdErr()); - } - - return new Jedis("localhost", settings.getPort()); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(artifactId) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(5); - final boolean requiredToBootstrap = false; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RoscoService.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RoscoService.java deleted file mode 100644 index 7db8876889..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/KubernetesV1RoscoService.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.HasServiceSettings; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.RoscoService; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedLogCollector; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.KubernetesSharedServiceSettings; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Delegate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@EqualsAndHashCode(callSuper = true) -@Component -@Data -public class KubernetesV1RoscoService extends RoscoService - implements KubernetesV1DistributedService { - @Delegate @Autowired KubernetesV1DistributedServiceDelegate distributedServiceDelegate; - - @Delegate(excludes = HasServiceSettings.class) - public DistributedLogCollector getLogCollector() { - return getLogCollectorFactory().build(this); - } - - @Override - public Settings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - KubernetesSharedServiceSettings kubernetesSharedServiceSettings = - new KubernetesSharedServiceSettings(deploymentConfiguration); - Settings settings = new Settings(); - String location = kubernetesSharedServiceSettings.getDeployLocation(); - settings - .setAddress(buildAddress(location)) - .setArtifactId(getArtifactId(deploymentConfiguration)) - .setLocation(location) - .setEnabled(true); - return settings; - } - - final DeployPriority deployPriority = new DeployPriority(0); - final boolean requiredToBootstrap = false; - final boolean stateful = true; -} diff --git a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/ResourceBuilder.java b/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/ResourceBuilder.java deleted file mode 100644 index 77b93531f1..0000000000 --- a/halyard-deploy/src/main/java/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/v1/ResourceBuilder.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2018 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1; - -import com.netflix.spinnaker.halyard.config.model.v1.node.CustomSizing; -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ConfigSource; -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings; -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.ContainerBuilder; -import io.fabric8.kubernetes.api.model.ContainerPortBuilder; -import io.fabric8.kubernetes.api.model.EnvVar; -import io.fabric8.kubernetes.api.model.EnvVarBuilder; -import io.fabric8.kubernetes.api.model.ProbeBuilder; -import io.fabric8.kubernetes.api.model.QuantityBuilder; -import io.fabric8.kubernetes.api.model.ResourceRequirements; -import io.fabric8.kubernetes.api.model.ResourceRequirementsBuilder; -import io.fabric8.kubernetes.api.model.VolumeMount; -import io.fabric8.kubernetes.api.model.VolumeMountBuilder; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; - -class ResourceBuilder { - static Container buildContainer( - String name, - ServiceSettings settings, - List configSources, - DeploymentEnvironment deploymentEnvironment) { - int port = settings.getPort(); - List envVars = - settings.getEnv().entrySet().stream() - .map( - e -> { - EnvVarBuilder envVarBuilder = new EnvVarBuilder(); - return envVarBuilder.withName(e.getKey()).withValue(e.getValue()).build(); - }) - .collect(Collectors.toList()); - - configSources.forEach( - c -> { - c.getEnv() - .entrySet() - .forEach( - envEntry -> { - EnvVarBuilder envVarBuilder = new EnvVarBuilder(); - envVars.add( - envVarBuilder - .withName(envEntry.getKey()) - .withValue(envEntry.getValue()) - .build()); - }); - }); - - String healthEndpoint = settings.getHealthEndpoint(); - String scheme = settings.getScheme(); - if (StringUtils.isNotEmpty(scheme)) { - scheme = scheme.toUpperCase(); - } else { - scheme = null; - } - - ProbeBuilder readinessProbeBuilder = buildProbeBuilder(port, scheme, healthEndpoint, null); - ProbeBuilder livenessProbeBuilder = null; - - DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig = - deploymentEnvironment.getLivenessProbeConfig(); - if (livenessProbeConfig != null - && livenessProbeConfig.isEnabled() - && livenessProbeConfig.getInitialDelaySeconds() != null) { - livenessProbeBuilder = - buildProbeBuilder( - port, scheme, healthEndpoint, livenessProbeConfig.getInitialDelaySeconds()); - } - - List volumeMounts = - configSources.stream() - .map( - c -> { - return new VolumeMountBuilder() - .withMountPath(c.getMountPath()) - .withName(c.getId()) - .build(); - }) - .collect(Collectors.toList()); - - ContainerBuilder containerBuilder = new ContainerBuilder(); - containerBuilder = - containerBuilder - .withName(name) - .withImage(settings.getArtifactId()) - .withPorts(new ContainerPortBuilder().withContainerPort(port).build()) - .withVolumeMounts(volumeMounts) - .withEnv(envVars) - .withReadinessProbe(readinessProbeBuilder.build()) - .withResources(buildResourceRequirements(name, deploymentEnvironment)); - - if (livenessProbeBuilder != null) { - containerBuilder.withLivenessProbe(livenessProbeBuilder.build()); - } - - return containerBuilder.build(); - } - - static ResourceRequirements buildResourceRequirements( - String serviceName, DeploymentEnvironment deploymentEnvironment) { - Map customSizing = deploymentEnvironment.getCustomSizing().get(serviceName); - - if (customSizing == null) { - return null; - } - - ResourceRequirementsBuilder resourceRequirementsBuilder = new ResourceRequirementsBuilder(); - if (customSizing.get("requests") != null) { - resourceRequirementsBuilder.addToRequests( - "memory", - new QuantityBuilder() - .withAmount(CustomSizing.stringOrNull(customSizing.get("requests").get("memory"))) - .build()); - resourceRequirementsBuilder.addToRequests( - "cpu", - new QuantityBuilder() - .withAmount(CustomSizing.stringOrNull(customSizing.get("requests").get("cpu"))) - .build()); - } - if (customSizing.get("limits") != null) { - resourceRequirementsBuilder.addToLimits( - "memory", - new QuantityBuilder() - .withAmount(CustomSizing.stringOrNull(customSizing.get("limits").get("memory"))) - .build()); - resourceRequirementsBuilder.addToLimits( - "cpu", - new QuantityBuilder() - .withAmount(CustomSizing.stringOrNull(customSizing.get("limits").get("cpu"))) - .build()); - } - - return resourceRequirementsBuilder.build(); - } - - private static ProbeBuilder buildProbeBuilder( - Integer port, String scheme, String healthEndpoint, Integer initialDelaySeconds) { - ProbeBuilder probeBuilder = new ProbeBuilder(); - if (healthEndpoint != null) { - return probeBuilder - .withNewHttpGet() - .withNewPort(port) - .withPath(healthEndpoint) - .withScheme(scheme) - .endHttpGet() - .withInitialDelaySeconds(initialDelaySeconds); - } else { - return probeBuilder - .withNewTcpSocket() - .withNewPort() - .withIntVal(port) - .endPort() - .endTcpSocket() - .withInitialDelaySeconds(initialDelaySeconds); - } - } -} diff --git a/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesV1DistributedServiceSpec.groovy b/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesV1DistributedServiceSpec.groovy deleted file mode 100644 index abcabad606..0000000000 --- a/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/KubernetesV1DistributedServiceSpec.groovy +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2017 Target, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes - -import com.fasterxml.jackson.databind.ObjectMapper -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.DeployKubernetesAtomicOperationDescription -import com.netflix.spinnaker.clouddriver.kubernetes.v1.deploy.description.servergroup.KubernetesContainerDescription -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment -import com.netflix.spinnaker.halyard.deploy.deployment.v1.AccountDeploymentDetails -import com.netflix.spinnaker.halyard.deploy.deployment.v1.DeploymentDetails -import com.netflix.spinnaker.halyard.deploy.services.v1.ArtifactService -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerArtifact -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.SpinnakerRuntimeSettings -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceInterfaceFactory -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.ServiceSettings -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerMonitoringDaemonService -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.SpinnakerService -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.DistributedService -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1.KubernetesV1DistributedService -import io.fabric8.kubernetes.api.model.LocalObjectReference -import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder -import spock.lang.Specification -import spock.lang.Unroll - -class KubernetesV1DistributedServiceSpec extends Specification { - - @Unroll() - def "applies request and limit overrides: #description"() { - setup: - KubernetesContainerDescription container = new KubernetesContainerDescription() - def service = createServiceTestDouble() - def deploymentEnvironment = new DeploymentEnvironment() - def kubernetesDescription = new DeployKubernetesAtomicOperationDescription() - deploymentEnvironment.customSizing["echo"] = new HashMap<>(requests: requests, limits: limits) - - when: - service.applyCustomSize(container, deploymentEnvironment, "echo", kubernetesDescription) - - then: - container.requests?.memory == requestsMemory - container.requests?.cpu == requestsCpu - container.limits?.memory == limitsMemory - container.limits?.cpu == limitsCpu - - where: - description | requests | limits | requestsMemory | requestsCpu | limitsMemory | limitsCpu - "all" | new HashMap<>(memory: "1Mi", cpu: "1m") | new HashMap<>(memory: "50Mi", cpu: "50m") | "1Mi" | "1m" | "50Mi" | "50m" - "only cpu" | new HashMap<>(cpu: "1m") | new HashMap<>(cpu: "50m") | null | "1m" | null | "50m" - "only mem" | new HashMap<>(memory: "1Mi") | new HashMap<>(memory: "50Mi" ) | "1Mi" | null | "50Mi" | null - "only reqs" | new HashMap<>(memory: "1Mi", cpu: "1m") | null | "1Mi" | "1m" | null | null - "only limits" | null | new HashMap<>(memory: "50Mi", cpu: "50m") | null | null | "50Mi" | "50m" - "integer values" | new HashMap<>(memory: 1, cpu: 2) | new HashMap<>(memory: 3, cpu: 4) | "1" | "2" | "3" | "4" - } - - def "adds no requests or limits when not specified"() { - setup: - KubernetesContainerDescription container = new KubernetesContainerDescription() - def service = createServiceTestDouble() - def deploymentEnvironment = new DeploymentEnvironment() - def kubernetesDescription = new DeployKubernetesAtomicOperationDescription() - - - when: - service.applyCustomSize(container, deploymentEnvironment, "echo", kubernetesDescription) - - then: - container.requests == null - container.limits == null - } - - def "no-ops when given null component"() { - setup: - KubernetesContainerDescription container = new KubernetesContainerDescription() - def service = createServiceTestDouble() - def requests = new HashMap<>(memory: "1Mi", cpu: "1m") - def limits = new HashMap<>(memory: "50Mi", cpu: "50m") - def deploymentEnvironment = new DeploymentEnvironment() - def kubernetesDescription = new DeployKubernetesAtomicOperationDescription() - deploymentEnvironment.customSizing["echo"] = new HashMap<>(requests: requests, limits: limits) - - when: - service.applyCustomSize(container, deploymentEnvironment, null, kubernetesDescription) - - then: - container.requests == null - container.limits == null - } - - @Unroll - def "applies replicaset sizes on 'orca-driven' deploy"() { - setup: - KubernetesContainerDescription container = new KubernetesContainerDescription() - def service = createServiceTestDouble() - def deploymentEnvironment = new DeploymentEnvironment() - def kubernetesDescription = new DeployKubernetesAtomicOperationDescription() - deploymentEnvironment.customSizing['echo'] = new HashMap<>('replicas': inputReplicas) - - when: - service.applyCustomSize(container, deploymentEnvironment, "echo", kubernetesDescription) - - then: - kubernetesDescription.getTargetSize() == expectedReplicas - - - where: - description | inputReplicas | expectedReplicas - "one replica specified" | 1 | 1 - "multiple replicas specified" | 2 | 2 - } - - @Unroll - def "applies replicaset sizes on 'manual' deploy"() { - setup: - def service = createServiceTestDouble() - ReplicaSetBuilder replicaSetBuilder = new ReplicaSetBuilder() - def deploymentEnvironment = new DeploymentEnvironment() - def componentSizing = deploymentEnvironment.customSizing['echo'] = new HashMap<>('replicas': inputReplicas) - - when: - replicaSetBuilder = replicaSetBuilder - .withNewSpec() - .withReplicas(service.retrieveKubernetesTargetSize(componentSizing)) - .endSpec() - def replicaSet = replicaSetBuilder.build() - - then: - replicaSet.spec.replicas == expectedReplicas - - where: - description | inputReplicas | expectedReplicas - "replica amount not specified" | null | 1 - "one replica specified" | 1 | 1 - "multiple replicas specified" | 2 | 2 - } - - def "retrieveKubernetesTargetSize return 1 when given null map"() { - setup: - def service = createServiceTestDouble() - def componentSizing = null - def replicas - - when: - replicas = service.retrieveKubernetesTargetSize(componentSizing) - - then: - replicas == 1 - } - - def "DeployKubernetesAtomicOperationDescription uses previously set replicaset size"(){ - setup: - def service = createServiceTestDouble() - DeployKubernetesAtomicOperationDescription kDescription = new DeployKubernetesAtomicOperationDescription() - kDescription.setTargetSize(expectedReplicas) - DeploymentEnvironment deploymentEnvironment = new DeploymentEnvironment() - deploymentEnvironment.customSizing["echo"] = componentSizing - - when: - service.applyCustomSize(new KubernetesContainerDescription(), deploymentEnvironment, "echo", kDescription) - - then: - kDescription.getTargetSize() == expectedReplicas - - where: - description | componentSizing | expectedReplicas - "componentSizing is null" | null | 3 - "replicas is null" | new HashMap<>() | 3 - } - - @Unroll - def "imagePullSecret is set on a replicaset"() { - setup: - ServiceSettings serviceSettings = new ServiceSettings() - def kubernetesSettings = serviceSettings.kubernetes - def service = createServiceTestDouble() - ReplicaSetBuilder replicaSetBuilder = new ReplicaSetBuilder() - - when: - kubernetesSettings.imagePullSecrets = pullSecrets - def imagePullSecrets = service.getImagePullSecrets(serviceSettings) - replicaSetBuilder = replicaSetBuilder - .withNewSpec() - .withNewTemplate() - .withNewSpec() - .withImagePullSecrets(imagePullSecrets) - .endSpec() - .endTemplate() - .endSpec() - def replicaSet = replicaSetBuilder.build() - - then: - replicaSet.spec.template.spec.imagePullSecrets == compiledPullSecret - - where: - description | pullSecrets | compiledPullSecret - "is null" | null | [] - "is empty" | [] | [] - "is one item" | ["item"] | [new LocalObjectReference("item")] - "is multiple items" | ["item1", "item2"] | [new LocalObjectReference("item1"), new LocalObjectReference("item2")] - } - - private KubernetesV1DistributedService createServiceTestDouble() { - new KubernetesV1DistributedService() { - @Override - String getDockerRegistry(String deploymentName, SpinnakerArtifact artifact) { - return null - } - - @Override - ArtifactService getArtifactService() { - return null - } - - @Override - ServiceInterfaceFactory getServiceInterfaceFactory() { - return null - } - - @Override - ObjectMapper getObjectMapper() { - return null - } - - void collectLogs(DeploymentDetails details, SpinnakerRuntimeSettings runtimeSettings) { - - } - - @Override - String getSpinnakerStagingPath(String deploymentName) { - return null - } - - @Override - String getServiceName() { - return null - } - - @Override - String getCanonicalName() { - return null - } - - @Override - SpinnakerMonitoringDaemonService getMonitoringDaemonService() { - return null - } - - @Override - Object connectToService(AccountDeploymentDetails details, SpinnakerRuntimeSettings runtimeSettings, SpinnakerService sidecar) { - return null - } - - @Override - Object connectToInstance(AccountDeploymentDetails details, SpinnakerRuntimeSettings runtimeSettings, SpinnakerService sidecar, String instanceId) { - return null - } - - @Override - boolean isRequiredToBootstrap() { - return false - } - - @Override - DistributedService.DeployPriority getDeployPriority() { - return null - } - - @Override - SpinnakerService getService() { - return null - } - - @Override - ServiceSettings buildServiceSettings(DeploymentConfiguration deploymentConfiguration) { - return null - } - - @Override - ServiceSettings getDefaultServiceSettings(DeploymentConfiguration deploymentConfiguration) { - return null - } - - @Override - SpinnakerArtifact getArtifact() { - return null - } - } - } -} diff --git a/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/ResourceBuilderSpec.groovy b/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/ResourceBuilderSpec.groovy deleted file mode 100644 index 351b9352d7..0000000000 --- a/halyard-deploy/src/test/groovy/com/netflix/spinnaker/halyard/deploy/spinnaker/v1/service/distributed/kubernetes/ResourceBuilderSpec.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017 Target, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes - -import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment -import com.netflix.spinnaker.halyard.deploy.spinnaker.v1.service.distributed.kubernetes.v1.ResourceBuilder -import spock.lang.Specification -import spock.lang.Unroll - -@Unroll -class ResourceBuilderSpec extends Specification { - def "adds requests and limits - #description"() { - given: - def builder = new ResourceBuilder() - def deploymentEnvironment = new DeploymentEnvironment() - deploymentEnvironment.customSizing["echo"] = new HashMap<>(requests: requests, limits: limits) - - when: - def builtRequirements = builder.buildResourceRequirements("echo", deploymentEnvironment) - - then: - builtRequirements.requests.get("memory")?.amount == requestsMemory - builtRequirements.requests.get("cpu")?.amount == requestsCpu - builtRequirements.limits.get("memory")?.amount == limitsMemory - builtRequirements.limits.get("cpu")?.amount == limitsCpu - - where: - description | requests | limits | requestsMemory | requestsCpu | limitsMemory | limitsCpu - "all" | new HashMap<>(memory: "1Mi", cpu: "1m") | new HashMap<>(memory: "50Mi", cpu: "50m") | "1Mi" | "1m" | "50Mi" | "50m" - "only cpu" | new HashMap<>(cpu: "1m") | new HashMap<>(cpu: "50m") | null | "1m" | null | "50m" - "only mem" | new HashMap<>(memory: "1Mi") | new HashMap<>(memory: "50Mi" ) | "1Mi" | null | "50Mi" | null - "only reqs" | new HashMap<>(memory: "1Mi", cpu: "1m") | null | "1Mi" | "1m" | null | null - "only limits" | null | new HashMap<>(memory: "50Mi", cpu: "50m") | null | null | "50Mi" | "50m" - "integer values" | new HashMap<>(memory: 1, cpu: 2) | new HashMap<>(memory: 3, cpu: 4) | "1" | "2" | "3" | "4" - } - - def "adds no requests or limits when not specified"() { - given: - def builder = new ResourceBuilder() - def deploymentEnvironment = new DeploymentEnvironment() - - when: - def builtRequirements = builder.buildResourceRequirements("echo", deploymentEnvironment) - - then: - builtRequirements == null - } - - def "noops when given null component"() { - given: - def builder = new ResourceBuilder() - def requests = new HashMap<>(memory: "1Mi", cpu: "1m") - def limits = new HashMap<>(memory: "50Mi", cpu: "50m") - def deploymentEnvironment = new DeploymentEnvironment() - deploymentEnvironment.customSizing["echo"] = new HashMap<>(requests: requests, limits: limits) - - when: - def builtRequirements = builder.buildResourceRequirements(null, deploymentEnvironment) - - then: - builtRequirements == null - } -}