Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

provider/kubernetes: Register docker registry credentials. #285

Merged
merged 2 commits into from
Feb 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ import retrofit.http.Query
class DockerBearerTokenService {
private Map<String, TokenService> realmToService
private Map<String, DockerBearerToken> cachedTokens
private String basicAuthenticate
public String basicAuth

DockerBearerTokenService(String username, String password) {
realmToService = new HashMap<String, TokenService>()
cachedTokens = new HashMap<String, DockerBearerToken>()
if (username) {
basicAuthenticate = new String(Base64.encoder.encode(("${username}:${password}").bytes))
basicAuthenticate = "Basic $basicAuthenticate"
basicAuth = new String(Base64.encoder.encode(("${username}:${password}").bytes))
basicAuth = "Basic $basicAuth"
} else {
basicAuthenticate = null
basicAuth = null
}
}

Expand Down Expand Up @@ -168,8 +168,8 @@ class DockerBearerTokenService {

def tokenService = getTokenService(authenticateDetails.realm)
def token
if (basicAuthenticate) {
token = tokenService.getToken(authenticateDetails.path, authenticateDetails.service, authenticateDetails.scope, basicAuthenticate)
if (basicAuth) {
token = tokenService.getToken(authenticateDetails.path, authenticateDetails.service, authenticateDetails.scope, basicAuth)
}
else {
token = tokenService.getToken(authenticateDetails.path, authenticateDetails.service, authenticateDetails.scope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,16 @@ class DockerRegistryClient {
public String address
private DockerRegistryService registryService
private GsonConverter converter
private String basicAuth

public getBasicAuth() {
return basicAuth
}

DockerRegistryClient(String address, String email, String username, String password) {
this.tokenService = new DockerBearerTokenService(username, password)
this.registryService = new RestAdapter.Builder().setEndpoint(address).setLogLevel(RestAdapter.LogLevel.NONE).build().create(DockerRegistryService)
this.basicAuth = this.tokenService.basicAuth;
this.registryService = new RestAdapter.Builder().setEndpoint(address).setLogLevel(RestAdapter.LogLevel.BASIC).build().create(DockerRegistryService)
this.converter = new GsonConverter(new GsonBuilder().create())
this.address = address
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,88 +16,118 @@

package com.netflix.spinnaker.clouddriver.docker.registry.security

import com.netflix.spinnaker.clouddriver.docker.registry.api.v2.client.DockerRegistryClient;
import com.netflix.spinnaker.clouddriver.security.AccountCredentials;

import java.util.*;
import com.netflix.spinnaker.clouddriver.docker.registry.api.v2.client.DockerRegistryClient
import com.netflix.spinnaker.clouddriver.security.AccountCredentials

public class DockerRegistryNamedAccountCredentials implements AccountCredentials<DockerRegistryCredentials> {
public DockerRegistryNamedAccountCredentials(String accountName, String environment, String accountType,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can drop semi-colons in this file.

String address, String username, String password, String email,
List<String> repositories) {
this(accountName, environment, accountType, address, username, password, email, repositories, null);
this(accountName, environment, accountType, address, username, password, email, repositories, null)
}

public DockerRegistryNamedAccountCredentials(String accountName, String environment, String accountType,
String address, String username, String password, String email,
List<String> repositories, List<String> requiredGroupMembership) {
this.accountName = accountName;
this.environment = environment;
this.accountType = accountType;
this.address = address;
this.username = username;
this.password = password;
this.email = email;
if (!accountName == 0) {
throw new IllegalArgumentException("Docker Registry account must be provided with a name.")
}
this.accountName = accountName
this.environment = environment
this.accountType = accountType

if (!address == 0) {
throw new IllegalArgumentException("Docker Registry account $accountName must provide an endpoint address.");
} else {
int addressLen = address.length();
if (address[addressLen - 1] == '/') {
address = address.substring(0, addressLen - 1)
addressLen -= 1
}
// Strip the v2 endpoint, as the Docker API assumes it's not present.
if (address.endsWith('/v2')) {
address = address.substring(0, addressLen - 3)
}
}

this.address = address
this.username = username
this.password = password
this.email = email
this.repositories = (repositories == null) ? [] : repositories
this.requiredGroupMembership = requiredGroupMembership == null ? Collections.emptyList() : Collections.unmodifiableList(requiredGroupMembership);
this.credentials = buildCredentials();
this.requiredGroupMembership = requiredGroupMembership == null ? Collections.emptyList() : Collections.unmodifiableList(requiredGroupMembership)
this.credentials = buildCredentials()
}

@Override
public String getName() {
return accountName;
return accountName
}

public String getBasicAuth() {
return this.credentials ?
this.credentials.client ?
this.credentials.client.basicAuth ?
this.credentials.client.basicAuth :
"" :
"" :
""
}

public String getEmail() {
return email
}

public String getV2Endpoint() {
return "$address/v2"
}

@Override
public String getEnvironment() {
return environment;
return environment
}

@Override
public String getAccountType() {
return accountType;
return accountType
}

@Override
public String getCloudProvider() {
return CLOUD_PROVIDER;
return CLOUD_PROVIDER
}

public DockerRegistryCredentials getCredentials() {
return credentials;
return credentials
}

private DockerRegistryCredentials buildCredentials() {
DockerRegistryClient client = new DockerRegistryClient(this.address, this.email, this.username, this.password);
return new DockerRegistryCredentials(client, this.repositories);
}

private static String getLocalName(String fullUrl) {
return fullUrl.substring(fullUrl.lastIndexOf('/') + 1);
DockerRegistryClient client = new DockerRegistryClient(this.address, this.email, this.username, this.password)
return new DockerRegistryCredentials(client, this.repositories)
}

@Override
public String getProvider() {
return getCloudProvider();
return getCloudProvider()
}

public String getAccountName() {
return accountName;
return accountName
}

public List<String> getRequiredGroupMembership() {
return requiredGroupMembership;
return requiredGroupMembership
}

private static final String CLOUD_PROVIDER = "dockerRegistry";
private final String accountName;
private final String environment;
private final String accountType;
private final String address;
private final String username;
private final String password;
private final String email;
private final List<String> repositories;
private final DockerRegistryCredentials credentials;
private final List<String> requiredGroupMembership;
private static final String CLOUD_PROVIDER = "dockerRegistry"
private final String accountName
private final String environment
private final String accountType
private final String address
private final String username
private final String password
private final String email
private final List<String> repositories
private final DockerRegistryCredentials credentials
private final List<String> requiredGroupMembership
}
1 change: 1 addition & 0 deletions clouddriver-kubernetes/clouddriver-kubernetes.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dependencies {
compile project(":clouddriver-core")
compile project(":clouddriver-docker")
compile spinnaker.dependency('frigga')
compile spinnaker.dependency('bootActuator')
compile spinnaker.dependency('bootWeb')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2016 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.clouddriver.kubernetes.api

import com.netflix.spinnaker.clouddriver.kubernetes.deploy.KubernetesUtil
import io.fabric8.kubernetes.api.model.Namespace
import io.fabric8.kubernetes.api.model.Pod
import io.fabric8.kubernetes.api.model.ReplicationController
import io.fabric8.kubernetes.api.model.Secret
import io.fabric8.kubernetes.api.model.Service
import io.fabric8.kubernetes.client.KubernetesClient

class KubernetesApiAdaptor {
KubernetesClient client

KubernetesApiAdaptor(KubernetesClient client) {
if (!client) {
throw new IllegalArgumentException("Client may not be null.")
}
this.client = client
}

List<ReplicationController> getReplicationControllers(String namespace) {
client.replicationControllers().inNamespace(namespace).list().items
}

List<Pod> getPods(String namespace, String replicationControllerName) {
client.pods().inNamespace(namespace).withLabel(KubernetesUtil.REPLICATION_CONTROLLER_LABEL, replicationControllerName).list().items
}

ReplicationController getReplicationController(String namespace, String serverGroupName) {
client.replicationControllers().inNamespace(namespace).withName(serverGroupName).get()
}

ReplicationController createReplicationController(String namespace, ReplicationController replicationController) {
client.replicationControllers().inNamespace(namespace).create(replicationController)
}

Service getService(String namespace, String service) {
client.services().inNamespace(namespace).withName(service).get()
}

Service getSecurityGroup(String namespace, String securityGroup) {
getService(namespace, securityGroup)
}

Service getLoadBalancer(String namespace, String loadBalancer) {
getService(namespace, loadBalancer)
}

Secret getSecret(String namespace, String secret) {
client.secrets().inNamespace(namespace).withName(secret).get()
}

Boolean deleteSecret(String namespace, String secret) {
client.secrets().inNamespace(namespace).withName(secret).delete()
}

Secret createSecret(String namespace, Secret secret) {
client.secrets().inNamespace(namespace).create(secret)
}

Namespace getNamespace(String namespace) {
client.namespaces().withName(namespace).get()
}

Namespace createNamespace(Namespace namespace) {
client.namespaces().create(namespace)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ class KubernetesConfigurationProperties {
String username
String password
List<String> namespaces
List<LinkedDockerRegistryConfiguration> dockerRegistries

}

List<ManagedAccount> accounts = []
}

@ToString(includeNames = true)
class LinkedDockerRegistryConfiguration {
String accountName
List<String> namespaces
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,51 +22,27 @@ import com.netflix.spinnaker.clouddriver.kubernetes.security.KubernetesCredentia
import io.fabric8.kubernetes.api.model.PodList
import io.fabric8.kubernetes.api.model.ReplicationController
import io.fabric8.kubernetes.api.model.ReplicationControllerList
import io.fabric8.kubernetes.api.model.Secret
import io.fabric8.kubernetes.api.model.Service

class KubernetesUtil {

static String SECURITY_GROUP_LABEL_PREFIX = "security-group-"
static String LOAD_BALANCER_LABEL_PREFIX = "load-balancer-"
static String REPLICATION_CONTROLLER_LABEL = "replication-controller"
private static int SECURITY_GROUP_LABEL_PREFIX_LENGTH = SECURITY_GROUP_LABEL_PREFIX.length()
private static int LOAD_BALANCER_LABEL_PREFIX_LENGTH = LOAD_BALANCER_LABEL_PREFIX.length()

ReplicationControllerList getReplicationControllers(KubernetesCredentials credentials, String namespace) {
credentials.client.replicationControllers().inNamespace(namespace).list()
}

PodList getPods(KubernetesCredentials credentials, String namespace, String replicationControllerName) {
credentials.client.pods().inNamespace(namespace).withLabel(REPLICATION_CONTROLLER_LABEL, replicationControllerName).list()
}

ReplicationController getReplicationController(KubernetesCredentials credentials, String namespace, String serverGroupName) {
credentials.client.replicationControllers().inNamespace(namespace).withName(serverGroupName).get()
}

Service getService(KubernetesCredentials credentials, String namespace, String service) {
credentials.client.services().inNamespace(namespace).withName(service).get()
}

Service getSecurityGroup(KubernetesCredentials credentials, String namespace, String securityGroup) {
getService(credentials, namespace, securityGroup)
}

Service getLoadBalancer(KubernetesCredentials credentials, String namespace, String loadBalancer) {
getService(credentials, namespace, loadBalancer)
}

String getNextSequence(String clusterName, String namespace, KubernetesCredentials credentials) {
static String getNextSequence(String clusterName, String namespace, KubernetesCredentials credentials) {
def maxSeqNumber = -1
def replicationControllers = getReplicationControllers(credentials, namespace)
def replicationControllers = credentials.apiAdaptor.getReplicationControllers(namespace)

for (def replicationController : replicationControllers.getItems()) {
replicationControllers.forEach( { replicationController ->
def names = Names.parseName(replicationController.getMetadata().getName())

if (names.cluster == clusterName) {
maxSeqNumber = Math.max(maxSeqNumber, names.sequence)
}
}
})

String.format("%03d", ++maxSeqNumber)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class DeployKubernetesAtomicOperationDescription extends KubernetesAtomicOperati
Integer targetSize
List<String> loadBalancers
List<String> securityGroups
List<String> imagePullSecrets
List<KubernetesContainerDescription> containers
}

Expand Down
Loading