Skip to content

Commit

Permalink
feat(tencentcloud): Add tecentcloud stages and tasks (spinnaker#3486)
Browse files Browse the repository at this point in the history
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
shengyu and mergify[bot] authored Mar 25, 2020
1 parent 8365e64 commit c50372f
Show file tree
Hide file tree
Showing 9 changed files with 373 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ trait ApplicationNameValidator {
// (e.g. if the length of the app name prevents creating load balancers in AWS) so we
// just validate the characters and name length.
Map<String, NameConstraint> cloudProviderNameConstraints = [
'appengine' : new NameConstraint(58, '^[a-z0-9]*$'),
'aws' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$'),
'dcos' : new NameConstraint(127, '^[a-z0-9]*$'),
'gce' : new NameConstraint(63, '^([a-zA-Z][a-zA-Z0-9]*)?$'),
'kubernetes': new NameConstraint(63, '^([a-zA-Z][a-zA-Z0-9-]*)$'),
'openstack' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$'),
'titus' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$')
'appengine' : new NameConstraint(58, '^[a-z0-9]*$'),
'aws' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$'),
'dcos' : new NameConstraint(127, '^[a-z0-9]*$'),
'gce' : new NameConstraint(63, '^([a-zA-Z][a-zA-Z0-9]*)?$'),
'kubernetes' : new NameConstraint(63, '^([a-zA-Z][a-zA-Z0-9-]*)$'),
'openstack' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$'),
'titus' : new NameConstraint(250, '^[a-zA-Z_0-9.]*$'),
'tencentcloud': new NameConstraint(50, '^[a-zA-Z_0-9.\u4e00-\u9fa5-]*$')
]

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class BakeRequest {
}

static enum CloudProviderType {
aws, azure, docker, gce, openstack, titus, oracle, alicloud, huaweicloud
aws, azure, docker, gce, openstack, titus, oracle, alicloud, huaweicloud, tencentcloud
}

static enum VmType {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2019 THL A29 Limited, a Tencent company.
*
* 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.clouddriver.pipeline.providers.tencentcloud;

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.clouddriver.tasks.MonitorKatoTask;
import com.netflix.spinnaker.orca.clouddriver.tasks.servergroup.ServerGroupCacheForceRefreshTask;
import javax.annotation.Nonnull;
import org.springframework.stereotype.Component;

@Component
public class DeleteTencentCloudScheduledActionStage implements StageDefinitionBuilder {

@Override
public void taskGraph(@Nonnull StageExecution stage, @Nonnull TaskNode.Builder builder) {
builder
.withTask("deleteTencentCloudScheduledAction", DeleteTencentCloudScheduledActionTask.class)
.withTask("monitorUpsert", MonitorKatoTask.class)
.withTask("forceCacheRefresh", ServerGroupCacheForceRefreshTask.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2019 THL A29 Limited, a Tencent company.
*
* 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.clouddriver.pipeline.providers.tencentcloud;

import com.netflix.spinnaker.orca.api.pipeline.Task;
import com.netflix.spinnaker.orca.api.pipeline.TaskResult;
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus;
import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution;
import com.netflix.spinnaker.orca.clouddriver.KatoService;
import com.netflix.spinnaker.orca.clouddriver.model.TaskId;
import com.netflix.spinnaker.orca.kato.pipeline.support.AsgDescriptionSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DeleteTencentCloudScheduledActionTask implements Task {

@Override
public TaskResult execute(StageExecution stage) {
Map<String, Map> map = new HashMap<>();
map.put("deleteTencentCloudScheduledActionDescription", stage.getContext());
Collection<Map<String, Map>> ops = new ArrayList<>();
ops.add(map);
TaskId taskId = kato.requestOperations(ops).toBlocking().first();

Map<Object, Object> deployServerGroups =
AsgDescriptionSupport.convertAsgsToDeploymentTargets(
(List<Map<String, String>>) stage.getContext().get("asgs"));

Map<String, Object> contextMap = new HashMap<>();
contextMap.put("notification.type", "deletetencentcloudscheduledaction");
contextMap.put("deploy.server.groups", deployServerGroups);
contextMap.put("kato.last.task.id", taskId);
return TaskResult.builder(ExecutionStatus.SUCCEEDED).context(contextMap).build();
}

public KatoService getKato() {
return kato;
}

public void setKato(KatoService kato) {
this.kato = kato;
}

@Autowired private KatoService kato;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Only the pipeline stages which are specific to Tencent Cloud should belong to this package
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2019 THL A29 Limited, a Tencent company.
*
* 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.clouddriver.pipeline.providers.tencentcloud;

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.clouddriver.tasks.MonitorKatoTask;
import com.netflix.spinnaker.orca.clouddriver.tasks.servergroup.ServerGroupCacheForceRefreshTask;
import javax.annotation.Nonnull;
import org.springframework.stereotype.Component;

@Component
public class UpsertTencentCloudScheduledActionsStage implements StageDefinitionBuilder {

@Override
public void taskGraph(@Nonnull StageExecution stage, @Nonnull TaskNode.Builder builder) {
builder
.withTask(
"upsertTencentCloudScheduledActions", UpsertTencentCloudScheduledActionsTask.class)
.withTask("monitorUpsert", MonitorKatoTask.class)
.withTask("forceCacheRefresh", ServerGroupCacheForceRefreshTask.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2019 THL A29 Limited, a Tencent company.
*
* 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.clouddriver.pipeline.providers.tencentcloud;

import com.netflix.spinnaker.orca.api.pipeline.Task;
import com.netflix.spinnaker.orca.api.pipeline.TaskResult;
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus;
import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution;
import com.netflix.spinnaker.orca.clouddriver.KatoService;
import com.netflix.spinnaker.orca.clouddriver.model.TaskId;
import com.netflix.spinnaker.orca.kato.pipeline.support.AsgDescriptionSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class UpsertTencentCloudScheduledActionsTask implements Task {

@Autowired private KatoService kato;

@Override
public TaskResult execute(StageExecution stage) {
Map<String, Map> map = new HashMap<>();
map.put("upsertTencentCloudScheduledActionsDescription", stage.getContext());
Collection<Map<String, Map>> ops = new ArrayList<>();
ops.add(map);
TaskId taskId = kato.requestOperations(ops).toBlocking().first();

Map deployServerGroups =
AsgDescriptionSupport.convertAsgsToDeploymentTargets(
(List<Map<String, String>>) stage.getContext().get("asgs"));

Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("notification.type", "upserttencentcloudscheduledactions");
resultMap.put("deploy.server.groups", deployServerGroups);
resultMap.put("kato.last.task.id", taskId);
TaskResult taskResult =
TaskResult.builder(ExecutionStatus.SUCCEEDED).outputs(resultMap).build();

return taskResult;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2019 THL A29 Limited, a Tencent company.
*
* 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.clouddriver.tasks.providers.tencentcloud;

import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution;
import com.netflix.spinnaker.orca.clouddriver.MortService;
import com.netflix.spinnaker.orca.clouddriver.MortService.SecurityGroup;
import com.netflix.spinnaker.orca.clouddriver.tasks.securitygroup.SecurityGroupUpserter;
import com.netflix.spinnaker.orca.clouddriver.utils.CloudProviderAware;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import retrofit.RetrofitError;
import retrofit.client.Response;

@Slf4j
@Component
public class TencentCloudSecurityGroupUpserter
implements SecurityGroupUpserter, CloudProviderAware {

private final String cloudProvider = "tencentcloud";
@Autowired private MortService mortService;

@Override
public OperationContext getOperationContext(StageExecution stage) {
Map<String, Map<String, Object>> operationMap = new HashMap<>();
operationMap.put(SecurityGroupUpserter.OPERATION, stage.getContext());

List<Map> ops = new ArrayList<>(Collections.singletonList(operationMap));

SecurityGroup group = new SecurityGroup();
group.setName((String) stage.getContext().get("securityGroupName"));
group.setRegion((String) stage.getContext().get("region"));
group.setAccountName(getCredentials(stage));

List<SecurityGroup> targets = new ArrayList<>();
targets.add(group);

Map<String, List<SecurityGroup>> targetsMap = new HashMap<>();
targetsMap.put("targets", targets);

SecurityGroupUpserter.OperationContext operationContext =
new SecurityGroupUpserter.OperationContext();
operationContext.setOperations(ops);
operationContext.setExtraOutput(targetsMap);
return operationContext;
}

public boolean isSecurityGroupUpserted(
SecurityGroup upsertedSecurityGroup, StageExecution stage) {
log.info("Enter tencentcloud isSecurityGroupUpserted with " + upsertedSecurityGroup);
try {
SecurityGroup securityGroup =
mortService.getSecurityGroup(
upsertedSecurityGroup.getAccountName(),
cloudProvider,
upsertedSecurityGroup.getName(),
upsertedSecurityGroup.getRegion(),
upsertedSecurityGroup.getVpcId());

return upsertedSecurityGroup.getName().equals(securityGroup.getName());
} catch (RetrofitError e) {
final Response response = e.getResponse();
if ((response == null ? null : response.getStatus()) != 404) {
throw e;
}
}

return false;
}

public final String getCloudProvider() {
return cloudProvider;
}
}
Loading

0 comments on commit c50372f

Please sign in to comment.