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 - } -}