forked from spinnaker/orca
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(codebuild): Add AWS CodeBuild stage (spinnaker#3386)
* feat(codebuild): Add AWS CodeBuild stage * Fix broken test Co-authored-by: Clare Liguori <[email protected]>
- Loading branch information
1 parent
7bde8eb
commit 5b0731b
Showing
9 changed files
with
471 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/model/AwsCodeBuildExecution.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.model; | ||
|
||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.netflix.spinnaker.orca.ExecutionStatus; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
|
||
@Data | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public class AwsCodeBuildExecution { | ||
private final String arn; | ||
private final Status status; | ||
private final AwsCodeBuildLogs logs; | ||
private final String buildUrl; | ||
|
||
@JsonCreator | ||
public AwsCodeBuildExecution( | ||
@JsonProperty("arn") String arn, | ||
@JsonProperty("buildStatus") String buildStatus, | ||
@JsonProperty("logs") AwsCodeBuildLogs logs) { | ||
this.arn = arn; | ||
this.status = Status.fromString(buildStatus); | ||
this.buildUrl = getBuildUrl(arn); | ||
this.logs = logs; | ||
} | ||
|
||
private String getBuildUrl(String arn) { | ||
final String[] arnSplit = arn.split("/"); | ||
final String region = arnSplit[0].split(":")[3]; | ||
final String buildId = arnSplit[1]; | ||
final String project = buildId.split(":")[0]; | ||
return String.format( | ||
"https://%s.console.aws.amazon.com/codesuite/codebuild/projects/%s/build/%s/log?region=%s", | ||
region, project, buildId, region); | ||
} | ||
|
||
@Data | ||
private static class AwsCodeBuildLogs { | ||
private String deepLink; | ||
private String s3DeepLink; | ||
} | ||
|
||
public enum Status { | ||
IN_PROGRESS(ExecutionStatus.RUNNING), | ||
SUCCEEDED(ExecutionStatus.SUCCEEDED), | ||
FAILED(ExecutionStatus.TERMINAL), | ||
FAULT(ExecutionStatus.TERMINAL), | ||
TIMED_OUT(ExecutionStatus.TERMINAL), | ||
STOPPED(ExecutionStatus.CANCELED), | ||
UNKNOWN(ExecutionStatus.TERMINAL); | ||
|
||
@Getter private ExecutionStatus executionStatus; | ||
|
||
Status(ExecutionStatus executionStatus) { | ||
this.executionStatus = executionStatus; | ||
} | ||
|
||
public static Status fromString(String status) { | ||
try { | ||
return valueOf(status); | ||
} catch (NullPointerException | IllegalArgumentException e) { | ||
return UNKNOWN; | ||
} | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...or/src/main/groovy/com/netflix/spinnaker/orca/igor/model/AwsCodeBuildStageDefinition.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.model; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
public class AwsCodeBuildStageDefinition implements RetryableStageDefinition { | ||
private String account; | ||
private String projectName; | ||
private AwsCodeBuildExecution buildInfo; | ||
private int consecutiveErrors; | ||
} |
38 changes: 38 additions & 0 deletions
38
orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/pipeline/AwsCodeBuildStage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.pipeline; | ||
|
||
import com.netflix.spinnaker.orca.igor.tasks.MonitorAwsCodeBuildTask; | ||
import com.netflix.spinnaker.orca.igor.tasks.StartAwsCodeBuildTask; | ||
import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder; | ||
import com.netflix.spinnaker.orca.pipeline.TaskNode; | ||
import com.netflix.spinnaker.orca.pipeline.model.Stage; | ||
import javax.annotation.Nonnull; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class AwsCodeBuildStage implements StageDefinitionBuilder { | ||
@Override | ||
public void taskGraph(@Nonnull Stage stage, @Nonnull TaskNode.Builder builder) { | ||
builder | ||
.withTask("startAwsCodeBuildTask", StartAwsCodeBuildTask.class) | ||
.withTask("monitorAwsCodeBuildTask", MonitorAwsCodeBuildTask.class); | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/MonitorAwsCodeBuildTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.tasks; | ||
|
||
import com.netflix.spinnaker.orca.OverridableTimeoutRetryableTask; | ||
import com.netflix.spinnaker.orca.TaskResult; | ||
import com.netflix.spinnaker.orca.igor.IgorService; | ||
import com.netflix.spinnaker.orca.igor.model.AwsCodeBuildExecution; | ||
import com.netflix.spinnaker.orca.igor.model.AwsCodeBuildStageDefinition; | ||
import com.netflix.spinnaker.orca.pipeline.model.Stage; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.concurrent.TimeUnit; | ||
import javax.annotation.Nonnull; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class MonitorAwsCodeBuildTask extends RetryableIgorTask<AwsCodeBuildStageDefinition> | ||
implements OverridableTimeoutRetryableTask { | ||
@Getter protected long backoffPeriod = TimeUnit.SECONDS.toMillis(10); | ||
@Getter protected long timeout = TimeUnit.HOURS.toMillis(8); // maximum build timeout | ||
|
||
private final IgorService igorService; | ||
|
||
@Override | ||
@Nonnull | ||
public TaskResult tryExecute(@Nonnull AwsCodeBuildStageDefinition stageDefinition) { | ||
AwsCodeBuildExecution execution = | ||
igorService.getAwsCodeBuildExecution( | ||
stageDefinition.getAccount(), getBuildId(stageDefinition.getBuildInfo().getArn())); | ||
Map<String, Object> context = new HashMap<>(); | ||
context.put("buildInfo", execution); | ||
return TaskResult.builder(execution.getStatus().getExecutionStatus()).context(context).build(); | ||
} | ||
|
||
@Override | ||
@Nonnull | ||
protected AwsCodeBuildStageDefinition mapStage(@Nonnull Stage stage) { | ||
return stage.mapTo(AwsCodeBuildStageDefinition.class); | ||
} | ||
|
||
private String getBuildId(String arn) { | ||
return arn.split("/")[1]; | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
orca-igor/src/main/groovy/com/netflix/spinnaker/orca/igor/tasks/StartAwsCodeBuildTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.tasks; | ||
|
||
import com.netflix.spinnaker.orca.ExecutionStatus; | ||
import com.netflix.spinnaker.orca.Task; | ||
import com.netflix.spinnaker.orca.TaskResult; | ||
import com.netflix.spinnaker.orca.igor.IgorService; | ||
import com.netflix.spinnaker.orca.igor.model.AwsCodeBuildExecution; | ||
import com.netflix.spinnaker.orca.igor.model.AwsCodeBuildStageDefinition; | ||
import com.netflix.spinnaker.orca.pipeline.model.Stage; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import javax.annotation.Nonnull; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class StartAwsCodeBuildTask implements Task { | ||
private static final String PROJECT_NAME = "projectName"; | ||
|
||
private final IgorService igorService; | ||
|
||
@Override | ||
@Nonnull | ||
public TaskResult execute(@Nonnull Stage stage) { | ||
AwsCodeBuildStageDefinition stageDefinition = stage.mapTo(AwsCodeBuildStageDefinition.class); | ||
|
||
Map<String, Object> requestInput = new HashMap<>(); | ||
requestInput.put(PROJECT_NAME, stageDefinition.getProjectName()); | ||
|
||
AwsCodeBuildExecution execution = | ||
igorService.startAwsCodeBuild(stageDefinition.getAccount(), requestInput); | ||
|
||
Map<String, Object> context = stage.getContext(); | ||
context.put("buildInfo", execution); | ||
return TaskResult.builder(ExecutionStatus.SUCCEEDED).context(context).build(); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...gor/src/test/groovy/com/netflix/spinnaker/orca/igor/pipeline/AwsCodeBuildStageSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright 2020 Amazon.com, 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.orca.igor.pipeline | ||
|
||
import com.netflix.spinnaker.orca.igor.tasks.StartAwsCodeBuildTask | ||
import spock.lang.Specification | ||
|
||
import static com.netflix.spinnaker.orca.test.model.ExecutionBuilder.stage | ||
|
||
class AwsCodeBuildStageSpec extends Specification { | ||
def ACCOUNT = "codebuild-account" | ||
def PROJECT_NAME = "test" | ||
|
||
def "should start a build"() { | ||
given: | ||
def awsCodeBuildStage = new AwsCodeBuildStage() | ||
|
||
def stage = stage { | ||
type = "awsCodeBuild" | ||
context = [ | ||
account: ACCOUNT, | ||
projectName: PROJECT_NAME, | ||
] | ||
} | ||
|
||
when: | ||
def tasks = awsCodeBuildStage.buildTaskGraph(stage) | ||
|
||
then: | ||
tasks.findAll { | ||
it.implementingClass == StartAwsCodeBuildTask | ||
}.size() == 1 | ||
} | ||
} |
Oops, something went wrong.