Java tutorial
/* * Copyright 2017 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.profile; import com.amazonaws.util.IOUtils; import com.fasterxml.jackson.databind.ObjectMapper; import com.netflix.spinnaker.halyard.config.config.v1.HalconfigParser; 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.problem.v1.ConfigProblemBuilder; import com.netflix.spinnaker.halyard.config.services.v1.DeploymentService; import com.netflix.spinnaker.halyard.core.error.v1.HalException; import com.netflix.spinnaker.halyard.core.problem.v1.ProblemBuilder; import com.netflix.spinnaker.halyard.core.registry.v1.ProfileRegistry; 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.SpinnakerEndpoints; import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.Yaml; import retrofit.RetrofitError; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Collectors; import static com.netflix.spinnaker.halyard.core.problem.v1.Problem.Severity.FATAL; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; /** * A profile is a specialization of an artifact by means of feature flipping in .js and .yml * files. */ abstract public class SpinnakerProfile { @Autowired HalconfigParser parser; @Autowired Yaml yamlParser; @Autowired ObjectMapper objectMapper; @Autowired String spinnakerOutputDependencyPath; @Autowired DeploymentService deploymentService; @Autowired ProfileRegistry profileRegistry; @Autowired ArtifactService artifactService; final String EDIT_WARNING = commentPrefix() + "WARNING\n" + commentPrefix() + "This file was autogenerated, and _will_ be overwritten by Halyard.\n" + commentPrefix() + "Any edits you make here _will_ be lost.\n"; String yamlToString(Object o) { return yamlParser.dump(objectMapper.convertValue(o, Map.class)); } protected abstract String commentPrefix(); public abstract SpinnakerArtifact getArtifact(); public ProfileConfig getFullConfig(String deploymentName, SpinnakerEndpoints endpoints) { DeploymentConfiguration deploymentConfiguration = deploymentService .getDeploymentConfiguration(deploymentName); ProfileConfig result = generateFullConfig(getBaseConfig(deploymentConfiguration), deploymentConfiguration, endpoints); result.setConfig(result.getPrimaryConfigFile(), EDIT_WARNING + result.getPrimaryConfigContents()); return result; } public abstract String getProfileFileName(); /** * Overwrite this for components that need to specialize their config. * * @param config the base halconfig returned from the config storage. * @param deploymentConfiguration the deployment configuration being translated into Spinnaker config. * @param endpoints are the endpoints spinnaker will be running at. * @return the fully written configuration. */ protected ProfileConfig generateFullConfig(ProfileConfig config, DeploymentConfiguration deploymentConfiguration, SpinnakerEndpoints endpoints) { return config; } /** * @return the base config (typically found in a profile's ./halconfig/ directory) for * the version of the profile specified by the Spinnaker version in the loaded halconfig. */ private ProfileConfig getBaseConfig(DeploymentConfiguration deploymentConfiguration) { try { String componentVersion = artifactService.getArtifactVersion(deploymentConfiguration.getName(), getArtifact()); String componentObjectName = ProfileRegistry.profilePath(getArtifact().getName(), componentVersion, getProfileFileName()); return new ProfileConfig().setPrimaryConfigFile(getProfileFileName()) .extendConfig(getProfileFileName(), IOUtils.toString(profileRegistry.getObjectContents(componentObjectName))) .setVersion(componentVersion); } catch (RetrofitError | IOException e) { throw new HalException(new ConfigProblemBuilder(FATAL, "Unable to retrieve a profile for \"" + getArtifact().getName() + "\": " + e.getMessage()) .build()); } } /** * @param node is the node to find required files in. * @return the list of files required by the node to function. */ List<String> processRequiredFiles(Node node) { List<String> files = new ArrayList<>(); Consumer<Node> fileFinder = n -> files.addAll(n.localFiles().stream().map(f -> { try { f.setAccessible(true); String fPath = (String) f.get(n); if (fPath == null) { return null; } File fFile = new File(fPath); String fName = fFile.getName(); // Hash the path to uniquely flatten all files into the output directory Path newName = Paths.get(spinnakerOutputDependencyPath, Math.abs(fPath.hashCode()) + "-" + fName); File parent = newName.toFile().getParentFile(); if (!parent.exists()) { parent.mkdirs(); } else if (fFile.getParent().equals(parent.toString())) { // Don't move paths that are already in the right folder return fPath; } Files.copy(Paths.get(fPath), newName, REPLACE_EXISTING); f.set(n, newName.toString()); return newName.toString(); } catch (IllegalAccessException e) { throw new RuntimeException("Failed to get local files for node " + n.getNodeName(), e); } catch (IOException e) { throw new HalException( new ProblemBuilder(FATAL, "Failed to backup user file: " + e.getMessage()).build()); } finally { f.setAccessible(false); } }).filter(Objects::nonNull).collect(Collectors.toList())); node.recursiveConsume(fileFinder); return files; } }