From 984eb0c9a02cb3ff11717a0e3fec3071c69953ae Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 1 Feb 2019 01:23:44 -0500 Subject: [PATCH] Sync kubeconfig structure as part of generate Place it in config/v1/. Add Go 1.9 type aliases to the old names, to avoid breaking users. --- README.md | 2 +- client.go | 15 ++-- config.go | 177 +++++--------------------------------- config/v1/types.go | 203 ++++++++++++++++++++++++++++++++++++++++++++ scripts/generate.sh | 7 +- 5 files changed, 239 insertions(+), 165 deletions(-) create mode 100644 config/v1/types.go diff --git a/README.md b/README.md index 897bd66..c408cd8 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ func main() { ## Requirements -* Go 1.7+ (this package uses "context" features added in 1.7) +* Go 1.9+ (this package uses type alias features added in 1.9) * Kubernetes 1.3+ (protobuf support was added in 1.3) * [github.com/golang/protobuf/proto][go-proto] (protobuf serialization) * [golang.org/x/net/http2][go-http2] (HTTP/2 support) diff --git a/client.go b/client.go index 875d972..e424022 100644 --- a/client.go +++ b/client.go @@ -43,6 +43,7 @@ import ( "golang.org/x/net/http2" metav1 "github.com/ericchiang/k8s/apis/meta/v1" + configv1 "github.com/ericchiang/k8s/config/v1" ) const ( @@ -134,7 +135,7 @@ func (c *Client) newRequest(ctx context.Context, verb, url string, body io.Reade } // NewClient initializes a client from a client config. -func NewClient(config *Config) (*Client, error) { +func NewClient(config *configv1.Config) (*Client, error) { if len(config.Contexts) == 0 { if config.CurrentContext != "" { return nil, fmt.Errorf("no contexts with name %q", config.CurrentContext) @@ -154,7 +155,7 @@ func NewClient(config *Config) (*Client, error) { return newClient(config.Clusters[0].Cluster, config.AuthInfos[0].AuthInfo, namespaceDefault) } - var ctx Context + var ctx configv1.Context if config.CurrentContext == "" { if n := len(config.Contexts); n == 0 { return nil, errors.New("no contexts provided") @@ -180,8 +181,8 @@ func NewClient(config *Config) (*Client, error) { return nil, fmt.Errorf("context doesn't have a user") } var ( - user AuthInfo - cluster Cluster + user configv1.AuthInfo + cluster configv1.Cluster ) for _, u := range config.AuthInfos { @@ -226,11 +227,11 @@ func NewInClusterClient() (*Client, error) { Scheme: "https", Host: net.JoinHostPort(host, port), } - cluster := Cluster{ + cluster := configv1.Cluster{ Server: server.String(), CertificateAuthority: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", } - user := AuthInfo{TokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"} + user := configv1.AuthInfo{TokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"} return newClient(cluster, user, string(namespace)) } @@ -241,7 +242,7 @@ func load(filepath string, data []byte) (out []byte, err error) { return data, err } -func newClient(cluster Cluster, user AuthInfo, namespace string) (*Client, error) { +func newClient(cluster configv1.Cluster, user configv1.AuthInfo, namespace string) (*Client, error) { if cluster.Server == "" { // NOTE: kubectl defaults to localhost:8080, but it's probably better to just // be strict. diff --git a/config.go b/config.go index 3b9972e..5ef6cef 100644 --- a/config.go +++ b/config.go @@ -1,170 +1,35 @@ -/* -Copyright 2014 The Kubernetes Authors. - -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 k8s import ( - "github.com/ericchiang/k8s/runtime" + configv1 "github.com/ericchiang/k8s/config/v1" ) -// Where possible, json tags match the cli argument names. -// Top level config objects and all values required for proper functioning are not "omitempty". Any truly optional piece of config is allowed to be omitted. - -// Config holds the information needed to build connect to remote kubernetes clusters as a given user -type Config struct { - // Legacy field from pkg/api/types.go TypeMeta. - // TODO(jlowdermilk): remove this after eliminating downstream dependencies. - // +optional - Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` - // DEPRECATED: APIVersion is the preferred api version for communicating with the kubernetes cluster (v1, v2, etc). - // Because a cluster can run multiple API groups and potentially multiple versions of each, it no longer makes sense to specify - // a single value for the cluster version. - // This field isn't really needed anyway, so we are deprecating it without replacement. - // It will be ignored if it is present. - // +optional - APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` - // Preferences holds general information to be use for cli interactions - Preferences Preferences `json:"preferences" yaml:"preferences"` - // Clusters is a map of referencable names to cluster configs - Clusters []NamedCluster `json:"clusters" yaml:"clusters"` - // AuthInfos is a map of referencable names to user configs - AuthInfos []NamedAuthInfo `json:"users" yaml:"users"` - // Contexts is a map of referencable names to context configs - Contexts []NamedContext `json:"contexts" yaml:"contexts"` - // CurrentContext is the name of the context that you would like to use by default - CurrentContext string `json:"current-context" yaml:"current-context"` - // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields - // +optional - Extensions []NamedExtension `json:"extensions,omitempty" yaml:"extensions,omitempty"` -} +// Config is provided for backward compatibility with <= v1.2.0 of of the library +type Config = configv1.Config -type Preferences struct { - // +optional - Colors bool `json:"colors,omitempty" yaml:"colors,omitempty"` - // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields - // +optional - Extensions []NamedExtension `json:"extensions,omitempty" yaml:"extensions,omitempty"` -} +// Preferences is provided for backward compatibility with <= v1.2.0 of of the library +type Preferences = configv1.Preferences -// Cluster contains information about how to communicate with a kubernetes cluster -type Cluster struct { - // Server is the address of the kubernetes cluster (https://hostname:port). - Server string `json:"server" yaml:"server"` - // APIVersion is the preferred api version for communicating with the kubernetes cluster (v1, v2, etc). - // +optional - APIVersion string `json:"api-version,omitempty" yaml:"api-version,omitempty"` - // InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure. - // +optional - InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty" yaml:"insecure-skip-tls-verify,omitempty"` - // CertificateAuthority is the path to a cert file for the certificate authority. - // +optional - CertificateAuthority string `json:"certificate-authority,omitempty" yaml:"certificate-authority,omitempty"` - // CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority - // +optional - CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty" yaml:"certificate-authority-data,omitempty"` - // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields - // +optional - Extensions []NamedExtension `json:"extensions,omitempty" yaml:"extensions,omitempty"` -} +// Cluster is provided for backward compatibility with <= v1.2.0 of of the library +type Cluster = configv1.Cluster -// AuthInfo contains information that describes identity information. This is use to tell the kubernetes cluster who you are. -type AuthInfo struct { - // ClientCertificate is the path to a client cert file for TLS. - // +optional - ClientCertificate string `json:"client-certificate,omitempty" yaml:"client-certificate,omitempty"` - // ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate - // +optional - ClientCertificateData []byte `json:"client-certificate-data,omitempty" yaml:"client-certificate-data,omitempty"` - // ClientKey is the path to a client key file for TLS. - // +optional - ClientKey string `json:"client-key,omitempty" yaml:"client-key,omitempty"` - // ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey - // +optional - ClientKeyData []byte `json:"client-key-data,omitempty" yaml:"client-key-data,omitempty"` - // Token is the bearer token for authentication to the kubernetes cluster. - // +optional - Token string `json:"token,omitempty" yaml:"token,omitempty"` - // TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence. - // +optional - TokenFile string `json:"tokenFile,omitempty" yaml:"tokenFile,omitempty"` - // Impersonate is the username to imperonate. The name matches the flag. - // +optional - Impersonate string `json:"as,omitempty" yaml:"as,omitempty"` - // Username is the username for basic authentication to the kubernetes cluster. - // +optional - Username string `json:"username,omitempty" yaml:"username,omitempty"` - // Password is the password for basic authentication to the kubernetes cluster. - // +optional - Password string `json:"password,omitempty" yaml:"password,omitempty"` - // AuthProvider specifies a custom authentication plugin for the kubernetes cluster. - // +optional - AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty" yaml:"auth-provider,omitempty"` - // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields - // +optional - Extensions []NamedExtension `json:"extensions,omitempty" yaml:"extensions,omitempty"` -} +// AuthInfo is provided for backward compatibility with <= v1.2.0 of of the library +type AuthInfo = configv1.AuthInfo -// Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) -type Context struct { - // Cluster is the name of the cluster for this context - Cluster string `json:"cluster" yaml:"cluster"` - // AuthInfo is the name of the authInfo for this context - AuthInfo string `json:"user" yaml:"user"` - // Namespace is the default namespace to use on unspecified requests - // +optional - Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` - // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields - // +optional - Extensions []NamedExtension `json:"extensions,omitempty" yaml:"extensions,omitempty"` -} +// Context is provided for backward compatibility with <= v1.2.0 of of the library +type Context = configv1.Context -// NamedCluster relates nicknames to cluster information -type NamedCluster struct { - // Name is the nickname for this Cluster - Name string `json:"name" yaml:"name"` - // Cluster holds the cluster information - Cluster Cluster `json:"cluster" yaml:"cluster"` -} +// NamedCluster is provided for backward compatibility with <= v1.2.0 of of the library +type NamedCluster = configv1.NamedCluster -// NamedContext relates nicknames to context information -type NamedContext struct { - // Name is the nickname for this Context - Name string `json:"name" yaml:"name"` - // Context holds the context information - Context Context `json:"context" yaml:"context"` -} +// NamedContext is provided for backward compatibility with <= v1.2.0 of of the library +type NamedContext = configv1.NamedContext -// NamedAuthInfo relates nicknames to auth information -type NamedAuthInfo struct { - // Name is the nickname for this AuthInfo - Name string `json:"name" yaml:"name"` - // AuthInfo holds the auth information - AuthInfo AuthInfo `json:"user" yaml:"user"` -} +// NamedAuthInfo is provided for backward compatibility with <= v1.2.0 of of the library +type NamedAuthInfo = configv1.NamedAuthInfo -// NamedExtension relates nicknames to extension information -type NamedExtension struct { - // Name is the nickname for this Extension - Name string `json:"name" yaml:"name"` - // Extension holds the extension information - Extension runtime.RawExtension `json:"extension" yaml:"extension"` -} +// NamedExtension is provided for backward compatibility with <= v1.2.0 of of the library +type NamedExtension = configv1.NamedExtension -// AuthProviderConfig holds the configuration for a specified auth provider. -type AuthProviderConfig struct { - Name string `json:"name" yaml:"name"` - Config map[string]string `json:"config" yaml:"config"` -} +// AuthProviderConfig is provided for backward compatibility with <= v1.2.0 of of the library +type AuthProviderConfig = configv1.AuthProviderConfig diff --git a/config/v1/types.go b/config/v1/types.go new file mode 100644 index 0000000..a8579a9 --- /dev/null +++ b/config/v1/types.go @@ -0,0 +1,203 @@ +/* +Copyright 2014 The Kubernetes Authors. + +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 v1 + +import ( + "github.com/ericchiang/k8s/runtime" +) + +// Where possible, json tags match the cli argument names. +// Top level config objects and all values required for proper functioning are not "omitempty". Any truly optional piece of config is allowed to be omitted. + +// Config holds the information needed to build connect to remote kubernetes clusters as a given user +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type Config struct { + // Legacy field from pkg/api/types.go TypeMeta. + // TODO(jlowdermilk): remove this after eliminating downstream dependencies. + // +optional + Kind string `json:"kind,omitempty"` + // Legacy field from pkg/api/types.go TypeMeta. + // TODO(jlowdermilk): remove this after eliminating downstream dependencies. + // +optional + APIVersion string `json:"apiVersion,omitempty"` + // Preferences holds general information to be use for cli interactions + Preferences Preferences `json:"preferences"` + // Clusters is a map of referencable names to cluster configs + Clusters []NamedCluster `json:"clusters"` + // AuthInfos is a map of referencable names to user configs + AuthInfos []NamedAuthInfo `json:"users"` + // Contexts is a map of referencable names to context configs + Contexts []NamedContext `json:"contexts"` + // CurrentContext is the name of the context that you would like to use by default + CurrentContext string `json:"current-context"` + // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields + // +optional + Extensions []NamedExtension `json:"extensions,omitempty"` +} + +type Preferences struct { + // +optional + Colors bool `json:"colors,omitempty"` + // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields + // +optional + Extensions []NamedExtension `json:"extensions,omitempty"` +} + +// Cluster contains information about how to communicate with a kubernetes cluster +type Cluster struct { + // Server is the address of the kubernetes cluster (https://hostname:port). + Server string `json:"server"` + // InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure. + // +optional + InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"` + // CertificateAuthority is the path to a cert file for the certificate authority. + // +optional + CertificateAuthority string `json:"certificate-authority,omitempty"` + // CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority + // +optional + CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"` + // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields + // +optional + Extensions []NamedExtension `json:"extensions,omitempty"` +} + +// AuthInfo contains information that describes identity information. This is use to tell the kubernetes cluster who you are. +type AuthInfo struct { + // ClientCertificate is the path to a client cert file for TLS. + // +optional + ClientCertificate string `json:"client-certificate,omitempty"` + // ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate + // +optional + ClientCertificateData []byte `json:"client-certificate-data,omitempty"` + // ClientKey is the path to a client key file for TLS. + // +optional + ClientKey string `json:"client-key,omitempty"` + // ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey + // +optional + ClientKeyData []byte `json:"client-key-data,omitempty"` + // Token is the bearer token for authentication to the kubernetes cluster. + // +optional + Token string `json:"token,omitempty"` + // TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence. + // +optional + TokenFile string `json:"tokenFile,omitempty"` + // Impersonate is the username to imperonate. The name matches the flag. + // +optional + Impersonate string `json:"as,omitempty"` + // ImpersonateGroups is the groups to imperonate. + // +optional + ImpersonateGroups []string `json:"as-groups,omitempty"` + // ImpersonateUserExtra contains additional information for impersonated user. + // +optional + ImpersonateUserExtra map[string][]string `json:"as-user-extra,omitempty"` + // Username is the username for basic authentication to the kubernetes cluster. + // +optional + Username string `json:"username,omitempty"` + // Password is the password for basic authentication to the kubernetes cluster. + // +optional + Password string `json:"password,omitempty"` + // AuthProvider specifies a custom authentication plugin for the kubernetes cluster. + // +optional + AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty"` + // Exec specifies a custom exec-based authentication plugin for the kubernetes cluster. + // +optional + Exec *ExecConfig `json:"exec,omitempty"` + // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields + // +optional + Extensions []NamedExtension `json:"extensions,omitempty"` +} + +// Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) +type Context struct { + // Cluster is the name of the cluster for this context + Cluster string `json:"cluster"` + // AuthInfo is the name of the authInfo for this context + AuthInfo string `json:"user"` + // Namespace is the default namespace to use on unspecified requests + // +optional + Namespace string `json:"namespace,omitempty"` + // Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields + // +optional + Extensions []NamedExtension `json:"extensions,omitempty"` +} + +// NamedCluster relates nicknames to cluster information +type NamedCluster struct { + // Name is the nickname for this Cluster + Name string `json:"name"` + // Cluster holds the cluster information + Cluster Cluster `json:"cluster"` +} + +// NamedContext relates nicknames to context information +type NamedContext struct { + // Name is the nickname for this Context + Name string `json:"name"` + // Context holds the context information + Context Context `json:"context"` +} + +// NamedAuthInfo relates nicknames to auth information +type NamedAuthInfo struct { + // Name is the nickname for this AuthInfo + Name string `json:"name"` + // AuthInfo holds the auth information + AuthInfo AuthInfo `json:"user"` +} + +// NamedExtension relates nicknames to extension information +type NamedExtension struct { + // Name is the nickname for this Extension + Name string `json:"name"` + // Extension holds the extension information + Extension runtime.RawExtension `json:"extension"` +} + +// AuthProviderConfig holds the configuration for a specified auth provider. +type AuthProviderConfig struct { + Name string `json:"name"` + Config map[string]string `json:"config"` +} + +// ExecConfig specifies a command to provide client credentials. The command is exec'd +// and outputs structured stdout holding credentials. +// +// See the client.authentiction.k8s.io API group for specifications of the exact input +// and output format +type ExecConfig struct { + // Command to execute. + Command string `json:"command"` + // Arguments to pass to the command when executing it. + // +optional + Args []string `json:"args"` + // Env defines additional environment variables to expose to the process. These + // are unioned with the host's environment, as well as variables client-go uses + // to pass argument to the plugin. + // +optional + Env []ExecEnvVar `json:"env"` + + // Preferred input version of the ExecInfo. The returned ExecCredentials MUST use + // the same encoding version as the input. + APIVersion string `json:"apiVersion,omitempty"` +} + +// ExecEnvVar is used for setting environment variables when executing an exec-based +// credential plugin. +type ExecEnvVar struct { + Name string `json:"name"` + Value string `json:"value"` +} diff --git a/scripts/generate.sh b/scripts/generate.sh index b0a4545..722a0c0 100755 --- a/scripts/generate.sh +++ b/scripts/generate.sh @@ -31,6 +31,10 @@ done rm $( find . -type f -name '*.proto' ); cd - +mkdir -p $TEMPDIR/src/k8s.io/client-go/tools/clientcmd/api/v1 +cp $PWD/_output/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/api/v1/types.go \ + $TEMPDIR/src/k8s.io/client-go/tools/clientcmd/api/v1 + export GOPATH=$TEMPDIR function mvpkg { FROM="k8s.io/$1" @@ -49,6 +53,7 @@ for DIR in $( ls ${TEMPDIR}/src/k8s.io/api/ ); do mvpkg api/$DIR apis/$DIR done mvpkg kube-aggregator/pkg/apis/apiregistration apis/apiregistration +mvpkg client-go/tools/clientcmd/api/v1 config/v1 -rm -rf api apis runtime util +rm -rf api apis runtime util config mv $TEMPDIR/src/github.com/ericchiang/k8s/* .