diff --git a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/Front50Service.groovy b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/Front50Service.groovy index acb0d27204..93543e92b2 100644 --- a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/Front50Service.groovy +++ b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/Front50Service.groovy @@ -16,6 +16,7 @@ package com.netflix.spinnaker.orca.front50 import com.netflix.spinnaker.fiat.model.resources.ServiceAccount +import com.netflix.spinnaker.kork.plugins.update.release.PluginInfoRelease import com.netflix.spinnaker.orca.front50.model.Application import com.netflix.spinnaker.orca.front50.model.ApplicationNotifications import com.netflix.spinnaker.orca.front50.model.DeliveryConfig @@ -52,8 +53,11 @@ interface Front50Service { @POST("/pluginInfo") PluginInfo upsertPluginInfo(@Body PluginInfo pluginInfo) - @DELETE("/pluginInfo/{pluginInfoId}") - Response deletePluginInfo(@Path("pluginInfoId") String pluginInfoId) + @DELETE("/pluginInfo/{pluginId}") + Response deletePluginInfo(@Path("pluginId") String pluginId) + + @PUT("/pluginInfo/{pluginId}/releases/{version}") + Response setPreferredPluginVersion(@Path("pluginId") String pluginId, @Path("version") String version) @GET("/pipelines/{applicationName}") List> getPipelines(@Path("applicationName") String applicationName) diff --git a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/pipeline/SetPreferredPluginReleaseStage.java b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/pipeline/SetPreferredPluginReleaseStage.java new file mode 100644 index 0000000000..831de29358 --- /dev/null +++ b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/pipeline/SetPreferredPluginReleaseStage.java @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Netflix, 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.front50.pipeline; + +import com.netflix.spinnaker.orca.api.pipeline.graph.StageDefinitionBuilder; +import com.netflix.spinnaker.orca.api.pipeline.graph.TaskNode; +import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; +import com.netflix.spinnaker.orca.front50.tasks.SetPreferredPluginReleaseTask; +import javax.annotation.Nonnull; +import org.springframework.stereotype.Component; + +@Component +public class SetPreferredPluginReleaseStage implements StageDefinitionBuilder { + + @Override + public void taskGraph(@Nonnull StageExecution stage, @Nonnull TaskNode.Builder builder) { + builder.withTask("setPreferredPluginVersion", SetPreferredPluginReleaseTask.class); + } +} diff --git a/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTask.java b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTask.java new file mode 100644 index 0000000000..4beb076acb --- /dev/null +++ b/orca-front50/src/main/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTask.java @@ -0,0 +1,68 @@ +/* + * Copyright 2020 Netflix, 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.front50.tasks; + +import com.netflix.spinnaker.orca.api.pipeline.RetryableTask; +import com.netflix.spinnaker.orca.api.pipeline.TaskResult; +import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; +import com.netflix.spinnaker.orca.front50.Front50Service; +import java.time.Duration; +import java.util.Objects; +import javax.annotation.Nonnull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class SetPreferredPluginReleaseTask implements RetryableTask { + + private static final Logger log = LoggerFactory.getLogger(SetPreferredPluginReleaseTask.class); + + private final Front50Service front50Service; + + public SetPreferredPluginReleaseTask(Front50Service front50Service) { + this.front50Service = front50Service; + } + + @Nonnull + @Override + public TaskResult execute(@Nonnull StageExecution stage) { + final String pluginId = (String) stage.getContext().get("pluginId"); + final String version = (String) stage.getContext().get("preferredVersion"); + + Objects.requireNonNull(pluginId); + Objects.requireNonNull(version); + + try { + front50Service.setPreferredPluginVersion(pluginId, version); + } catch (Exception e) { + log.error("Failed setting preferred plugin version '{}' to '{}'", pluginId, version, e); + return TaskResult.RUNNING; + } + + return TaskResult.SUCCEEDED; + } + + @Override + public long getBackoffPeriod() { + return Duration.ofSeconds(10).toMillis(); + } + + @Override + public long getTimeout() { + return Duration.ofMinutes(2).toMillis(); + } +} diff --git a/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTaskSpec.groovy b/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTaskSpec.groovy new file mode 100644 index 0000000000..caa0690a0f --- /dev/null +++ b/orca-front50/src/test/groovy/com/netflix/spinnaker/orca/front50/tasks/SetPreferredPluginReleaseTaskSpec.groovy @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Netflix, 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.front50.tasks + +import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus +import com.netflix.spinnaker.orca.front50.Front50Service +import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl +import spock.lang.Specification +import spock.lang.Subject + +import static com.netflix.spinnaker.orca.test.model.ExecutionBuilder.stage + +class SetPreferredPluginReleaseTaskSpec extends Specification { + + Front50Service front50Service = Mock() + + @Subject + SetPreferredPluginReleaseTask subject = new SetPreferredPluginReleaseTask(front50Service) + + def "should call front50"() { + given: + StageExecutionImpl stageExecution = stage { + type = "whatever" + context = [ + "pluginId": "netflix.foo", + "preferredVersion": "1.0.1" + ] + } + + when: + def result = subject.execute(stageExecution) + + then: + result.status == ExecutionStatus.SUCCEEDED + 1 * front50Service.setPreferredPluginVersion("netflix.foo", "1.0.1") + } +}