Skip to content

Commit

Permalink
feat(huaweicloud): first commit for huaweicloud (#4176)
Browse files Browse the repository at this point in the history
* feat(huaweicloud): first commit for huaweicloud

* style(huaweicloud): fix code style
  • Loading branch information
zengchen1024 authored and mergify[bot] committed Nov 22, 2019
1 parent db92191 commit 46a2705
Show file tree
Hide file tree
Showing 12 changed files with 533 additions and 0 deletions.
22 changes: 22 additions & 0 deletions clouddriver-huaweicloud/clouddriver-huaweicloud.gradle
@@ -0,0 +1,22 @@
dependencies {
implementation project(":cats:cats-core")
implementation project(":clouddriver-core")
implementation project(":clouddriver-security")

compileOnly "org.projectlombok:lombok"
annotationProcessor "org.projectlombok:lombok"
testAnnotationProcessor "org.projectlombok:lombok"

implementation "com.netflix.frigga:frigga"
implementation "com.netflix.spectator:spectator-api"
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
implementation "com.netflix.spinnaker.moniker:moniker"
implementation "org.glassfish.jersey.inject:jersey-hk2:2.28"
implementation 'com.huawei:openstack4j:1.0.17'
implementation "org.glassfish.jersey.core:jersey-client:2.22.1"
implementation "org.glassfish.jersey.media:jersey-media-json-jackson:2.11"
implementation "org.codehaus.groovy:groovy-all"
implementation "org.springframework.boot:spring-boot-actuator"
implementation "org.springframework.boot:spring-boot-starter-web"
}
@@ -0,0 +1,28 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HuaweiCloudOperation {
String value();
}
@@ -0,0 +1,45 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud;

import com.netflix.spinnaker.clouddriver.core.CloudProvider;
import java.lang.annotation.Annotation;
import org.springframework.stereotype.Component;

@Component
public class HuaweiCloudProvider implements CloudProvider {
public static final String ID = "huaweicloud";

final String id = ID;
final String displayName = "HuaweiCloud";
final Class<? extends Annotation> operationAnnotationType = HuaweiCloudOperation.class;

@Override
public String getId() {
return id;
}

@Override
public String getDisplayName() {
return displayName;
}

@Override
public Class<? extends Annotation> getOperationAnnotationType() {
return operationAnnotationType;
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud.client;

import com.huawei.openstack4j.api.OSClient;

public interface AuthorizedClientProvider {
/**
* get authorized huaweicloud client.
*
* @return
*/
OSClient getAuthClient();
}
@@ -0,0 +1,30 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud.client;

import com.huawei.openstack4j.model.compute.ext.AvailabilityZone;
import java.util.List;

public interface HuaweiCloudClient {
/**
* List availability zones in a region
*
* @param region
* @return
*/
List<? extends AvailabilityZone> getZones(String region);
}
@@ -0,0 +1,38 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud.client;

import com.huawei.openstack4j.api.OSClient;
import com.huawei.openstack4j.model.compute.ext.AvailabilityZone;
import java.util.List;

public class HuaweiCloudClientImpl implements HuaweiCloudClient {
private final AuthorizedClientProvider provider;

public HuaweiCloudClientImpl(AuthorizedClientProvider provider) {
this.provider = provider;
}

private OSClient getRegionClient(String region) {
return this.provider.getAuthClient().useRegion(region);
}

@Override
public List<? extends AvailabilityZone> getZones(String region) {
return getRegionClient(region).compute().zones().list();
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud.config;

import java.util.List;
import lombok.Data;

@Data
public class HuaweiCloudConfigurationProperties {

@Data
public static class ManagedAccount {
private String name;
private String environment;
private String accountType;
private String authUrl;
private String username;
private String password;
private String projectName;
private String domainName;
private Boolean insecure;
private List<String> regions;
}

private List<ManagedAccount> accounts;
}
@@ -0,0 +1,92 @@
/*
* Copyright 2019 Huawei Technologies Co.,Ltd.
*
* 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.clouddriver.huaweicloud.security;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.huawei.openstack4j.api.OSClient;
import com.huawei.openstack4j.core.transport.Config;
import com.huawei.openstack4j.model.common.Identifier;
import com.huawei.openstack4j.model.identity.v3.Token;
import com.huawei.openstack4j.openstack.OSFactory;
import com.netflix.spinnaker.clouddriver.huaweicloud.client.AuthorizedClientProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HuaweiCloudCredentials implements AuthorizedClientProvider {
private final Logger log = LoggerFactory.getLogger(HuaweiCloudCredentials.class);

private final String authUrl;
private final String username;
@JsonIgnore private final String password;
private final String projectName;
private final String domainName;
private final Boolean insecure;

@JsonIgnore private Token token = null;

public HuaweiCloudCredentials(
String authUrl,
String username,
String password,
String projectName,
String domainName,
Boolean insecure) {
this.authUrl = authUrl;
this.username = username;
this.password = password;
this.projectName = projectName;
this.domainName = domainName;
this.insecure = insecure;
}

public OSClient getAuthClient() {
Config config =
insecure ? Config.newConfig().withSSLVerificationDisabled() : Config.newConfig();
OSClient client = null;
try {
if (needRefreshToken()) {
synchronized (this) {
if (needRefreshToken()) {
token =
OSFactory.builderV3()
.withConfig(config)
.endpoint(authUrl)
.credentials(username, password, Identifier.byName(domainName))
.scopeToProject(Identifier.byName(projectName), Identifier.byName(domainName))
.authenticate()
.getToken();
}
}
}

client = OSFactory.clientFromToken(token, config);
} catch (Exception e) {
log.error("Error building authorized client, error=%s", e);
}
return client;
}

private boolean needRefreshToken() {
if (token == null) {
return true;
}

long now = System.currentTimeMillis();
long expires = token.getExpires().getTime();
return now >= expires;
}
}

0 comments on commit 46a2705

Please sign in to comment.