diff --git a/pom.xml b/pom.xml index 06c03ea7..84895cc7 100755 --- a/pom.xml +++ b/pom.xml @@ -128,6 +128,11 @@ + + org.yaml + snakeyaml + 1.14 + org.jboss jboss-dmr diff --git a/src/main/java/com/openshift/internal/restclient/model/kubeclient/Cluster.java b/src/main/java/com/openshift/internal/restclient/model/kubeclient/Cluster.java new file mode 100644 index 00000000..99d1ac4d --- /dev/null +++ b/src/main/java/com/openshift/internal/restclient/model/kubeclient/Cluster.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeclient; + +import java.util.HashMap; +import java.util.Map; +import com.openshift.restclient.model.kubeclient.ICluster; + +public class Cluster implements ICluster { + + private static final String SERVER = "server"; + private static final String INSECURE_SKIP_TLS_VERIFY = "insecure-skip-tls-verify"; + private String name; + private Map cluster = new HashMap<>(); + + public void setCluster(Map cluster) { + this.cluster.clear(); + this.cluster.putAll(cluster); + } + + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String getServer() { + return (String) cluster.get(SERVER); + } + + @Override + public boolean isInsecureSkipTLSVerify() { + if(cluster.containsKey(INSECURE_SKIP_TLS_VERIFY)) { + return (Boolean) cluster.get(INSECURE_SKIP_TLS_VERIFY); + } + return false; + } + +} diff --git a/src/main/java/com/openshift/internal/restclient/model/kubeclient/Context.java b/src/main/java/com/openshift/internal/restclient/model/kubeclient/Context.java new file mode 100644 index 00000000..049df17e --- /dev/null +++ b/src/main/java/com/openshift/internal/restclient/model/kubeclient/Context.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeclient; + +import java.util.HashMap; +import java.util.Map; + +import com.openshift.internal.restclient.model.properties.ResourcePropertyKeys; +import com.openshift.restclient.model.kubeclient.IContext; + +/** + * KubeConfig context + * @author jeff.cantrill + * + */ +public class Context implements IContext, ResourcePropertyKeys{ + + private static final String USER = "user"; + private static final String CLUSTER = "cluster"; + private Map context = new HashMap<>(); + private String name; + + public void setContext(Map context) { + this.context.clear(); + this.context.putAll(context); + } + @Override + public String getCluster() { + return context.get(CLUSTER); + } + + @Override + public String getUser() { + return context.get(USER); + } + + @Override + public String getNamespace() { + return context.get(NAMESPACE); + } + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfig.java b/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfig.java new file mode 100644 index 00000000..308e19b5 --- /dev/null +++ b/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfig.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeclient; + +import java.util.ArrayList; +import java.util.Collection; + +import com.openshift.restclient.model.kubeclient.ICluster; +import com.openshift.restclient.model.kubeclient.IContext; +import com.openshift.restclient.model.kubeclient.IKubeClientConfig; +import com.openshift.restclient.model.kubeclient.IUser; + +/** + * Kube Client config impl + * + * @author jeff.cantrill + * + */ +public class KubeClientConfig implements IKubeClientConfig { + + private Collection clusters = new ArrayList<>(); + private Collection contexts = new ArrayList<>(); + private String currentContext = ""; + private Collection users = new ArrayList<>(); + + public void setApiVersion(String apiVersion) { + + } + + @Override + public Collection< ICluster> getClusters() { + return clusters; + } + + public void setClusters(Collection clusters) { + this.clusters = clusters; + } + + @Override + public Collection getContexts() { + return contexts; + } + public void setContexts(Collection contexts) { + this.contexts = contexts; + } + + @Override + public String getCurrentContext() { + // TODO Auto-generated method stub + return currentContext; + } + public void setCurrentContext(String currentContext) { + this.currentContext = currentContext; + } + @Override + public Collection getUsers() { + return users; + } + + public void setUsers(Collection users) { + this.users = users; + } + +} diff --git a/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfigConstructor.java b/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfigConstructor.java new file mode 100644 index 00000000..36a050fd --- /dev/null +++ b/src/main/java/com/openshift/internal/restclient/model/kubeclient/KubeClientConfigConstructor.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeclient; + +import org.yaml.snakeyaml.TypeDescription; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.introspector.PropertyUtils; + +public class KubeClientConfigConstructor extends Constructor { + + private static final String USERS = "users"; + private static final String CLUSTERS = "clusters"; + private static final String CONTEXTS = "contexts"; + + public KubeClientConfigConstructor(PropertyUtils propertyUtils) { + super(KubeClientConfig.class); + + TypeDescription configTypeDesc = new TypeDescription(KubeClientConfig.class); + configTypeDesc.putListPropertyType(CONTEXTS, Context.class); + configTypeDesc.putListPropertyType(CLUSTERS, Cluster.class); + configTypeDesc.putListPropertyType(USERS, User.class); + addTypeDescription(configTypeDesc); + + setPropertyUtils(propertyUtils); + } + +} diff --git a/src/main/java/com/openshift/internal/restclient/model/kubeclient/User.java b/src/main/java/com/openshift/internal/restclient/model/kubeclient/User.java new file mode 100644 index 00000000..f2fcc20d --- /dev/null +++ b/src/main/java/com/openshift/internal/restclient/model/kubeclient/User.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeclient; + +import java.util.Map; + +import com.openshift.restclient.model.kubeclient.IUser; + +public class User implements IUser { + + private String name; + private Map user; + + public void setUser(Map user) { + this.user = user; + } + @Override + public String getToken() { + return user.get("token"); + } + + @Override + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + +} diff --git a/src/main/java/com/openshift/restclient/ClientBuilder.java b/src/main/java/com/openshift/restclient/ClientBuilder.java index a7699cd6..6d04b0f3 100644 --- a/src/main/java/com/openshift/restclient/ClientBuilder.java +++ b/src/main/java/com/openshift/restclient/ClientBuilder.java @@ -31,6 +31,12 @@ public class ClientBuilder { private String certificateAlias; private IResourceFactory resourceFactory; private IAuthorizationStrategy authStrategy; + private String withUserName; + private Object token; + + public ClientBuilder() { + this(null); + } public ClientBuilder(String baseUrl) { this.baseUrl = baseUrl; @@ -52,11 +58,44 @@ public ClientBuilder resourceFactory(IResourceFactory factory) { return this; } + @Deprecated public ClientBuilder resourceFactory(IAuthorizationStrategy authStrategy) { this.authStrategy = authStrategy; return this; } + + public ClientBuilder authorizationStrategy(IAuthorizationStrategy authStrategy) { + this.authStrategy = authStrategy; + return this; + } + + public ClientBuilder toCluster(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + public ClientBuilder withUserName(String userName) { + this.withUserName = userName; + return this; + } + + public ClientBuilder usingToken(String userName) { + this.token = token; + return this; + } + /** + * Build a client using the config loading rules defined http://janetkuo.github.io/kubernetes/v1.0/docs/user-guide/kubeconfig-file.html. Brief summary + * of loading order: + * + * 1. use explicit values set in builder + * a. username/token + * b. authStrategy + * 2. currentContext of config file located at $KUBECONFIG + * 3. currentContext of config file located at ~/.kube/config + * + * @return + */ public IClient build() { try { ISSLCertificateCallback sslCallback = defaultIfNull(this.sslCertificateCallback, new NoopSSLCertificateCallback()); diff --git a/src/main/java/com/openshift/restclient/model/kubeclient/ICluster.java b/src/main/java/com/openshift/restclient/model/kubeclient/ICluster.java new file mode 100644 index 00000000..2ea4c9e8 --- /dev/null +++ b/src/main/java/com/openshift/restclient/model/kubeclient/ICluster.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.model.kubeclient; + +public interface ICluster { + + String getName(); + /** + * The server url + * @return + */ + String getServer(); + + boolean isInsecureSkipTLSVerify(); + +} \ No newline at end of file diff --git a/src/main/java/com/openshift/restclient/model/kubeclient/IContext.java b/src/main/java/com/openshift/restclient/model/kubeclient/IContext.java new file mode 100644 index 00000000..70676025 --- /dev/null +++ b/src/main/java/com/openshift/restclient/model/kubeclient/IContext.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.model.kubeclient; + +public interface IContext { + + /** + * The name of the cluster + * @return + */ + String getCluster(); + + /** + * Returns the user info in the form of: + * / + * @return the user info + */ + String getUser(); + + /** + * default namespace to use + * on unspecified requests + * @return + */ + String getNamespace(); + + /** + * The name of the context + * @return + */ + String getName(); + +} \ No newline at end of file diff --git a/src/main/java/com/openshift/restclient/model/kubeclient/IKubeClientConfig.java b/src/main/java/com/openshift/restclient/model/kubeclient/IKubeClientConfig.java new file mode 100644 index 00000000..9dd94c91 --- /dev/null +++ b/src/main/java/com/openshift/restclient/model/kubeclient/IKubeClientConfig.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.model.kubeclient; + +import java.util.Collection; + +/** + * Configuration type for connecting to a Kubernetes client config + * ref: client/unversioned/clientcmd/api/types.go + * + * @author jeff.cantrill + * + */ +public interface IKubeClientConfig { + + /** + * A map of userinfo to cluster info where the key + * is // + * @return + */ + Collection getClusters(); + + Collection getContexts(); + + /** + * The name of the current cluster context + * @return + */ + String getCurrentContext(); + + Collection getUsers(); +} diff --git a/src/main/java/com/openshift/restclient/model/kubeclient/IUser.java b/src/main/java/com/openshift/restclient/model/kubeclient/IUser.java new file mode 100644 index 00000000..bf72914e --- /dev/null +++ b/src/main/java/com/openshift/restclient/model/kubeclient/IUser.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.model.kubeclient; + +public interface IUser { + + String getToken(); + + String getName(); +} \ No newline at end of file diff --git a/src/main/java/com/openshift/restclient/model/kubeclient/KubeClientConfigSerializer.java b/src/main/java/com/openshift/restclient/model/kubeclient/KubeClientConfigSerializer.java new file mode 100644 index 00000000..0a5aa8a9 --- /dev/null +++ b/src/main/java/com/openshift/restclient/model/kubeclient/KubeClientConfigSerializer.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.model.kubeclient; + +import java.beans.IntrospectionException; +import java.io.Reader; + +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.introspector.Property; +import org.yaml.snakeyaml.introspector.PropertyUtils; +import org.yaml.snakeyaml.representer.Representer; + +import com.openshift.internal.restclient.model.kubeclient.KubeClientConfig; +import com.openshift.internal.restclient.model.kubeclient.KubeClientConfigConstructor; +import com.openshift.restclient.utils.BeanUtils; + +/** + * + * @author jeff.cantrill + * + */ +public class KubeClientConfigSerializer { + + public IKubeClientConfig loadKubeClientConfig(Reader reader) { + Representer representer = new Representer(); + Yaml parser = new Yaml(new KubeClientConfigConstructor(new YamlPropertyUtils()), representer); + representer.getPropertyUtils().setSkipMissingProperties(true); + return parser.loadAs(reader, KubeClientConfig.class); + } + + private static class YamlPropertyUtils extends PropertyUtils { + @Override + public Property getProperty(Class type, String name) throws IntrospectionException { + if (name.indexOf('-') > -1) { + name = BeanUtils.toCamelCase(name, "-"); + } + return super.getProperty(type, name); + } + } +} diff --git a/src/main/java/com/openshift/restclient/utils/BeanUtils.java b/src/main/java/com/openshift/restclient/utils/BeanUtils.java new file mode 100644 index 00000000..08342725 --- /dev/null +++ b/src/main/java/com/openshift/restclient/utils/BeanUtils.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.restclient.utils; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang.StringUtils; + +public class BeanUtils { + + private BeanUtils() { + } + + /** + * Convert a delimited string to camelcase (e.g. foo-bar -> fooBar) + * @param name the string to convert + * @param delimiter the delimiter to use + * @return the delimited string camelcased + */ + public static String toCamelCase(String name, String delimiter) { + String[] parts = name.split("-"); + List capitalized = Stream.of(parts).map(p->StringUtils.capitalize(p)).collect(Collectors.toList()); + return StringUtils.uncapitalize(StringUtils.join(capitalized, "")); + } +} diff --git a/src/test/java/com/openshift/internal/restclient/model/kubeconfig/KubeClientConfigTest.java b/src/test/java/com/openshift/internal/restclient/model/kubeconfig/KubeClientConfigTest.java new file mode 100644 index 00000000..487d90cc --- /dev/null +++ b/src/test/java/com/openshift/internal/restclient/model/kubeconfig/KubeClientConfigTest.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package com.openshift.internal.restclient.model.kubeconfig; + +import static org.junit.Assert.*; + +import java.io.StringReader; + +import org.junit.Before; +import org.junit.Test; + +import com.openshift.restclient.model.kubeclient.ICluster; +import com.openshift.restclient.model.kubeclient.IContext; +import com.openshift.restclient.model.kubeclient.IKubeClientConfig; +import com.openshift.restclient.model.kubeclient.IUser; +import com.openshift.restclient.model.kubeclient.KubeClientConfigSerializer; +import com.openshift.restclient.utils.Samples; + +public class KubeClientConfigTest { + + private IKubeClientConfig config; + @Before + public void setUp() throws Exception { + + String kubeConfig = Samples.V1_KUBE_CONFIG.getContentAsString(); + StringReader reader = new StringReader(kubeConfig); + + KubeClientConfigSerializer serializer = new KubeClientConfigSerializer(); + config = serializer.loadKubeClientConfig(reader); + } + + @Test + public void testDeserialization() { + assertEquals("default/10-3-9-15:8443/jcantril@redhat.com", config.getCurrentContext()); + + assertEquals(2, config.getClusters().size()); + ICluster cluster = config.getClusters().iterator().next(); + assertEquals("10-3-9-15:8443", cluster.getName()); + assertEquals("https://10.3.9.15:8443", cluster.getServer()); + assertEquals("Exp. cluster skipTLSVerify", true, cluster.isInsecureSkipTLSVerify()); + + assertEquals(4, config.getContexts().size()); + IContext context = config.getContexts().iterator().next(); + assertNotNull(context); + assertEquals("default", context.getNamespace()); + assertEquals("10-3-9-15:8443", context.getCluster()); + assertEquals("jcantril@redhat.com/10-3-9-15:8443", context.getUser()); + + assertEquals("Exp. user count", 2, config.getUsers().size()); + IUser user = config.getUsers().iterator().next(); + assertEquals("admin/localhost:8443", user.getName()); + assertEquals("Q6cbJl4yMwP9o7crPbT5XMx9HSuv9W6jgXXE6omHK0Q", user.getToken()); + } + +} diff --git a/src/test/java/com/openshift/restclient/utils/Samples.java b/src/test/java/com/openshift/restclient/utils/Samples.java index 8cc1b75f..bc22994e 100644 --- a/src/test/java/com/openshift/restclient/utils/Samples.java +++ b/src/test/java/com/openshift/restclient/utils/Samples.java @@ -21,6 +21,8 @@ public enum Samples { //v1 + V1_KUBE_CONFIG("openshift3/v1_kubeconfig.yaml"), + V1_BUILD_CONFIG("openshift3/v1_build_config.json"), V1_BUILD_CONFIG_LIST("openshift3/v1_build_config_list.json"), V1_DEPLOYMENT_CONIFIG("openshift3/v1_deployment_config.json"), diff --git a/src/test/resources/samples/openshift3/v1_kubeconfig.yaml b/src/test/resources/samples/openshift3/v1_kubeconfig.yaml new file mode 100644 index 00000000..a1a980b6 --- /dev/null +++ b/src/test/resources/samples/openshift3/v1_kubeconfig.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +clusters: +- cluster: + insecure-skip-tls-verify: true + server: https://10.3.9.15:8443 + name: 10-3-9-15:8443 +- cluster: + insecure-skip-tls-verify: true + server: https://localhost:8443 + name: localhost:8443 +contexts: +- context: + cluster: 10-3-9-15:8443 + namespace: default + user: jcantril@redhat.com/10-3-9-15:8443 + name: default/10-3-9-15:8443/jcantril@redhat.com +- context: + cluster: localhost:8443 + namespace: default + user: admin/localhost:8443 + name: default/localhost:8443/admin +- context: + cluster: localhost:8443 + namespace: foo + user: admin/localhost:8443 + name: foo/localhost:8443/admin +- context: + cluster: localhost:8443 + namespace: openshift + user: admin/localhost:8443 + name: openshift/localhost:8443/admin +current-context: default/10-3-9-15:8443/jcantril@redhat.com +kind: Config +preferences: {} +users: +- name: admin/localhost:8443 + user: + token: Q6cbJl4yMwP9o7crPbT5XMx9HSuv9W6jgXXE6omHK0Q +- name: jcantril@redhat.com/10-3-9-15:8443 + user: + token: co3qQP7aYj9Mw2JBQzwJQ2yjyBHSv4SXXs9RSkYlgBQ