mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 09:49:50 +00:00
Merge pull request #14087 from brendandburns/kubectl
Move the default schema cache to the home directory
This commit is contained in:
commit
44a16834d8
@ -29,8 +29,8 @@ JSON and YAML formats are accepted.
|
|||||||
Output mode. Use "\-o name" for shorter output (resource/name).
|
Output mode. Use "\-o name" for shorter output (resource/name).
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-schema\-cache\-dir\fP="/tmp/kubectl.schema"
|
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
|
||||||
If non\-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-validate\fP=true
|
\fB\-\-validate\fP=true
|
||||||
|
@ -47,8 +47,8 @@ Please refer to the models in
|
|||||||
Output mode. Use "\-o name" for shorter output (resource/name).
|
Output mode. Use "\-o name" for shorter output (resource/name).
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-schema\-cache\-dir\fP="/tmp/kubectl.schema"
|
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
|
||||||
If non\-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-timeout\fP=0
|
\fB\-\-timeout\fP=0
|
||||||
|
@ -61,8 +61,8 @@ existing replication controller and overwrite at least one (common) label in its
|
|||||||
If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout
|
If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-schema\-cache\-dir\fP="/tmp/kubectl.schema"
|
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
|
||||||
If non\-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-a\fP, \fB\-\-show\-all\fP=false
|
\fB\-a\fP, \fB\-\-show\-all\fP=false
|
||||||
|
@ -61,7 +61,7 @@ $ cat pod.json | kubectl create -f -
|
|||||||
```
|
```
|
||||||
-f, --filename=[]: Filename, directory, or URL to file to use to create the resource
|
-f, --filename=[]: Filename, directory, or URL to file to use to create the resource
|
||||||
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
||||||
--schema-cache-dir="/tmp/kubectl.schema": If non-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
--validate[=true]: If true, use a schema to validate the input before sending it
|
--validate[=true]: If true, use a schema to validate the input before sending it
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ $ cat pod.json | kubectl create -f -
|
|||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-09-11 20:48:33.289761103 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-09-17 21:39:48.399116592 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[]()
|
[]()
|
||||||
|
@ -74,7 +74,7 @@ kubectl replace --force -f ./pod.json
|
|||||||
--force[=false]: Delete and re-create the specified resource
|
--force[=false]: Delete and re-create the specified resource
|
||||||
--grace-period=-1: Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.
|
--grace-period=-1: Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.
|
||||||
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
|
||||||
--schema-cache-dir="/tmp/kubectl.schema": If non-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
--timeout=0: Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object
|
--timeout=0: Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object
|
||||||
--validate[=true]: If true, use a schema to validate the input before sending it
|
--validate[=true]: If true, use a schema to validate the input before sending it
|
||||||
```
|
```
|
||||||
@ -111,7 +111,7 @@ kubectl replace --force -f ./pod.json
|
|||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-09-11 20:48:33.290279625 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-09-17 21:39:48.399461456 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[]()
|
[]()
|
||||||
|
@ -78,7 +78,7 @@ $ kubectl rolling-update frontend --image=image:v2
|
|||||||
--output-version="": Output the formatted object with the given version (default api-version).
|
--output-version="": Output the formatted object with the given version (default api-version).
|
||||||
--poll-interval=3s: Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
--poll-interval=3s: Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||||
--rollback[=false]: If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout
|
--rollback[=false]: If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout
|
||||||
--schema-cache-dir="/tmp/kubectl.schema": If non-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'
|
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
|
||||||
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
|
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
|
||||||
--sort-by="": If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. 'ObjectMeta.Name'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
|
--sort-by="": If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. 'ObjectMeta.Name'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
|
||||||
--template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
|
--template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
|
||||||
@ -119,7 +119,7 @@ $ kubectl rolling-update frontend --image=image:v2
|
|||||||
|
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-09-11 20:48:33.293748592 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-09-17 21:39:48.40113721 +0000 UTC
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[]()
|
[]()
|
||||||
|
@ -36,11 +36,14 @@ import (
|
|||||||
const (
|
const (
|
||||||
RecommendedConfigPathFlag = "kubeconfig"
|
RecommendedConfigPathFlag = "kubeconfig"
|
||||||
RecommendedConfigPathEnvVar = "KUBECONFIG"
|
RecommendedConfigPathEnvVar = "KUBECONFIG"
|
||||||
RecommendedHomeFileName = "/.kube/config"
|
RecommendedHomeDir = ".kube"
|
||||||
|
RecommendedFileName = "config"
|
||||||
|
RecommendedSchemaName = "schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OldRecommendedHomeFile = path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig")
|
var OldRecommendedHomeFile = path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig")
|
||||||
var RecommendedHomeFile = path.Join(os.Getenv("HOME"), RecommendedHomeFileName)
|
var RecommendedHomeFile = path.Join(os.Getenv("HOME"), RecommendedHomeDir, RecommendedFileName)
|
||||||
|
var RecommendedSchemaFile = path.Join(os.Getenv("HOME"), RecommendedHomeDir, RecommendedSchemaName)
|
||||||
|
|
||||||
// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config
|
// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config
|
||||||
// Callers can put the chain together however they want, but we'd recommend:
|
// Callers can put the chain together however they want, but we'd recommend:
|
||||||
|
@ -100,7 +100,7 @@ func NewDefaultPathOptions() *PathOptions {
|
|||||||
EnvVar: clientcmd.RecommendedConfigPathEnvVar,
|
EnvVar: clientcmd.RecommendedConfigPathEnvVar,
|
||||||
ExplicitFileFlag: clientcmd.RecommendedConfigPathFlag,
|
ExplicitFileFlag: clientcmd.RecommendedConfigPathFlag,
|
||||||
|
|
||||||
GlobalFileSubpath: clientcmd.RecommendedHomeFileName,
|
GlobalFileSubpath: path.Join(clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName),
|
||||||
|
|
||||||
LoadingRules: clientcmd.NewDefaultClientConfigLoadingRules(),
|
LoadingRules: clientcmd.NewDefaultClientConfigLoadingRules(),
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -308,9 +309,63 @@ type schemaClient interface {
|
|||||||
Get() *client.Request
|
Get() *client.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func recursiveSplit(dir string) []string {
|
||||||
|
parent, file := path.Split(dir)
|
||||||
|
if len(parent) == 0 {
|
||||||
|
return []string{file}
|
||||||
|
}
|
||||||
|
return append(recursiveSplit(parent[:len(parent)-1]), file)
|
||||||
|
}
|
||||||
|
|
||||||
|
func substituteUserHome(dir string) (string, error) {
|
||||||
|
if len(dir) == 0 || dir[0] != '~' {
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
parts := recursiveSplit(dir)
|
||||||
|
if len(parts[0]) == 1 {
|
||||||
|
parts[0] = os.Getenv("HOME")
|
||||||
|
} else {
|
||||||
|
usr, err := user.Lookup(parts[0][1:])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
parts[0] = usr.HomeDir
|
||||||
|
}
|
||||||
|
return path.Join(parts...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeSchemaFile(schemaData []byte, cacheDir, cacheFile, prefix, groupVersion string) error {
|
||||||
|
if err := os.MkdirAll(path.Join(cacheDir, prefix, groupVersion), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpFile, err := ioutil.TempFile(cacheDir, "schema")
|
||||||
|
if err != nil {
|
||||||
|
// If we can't write, keep going.
|
||||||
|
if os.IsPermission(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(tmpFile, bytes.NewBuffer(schemaData)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.Link(tmpFile.Name(), cacheFile); err != nil {
|
||||||
|
// If we can't write due to file existing, or permission problems, keep going.
|
||||||
|
if os.IsExist(err) || os.IsPermission(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getSchemaAndValidate(c schemaClient, data []byte, prefix, groupVersion, cacheDir string) (err error) {
|
func getSchemaAndValidate(c schemaClient, data []byte, prefix, groupVersion, cacheDir string) (err error) {
|
||||||
var schemaData []byte
|
var schemaData []byte
|
||||||
cacheFile := path.Join(cacheDir, prefix, groupVersion, schemaFileName)
|
fullDir, err := substituteUserHome(cacheDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cacheFile := path.Join(fullDir, prefix, groupVersion, schemaFileName)
|
||||||
|
|
||||||
if len(cacheDir) != 0 {
|
if len(cacheDir) != 0 {
|
||||||
if schemaData, err = ioutil.ReadFile(cacheFile); err != nil && !os.IsNotExist(err) {
|
if schemaData, err = ioutil.ReadFile(cacheFile); err != nil && !os.IsNotExist(err) {
|
||||||
@ -326,17 +381,7 @@ func getSchemaAndValidate(c schemaClient, data []byte, prefix, groupVersion, cac
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(cacheDir) != 0 {
|
if len(cacheDir) != 0 {
|
||||||
if err = os.MkdirAll(path.Join(cacheDir, prefix, groupVersion), 0755); err != nil {
|
if err := writeSchemaFile(schemaData, fullDir, cacheFile, prefix, groupVersion); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpFile, err := ioutil.TempFile(cacheDir, "schema")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := io.Copy(tmpFile, bytes.NewBuffer(schemaData)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := os.Link(tmpFile.Name(), cacheFile); err != nil && !os.IsExist(err) {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -302,3 +303,32 @@ func TestValidateCachesSchema(t *testing.T) {
|
|||||||
t.Errorf("unexpected cache file error: %v", err)
|
t.Errorf("unexpected cache file error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSubstitueUser(t *testing.T) {
|
||||||
|
usr, _ := user.Current()
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{input: "~/foo", expected: path.Join(os.Getenv("HOME"), "foo")},
|
||||||
|
{input: "~" + usr.Username + "/bar", expected: usr.HomeDir + "/bar"},
|
||||||
|
{input: "/foo/bar", expected: "/foo/bar"},
|
||||||
|
{input: "~doesntexit/bar", expectErr: true},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
output, err := substituteUserHome(test.input)
|
||||||
|
if test.expectErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Error("unexpected non-error")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if output != test.expected {
|
||||||
|
t.Errorf("expected: %s, saw: %s", test.expected, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -279,7 +279,7 @@ func GetFlagDuration(cmd *cobra.Command, flag string) time.Duration {
|
|||||||
|
|
||||||
func AddValidateFlags(cmd *cobra.Command) {
|
func AddValidateFlags(cmd *cobra.Command) {
|
||||||
cmd.Flags().Bool("validate", true, "If true, use a schema to validate the input before sending it")
|
cmd.Flags().Bool("validate", true, "If true, use a schema to validate the input before sending it")
|
||||||
cmd.Flags().String("schema-cache-dir", "/tmp/kubectl.schema", "If non-empty, load/store cached API schemas in this directory, default is '/tmp/kubectl.schema'")
|
cmd.Flags().String("schema-cache-dir", fmt.Sprintf("~/%s/%s", clientcmd.RecommendedHomeDir, clientcmd.RecommendedSchemaName), fmt.Sprintf("If non-empty, load/store cached API schemas in this directory, default is '$HOME/%s/%s'", clientcmd.RecommendedHomeDir, clientcmd.RecommendedSchemaName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
|
func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user