Skip to content

Commit

Permalink
feat(bake/artifacts): Pass artifacts to packer (#253)
Browse files Browse the repository at this point in the history
Updates the rosco bake endpoint to accept a list of artifacts
and passes these artifacts to packer.  Packer does not yet
consume these artifacts, which will be implemented in a later
pull request.
  • Loading branch information
ezimanyi committed Apr 27, 2018
1 parent bddfd19 commit 4d90fc7
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 13 deletions.
Expand Up @@ -18,6 +18,7 @@ package com.netflix.spinnaker.rosco.api

import com.fasterxml.jackson.annotation.JsonProperty
import com.google.gson.annotations.SerializedName
import com.netflix.spinnaker.kork.artifacts.model.Artifact
import com.netflix.spinnaker.rosco.providers.util.PackageUtil
import com.netflix.spinnaker.rosco.providers.util.packagespecific.DebPackageUtil
import com.netflix.spinnaker.rosco.providers.util.packagespecific.NupkgPackageUtil
Expand All @@ -39,8 +40,10 @@ class BakeRequest {
@ApiModelProperty(value = "A generated UUID which will be used to identify the effective packer bake", readOnly = true)
final String request_id = UUID.randomUUID().toString()
String user
@ApiModelProperty("The package(s) to install") @JsonProperty("package") @SerializedName("package")
@ApiModelProperty("The package(s) to install, as a space-delimited string") @JsonProperty("package") @SerializedName("package")
String package_name
@ApiModelProperty("The package(s) to install, as Spinnaker artifacts")
List<Artifact> package_artifacts
@ApiModelProperty("The CI server")
String build_host
@ApiModelProperty("The CI job")
Expand Down
Expand Up @@ -209,6 +209,7 @@ class BakePoller implements ApplicationListener<ContextRefreshedEvent> {

if (cloudProviderBakeHandler) {
String region = bakeStore.retrieveRegionById(bakeId)
cloudProviderBakeHandler.deleteArtifactFile(bakeId)

if (region) {
Bake bakeDetails = cloudProviderBakeHandler.scrapeCompletedBakeResults(region, bakeId, logsContent)
Expand Down
Expand Up @@ -130,6 +130,13 @@ abstract class CloudProviderBakeHandler {
return bakeDetails.ami ?: bakeDetails.image_name
}

/**
* Deletes the temporary file containing artifacts to bake into the image. Currently only GCE
* supports baking artifacts, so this defaults to a no-op.
*/
void deleteArtifactFile(String bakeId) {
}

/**
* Finds the appropriate virtualization settings in this provider's configuration based on the region and
* bake request parameters. Throws an IllegalArgumentException if the virtualization settings cannot be
Expand Down
Expand Up @@ -22,6 +22,7 @@ import com.netflix.spinnaker.rosco.api.BakeRequest
import com.netflix.spinnaker.rosco.providers.CloudProviderBakeHandler
import com.netflix.spinnaker.rosco.providers.google.config.RoscoGoogleConfiguration
import com.netflix.spinnaker.rosco.providers.util.ImageNameFactory
import com.netflix.spinnaker.rosco.providers.util.PackerArtifactService
import com.netflix.spinnaker.rosco.providers.util.PackerManifest
import com.netflix.spinnaker.rosco.providers.util.PackerManifestService
import groovy.util.logging.Slf4j
Expand All @@ -38,6 +39,8 @@ public class GCEBakeHandler extends CloudProviderBakeHandler {

ImageNameFactory imageNameFactory = new ImageNameFactory()

PackerArtifactService packerArtifactService = new PackerArtifactService()

PackerManifestService packerManifestService = new PackerManifestService()

@Autowired
Expand Down Expand Up @@ -143,11 +146,18 @@ public class GCEBakeHandler extends CloudProviderBakeHandler {
parameterMap.appversion = appVersionStr
}

parameterMap.artifactFile = packerArtifactService.writeArtifactsToFile(bakeRequest.request_id, bakeRequest.package_artifacts)?.toString()

parameterMap.manifestFile = packerManifestService.getManifestFileName(bakeRequest.request_id)

return parameterMap
}

@Override
void deleteArtifactFile(String bakeId) {
packerArtifactService.deleteArtifactFile(bakeId)
}

@Override
String getTemplateFileName(BakeOptions.BaseImage baseImage) {
return baseImage.templateFile ?: bakeryDefaults?.templateFile
Expand Down
@@ -0,0 +1,77 @@
/*
* 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.rosco.providers.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.spinnaker.kork.artifacts.model.Artifact;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

public class PackerArtifactService {

private Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));
private ObjectMapper objectMapper = new ObjectMapper();

public PackerArtifactService() throws IOException {
if (!Files.isDirectory(tempDir)) {
Files.createDirectories(tempDir);
}
}

public Path writeArtifactsToFile(String bakeId, List<Artifact> artifacts) {
Path artifactFile = getArtifactFilePath(bakeId);

// If we were not passed any artifacts at all, write an empty array to the file rather
// than null
if (artifacts == null) {
artifacts = new ArrayList<>();
}

try (
BufferedOutputStream artifactStream =
new BufferedOutputStream(
Files.newOutputStream(artifactFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE)
)
) {
objectMapper.writeValue(artifactStream, artifacts);
} catch (IOException e) {
throw new IllegalStateException("Could not write artifacts to file: " + e.getMessage());
}

return artifactFile;
}

public void deleteArtifactFile(String bakeId) {
Path artifactFile = getArtifactFilePath(bakeId);

try {
Files.deleteIfExists(artifactFile);
} catch (IOException e) {
throw new IllegalStateException("Could not delete artifact file: " + e.getMessage());
}
}

private Path getArtifactFilePath(String bakeId) {
return tempDir.resolve(bakeId + "-artifacts.json");
}
}

0 comments on commit 4d90fc7

Please sign in to comment.