Update go dependencies
This commit is contained in:
parent
a46126a034
commit
3eafaa35a1
1108 changed files with 32555 additions and 83490 deletions
29
vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go
generated
vendored
29
vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package genericclioptions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -41,6 +42,7 @@ const (
|
|||
flagContext = "context"
|
||||
flagNamespace = "namespace"
|
||||
flagAPIServer = "server"
|
||||
flagTLSServerName = "tls-server-name"
|
||||
flagInsecure = "insecure-skip-tls-verify"
|
||||
flagCertFile = "client-certificate"
|
||||
flagKeyFile = "client-key"
|
||||
|
|
@ -54,7 +56,17 @@ const (
|
|||
flagHTTPCacheDir = "cache-dir"
|
||||
)
|
||||
|
||||
var defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache")
|
||||
var (
|
||||
defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache")
|
||||
|
||||
ErrEmptyConfig = errors.New(`Missing or incomplete configuration info. Please point to an existing, complete config file:
|
||||
|
||||
1. Via the command-line flag --kubeconfig
|
||||
2. Via the KUBECONFIG environment variable
|
||||
3. In your home directory as ~/.kube/config
|
||||
|
||||
To view or setup config directly use the 'config' command.`)
|
||||
)
|
||||
|
||||
// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands
|
||||
// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages
|
||||
|
|
@ -84,6 +96,7 @@ type ConfigFlags struct {
|
|||
Context *string
|
||||
Namespace *string
|
||||
APIServer *string
|
||||
TLSServerName *string
|
||||
Insecure *bool
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
|
|
@ -108,7 +121,12 @@ type ConfigFlags struct {
|
|||
// to a .kubeconfig file, loading rules, and config flag overrides.
|
||||
// Expects the AddFlags method to have been called.
|
||||
func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) {
|
||||
return f.ToRawKubeConfigLoader().ClientConfig()
|
||||
config, err := f.ToRawKubeConfigLoader().ClientConfig()
|
||||
// replace client-go's ErrEmptyConfig error with our custom, more verbose version
|
||||
if clientcmd.IsEmptyConfig(err) {
|
||||
return nil, ErrEmptyConfig
|
||||
}
|
||||
return config, err
|
||||
}
|
||||
|
||||
// ToRawKubeConfigLoader binds config flag values to config overrides
|
||||
|
|
@ -160,6 +178,9 @@ func (f *ConfigFlags) toRawKubeConfigLoader() clientcmd.ClientConfig {
|
|||
if f.APIServer != nil {
|
||||
overrides.ClusterInfo.Server = *f.APIServer
|
||||
}
|
||||
if f.TLSServerName != nil {
|
||||
overrides.ClusterInfo.TLSServerName = *f.TLSServerName
|
||||
}
|
||||
if f.CAFile != nil {
|
||||
overrides.ClusterInfo.CertificateAuthority = *f.CAFile
|
||||
}
|
||||
|
|
@ -294,6 +315,9 @@ func (f *ConfigFlags) AddFlags(flags *pflag.FlagSet) {
|
|||
if f.APIServer != nil {
|
||||
flags.StringVarP(f.APIServer, flagAPIServer, "s", *f.APIServer, "The address and port of the Kubernetes API server")
|
||||
}
|
||||
if f.TLSServerName != nil {
|
||||
flags.StringVar(f.TLSServerName, flagTLSServerName, *f.TLSServerName, "Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used")
|
||||
}
|
||||
if f.Insecure != nil {
|
||||
flags.BoolVar(f.Insecure, flagInsecure, *f.Insecure, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
||||
}
|
||||
|
|
@ -329,6 +353,7 @@ func NewConfigFlags(usePersistentConfig bool) *ConfigFlags {
|
|||
Context: stringptr(""),
|
||||
Namespace: stringptr(""),
|
||||
APIServer: stringptr(""),
|
||||
TLSServerName: stringptr(""),
|
||||
CertFile: stringptr(""),
|
||||
KeyFile: stringptr(""),
|
||||
CAFile: stringptr(""),
|
||||
|
|
|
|||
20
vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go
generated
vendored
20
vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go
generated
vendored
|
|
@ -90,7 +90,14 @@ func SecretHash(sec *v1.Secret) (string, error) {
|
|||
// Data, Kind, and Name are taken into account.
|
||||
func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
|
||||
// json.Marshal sorts the keys in a stable order in the encoding
|
||||
m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}
|
||||
m := map[string]interface{}{
|
||||
"kind": "ConfigMap",
|
||||
"name": cm.Name,
|
||||
"data": cm.Data,
|
||||
}
|
||||
if cm.Immutable != nil {
|
||||
m["immutable"] = *cm.Immutable
|
||||
}
|
||||
if len(cm.BinaryData) > 0 {
|
||||
m["binaryData"] = cm.BinaryData
|
||||
}
|
||||
|
|
@ -105,7 +112,16 @@ func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
|
|||
// Data, Kind, Name, and Type are taken into account.
|
||||
func encodeSecret(sec *v1.Secret) (string, error) {
|
||||
// json.Marshal sorts the keys in a stable order in the encoding
|
||||
data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data})
|
||||
m := map[string]interface{}{
|
||||
"kind": "Secret",
|
||||
"type": sec.Type,
|
||||
"name": sec.Name,
|
||||
"data": sec.Data,
|
||||
}
|
||||
if sec.Immutable != nil {
|
||||
m["immutable"] = *sec.Immutable
|
||||
}
|
||||
data, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
49
vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go
generated
vendored
49
vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go
generated
vendored
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/liggitt/tabwriter"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/duration"
|
||||
|
|
@ -36,7 +35,7 @@ import (
|
|||
var _ ResourcePrinter = &HumanReadablePrinter{}
|
||||
|
||||
type printHandler struct {
|
||||
columnDefinitions []metav1beta1.TableColumnDefinition
|
||||
columnDefinitions []metav1.TableColumnDefinition
|
||||
printFunc reflect.Value
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ var (
|
|||
printFunc: reflect.ValueOf(printStatus),
|
||||
}
|
||||
|
||||
statusColumnDefinitions = []metav1beta1.TableColumnDefinition{
|
||||
statusColumnDefinitions = []metav1.TableColumnDefinition{
|
||||
{Name: "Status", Type: "string"},
|
||||
{Name: "Reason", Type: "string"},
|
||||
{Name: "Message", Type: "string"},
|
||||
|
|
@ -57,7 +56,7 @@ var (
|
|||
printFunc: reflect.ValueOf(printObjectMeta),
|
||||
}
|
||||
|
||||
objectMetaColumnDefinitions = []metav1beta1.TableColumnDefinition{
|
||||
objectMetaColumnDefinitions = []metav1.TableColumnDefinition{
|
||||
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
|
||||
{Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
|
||||
}
|
||||
|
|
@ -73,7 +72,7 @@ var (
|
|||
type HumanReadablePrinter struct {
|
||||
options PrintOptions
|
||||
lastType interface{}
|
||||
lastColumns []metav1beta1.TableColumnDefinition
|
||||
lastColumns []metav1.TableColumnDefinition
|
||||
printedHeaders bool
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +109,7 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
|
|||
|
||||
// Parameter "obj" is a table from server; print it.
|
||||
// display tables following the rules of options
|
||||
if table, ok := obj.(*metav1beta1.Table); ok {
|
||||
if table, ok := obj.(*metav1.Table); ok {
|
||||
// Do not print headers if this table has no column definitions, or they are the same as the last ones we printed
|
||||
localOptions := h.options
|
||||
if h.printedHeaders && (len(table.ColumnDefinitions) == 0 || reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns)) {
|
||||
|
|
@ -136,8 +135,8 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
|
|||
}
|
||||
if len(eventType) > 0 {
|
||||
if err := addColumns(beginning, table,
|
||||
[]metav1beta1.TableColumnDefinition{{Name: "Event", Type: "string"}},
|
||||
[]cellValueFunc{func(metav1beta1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }},
|
||||
[]metav1.TableColumnDefinition{{Name: "Event", Type: "string"}},
|
||||
[]cellValueFunc{func(metav1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -171,7 +170,7 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
|
|||
// printTable prints a table to the provided output respecting the filtering rules for options
|
||||
// for wide columns and filtered rows. It filters out rows that are Completed. You should call
|
||||
// decorateTable if you receive a table from a remote server before calling printTable.
|
||||
func printTable(table *metav1beta1.Table, output io.Writer, options PrintOptions) error {
|
||||
func printTable(table *metav1.Table, output io.Writer, options PrintOptions) error {
|
||||
if !options.NoHeaders {
|
||||
// avoid printing headers if we have no rows to display
|
||||
if len(table.Rows) == 0 {
|
||||
|
|
@ -218,7 +217,7 @@ func printTable(table *metav1beta1.Table, output io.Writer, options PrintOptions
|
|||
return nil
|
||||
}
|
||||
|
||||
type cellValueFunc func(metav1beta1.TableRow) (interface{}, error)
|
||||
type cellValueFunc func(metav1.TableRow) (interface{}, error)
|
||||
|
||||
type columnAddPosition int
|
||||
|
||||
|
|
@ -227,7 +226,7 @@ const (
|
|||
end columnAddPosition = 2
|
||||
)
|
||||
|
||||
func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav1beta1.TableColumnDefinition, valueFuncs []cellValueFunc) error {
|
||||
func addColumns(pos columnAddPosition, table *metav1.Table, columns []metav1.TableColumnDefinition, valueFuncs []cellValueFunc) error {
|
||||
if len(columns) != len(valueFuncs) {
|
||||
return fmt.Errorf("cannot prepend columns, unmatched value functions")
|
||||
}
|
||||
|
|
@ -268,7 +267,7 @@ func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav
|
|||
}
|
||||
|
||||
// All cells successfully computed, now replace columns and rows
|
||||
newColumns := make([]metav1beta1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions))
|
||||
newColumns := make([]metav1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions))
|
||||
switch pos {
|
||||
case beginning:
|
||||
newColumns = append(newColumns, columns...)
|
||||
|
|
@ -291,7 +290,7 @@ func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav
|
|||
// namespace column. It will fill empty columns with nil (if the object
|
||||
// does not expose metadata). It returns an error if the table cannot
|
||||
// be decorated.
|
||||
func decorateTable(table *metav1beta1.Table, options PrintOptions) error {
|
||||
func decorateTable(table *metav1.Table, options PrintOptions) error {
|
||||
width := len(table.ColumnDefinitions) + len(options.ColumnLabels)
|
||||
if options.WithNamespace {
|
||||
width++
|
||||
|
|
@ -313,22 +312,22 @@ func decorateTable(table *metav1beta1.Table, options PrintOptions) error {
|
|||
}
|
||||
|
||||
if width != len(table.ColumnDefinitions) {
|
||||
columns = make([]metav1beta1.TableColumnDefinition, 0, width)
|
||||
columns = make([]metav1.TableColumnDefinition, 0, width)
|
||||
if options.WithNamespace {
|
||||
columns = append(columns, metav1beta1.TableColumnDefinition{
|
||||
columns = append(columns, metav1.TableColumnDefinition{
|
||||
Name: "Namespace",
|
||||
Type: "string",
|
||||
})
|
||||
}
|
||||
columns = append(columns, table.ColumnDefinitions...)
|
||||
for _, label := range formatLabelHeaders(options.ColumnLabels) {
|
||||
columns = append(columns, metav1beta1.TableColumnDefinition{
|
||||
columns = append(columns, metav1.TableColumnDefinition{
|
||||
Name: label,
|
||||
Type: "string",
|
||||
})
|
||||
}
|
||||
if options.ShowLabels {
|
||||
columns = append(columns, metav1beta1.TableColumnDefinition{
|
||||
columns = append(columns, metav1.TableColumnDefinition{
|
||||
Name: "Labels",
|
||||
Type: "string",
|
||||
})
|
||||
|
|
@ -417,7 +416,7 @@ func printRowsForHandlerEntry(output io.Writer, handler *printHandler, eventType
|
|||
}
|
||||
|
||||
if results[1].IsNil() {
|
||||
rows := results[0].Interface().([]metav1beta1.TableRow)
|
||||
rows := results[0].Interface().([]metav1.TableRow)
|
||||
printRows(output, eventType, rows, options)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -439,7 +438,7 @@ func formatEventType(eventType string) string {
|
|||
}
|
||||
|
||||
// printRows writes the provided rows to output.
|
||||
func printRows(output io.Writer, eventType string, rows []metav1beta1.TableRow, options PrintOptions) {
|
||||
func printRows(output io.Writer, eventType string, rows []metav1.TableRow, options PrintOptions) {
|
||||
for _, row := range rows {
|
||||
if len(eventType) > 0 {
|
||||
fmt.Fprint(output, formatEventType(eventType))
|
||||
|
|
@ -522,20 +521,20 @@ func appendLabelCells(values []interface{}, itemLabels map[string]string, opts P
|
|||
return values
|
||||
}
|
||||
|
||||
func printStatus(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) {
|
||||
func printStatus(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) {
|
||||
status, ok := obj.(*metav1.Status)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected *v1.Status, got %T", obj)
|
||||
}
|
||||
return []metav1beta1.TableRow{{
|
||||
return []metav1.TableRow{{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
Cells: []interface{}{status.Status, status.Reason, status.Message},
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) {
|
||||
func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) {
|
||||
if meta.IsListType(obj) {
|
||||
rows := make([]metav1beta1.TableRow, 0, 16)
|
||||
rows := make([]metav1.TableRow, 0, 16)
|
||||
err := meta.EachListItem(obj, func(obj runtime.Object) error {
|
||||
nestedRows, err := printObjectMeta(obj, options)
|
||||
if err != nil {
|
||||
|
|
@ -550,12 +549,12 @@ func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1beta1.Ta
|
|||
return rows, nil
|
||||
}
|
||||
|
||||
rows := make([]metav1beta1.TableRow, 0, 1)
|
||||
rows := make([]metav1.TableRow, 0, 1)
|
||||
m, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row := metav1beta1.TableRow{
|
||||
row := metav1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp()))
|
||||
|
|
|
|||
110
vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go
generated
vendored
Normal file
110
vendor/k8s.io/cli-runtime/pkg/resource/crd_finder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2018 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 resource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
// CRDGetter is a function that can download the list of GVK for all
|
||||
// CRDs.
|
||||
type CRDGetter func() ([]schema.GroupKind, error)
|
||||
|
||||
func CRDFromDynamic(client dynamic.Interface) CRDGetter {
|
||||
return func() ([]schema.GroupKind, error) {
|
||||
list, err := client.Resource(schema.GroupVersionResource{
|
||||
Group: "apiextensions.k8s.io",
|
||||
Version: "v1beta1",
|
||||
Resource: "customresourcedefinitions",
|
||||
}).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list CRDs: %v", err)
|
||||
}
|
||||
if list == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
gks := []schema.GroupKind{}
|
||||
|
||||
// We need to parse the list to get the gvk, I guess that's fine.
|
||||
for _, crd := range (*list).Items {
|
||||
// Look for group, version, and kind
|
||||
group, _, _ := unstructured.NestedString(crd.Object, "spec", "group")
|
||||
kind, _, _ := unstructured.NestedString(crd.Object, "spec", "names", "kind")
|
||||
|
||||
gks = append(gks, schema.GroupKind{
|
||||
Group: group,
|
||||
Kind: kind,
|
||||
})
|
||||
}
|
||||
|
||||
return gks, nil
|
||||
}
|
||||
}
|
||||
|
||||
// CRDFinder keeps a cache of known CRDs and finds a given GVK in the
|
||||
// list.
|
||||
type CRDFinder interface {
|
||||
HasCRD(gvk schema.GroupKind) (bool, error)
|
||||
}
|
||||
|
||||
func NewCRDFinder(getter CRDGetter) CRDFinder {
|
||||
return &crdFinder{
|
||||
getter: getter,
|
||||
}
|
||||
}
|
||||
|
||||
type crdFinder struct {
|
||||
getter CRDGetter
|
||||
cache *[]schema.GroupKind
|
||||
}
|
||||
|
||||
func (f *crdFinder) cacheCRDs() error {
|
||||
if f.cache != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
list, err := f.getter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.cache = &list
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *crdFinder) findCRD(gvk schema.GroupKind) bool {
|
||||
for _, crd := range *f.cache {
|
||||
if reflect.DeepEqual(gvk, crd) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *crdFinder) HasCRD(gvk schema.GroupKind) (bool, error) {
|
||||
if err := f.cacheCRDs(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return f.findCRD(gvk), nil
|
||||
}
|
||||
121
vendor/k8s.io/cli-runtime/pkg/resource/dry_run_verifier.go
generated
vendored
Normal file
121
vendor/k8s.io/cli-runtime/pkg/resource/dry_run_verifier.go
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright 2019 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 resource
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
// VerifyDryRun returns nil if a resource group-version-kind supports
|
||||
// server-side dry-run. Otherwise, an error is returned.
|
||||
func VerifyDryRun(gvk schema.GroupVersionKind, dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface) error {
|
||||
verifier := NewDryRunVerifier(dynamicClient, discoveryClient)
|
||||
return verifier.HasSupport(gvk)
|
||||
}
|
||||
|
||||
func NewDryRunVerifier(dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface) *DryRunVerifier {
|
||||
return &DryRunVerifier{
|
||||
finder: NewCRDFinder(CRDFromDynamic(dynamicClient)),
|
||||
openAPIGetter: discoveryClient,
|
||||
}
|
||||
}
|
||||
|
||||
func hasGVKExtension(extensions []*openapi_v2.NamedAny, gvk schema.GroupVersionKind) bool {
|
||||
for _, extension := range extensions {
|
||||
if extension.GetValue().GetYaml() == "" ||
|
||||
extension.GetName() != "x-kubernetes-group-version-kind" {
|
||||
continue
|
||||
}
|
||||
var value map[string]string
|
||||
err := yaml.Unmarshal([]byte(extension.GetValue().GetYaml()), &value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if value["group"] == gvk.Group && value["kind"] == gvk.Kind && value["version"] == gvk.Version {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DryRunVerifier verifies if a given group-version-kind supports DryRun
|
||||
// against the current server. Sending dryRun requests to apiserver that
|
||||
// don't support it will result in objects being unwillingly persisted.
|
||||
//
|
||||
// It reads the OpenAPI to see if the given GVK supports dryRun. If the
|
||||
// GVK can not be found, we assume that CRDs will have the same level of
|
||||
// support as "namespaces", and non-CRDs will not be supported. We
|
||||
// delay the check for CRDs as much as possible though, since it
|
||||
// requires an extra round-trip to the server.
|
||||
type DryRunVerifier struct {
|
||||
finder CRDFinder
|
||||
openAPIGetter discovery.OpenAPISchemaInterface
|
||||
}
|
||||
|
||||
// HasSupport verifies if the given gvk supports DryRun. An error is
|
||||
// returned if it doesn't.
|
||||
func (v *DryRunVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
||||
oapi, err := v.openAPIGetter.OpenAPISchema()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download openapi: %v", err)
|
||||
}
|
||||
supports, err := supportsDryRun(oapi, gvk)
|
||||
if err != nil {
|
||||
// We assume that we couldn't find the type, then check for namespace:
|
||||
supports, _ = supportsDryRun(oapi, schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"})
|
||||
// If namespace supports dryRun, then we will support dryRun for CRDs only.
|
||||
if supports {
|
||||
supports, err = v.finder.HasCRD(gvk.GroupKind())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check CRD: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !supports {
|
||||
return fmt.Errorf("%v doesn't support dry-run", gvk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// supportsDryRun is a method that let's us look in the OpenAPI if the
|
||||
// specific group-version-kind supports the dryRun query parameter for
|
||||
// the PATCH end-point.
|
||||
func supportsDryRun(doc *openapi_v2.Document, gvk schema.GroupVersionKind) (bool, error) {
|
||||
for _, path := range doc.GetPaths().GetPath() {
|
||||
// Is this describing the gvk we're looking for?
|
||||
if !hasGVKExtension(path.GetValue().GetPatch().GetVendorExtension(), gvk) {
|
||||
continue
|
||||
}
|
||||
for _, param := range path.GetValue().GetPatch().GetParameters() {
|
||||
if param.GetParameter().GetNonBodyParameter().GetQueryParameterSubSchema().GetName() == "dryRun" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, errors.New("couldn't find GVK in openapi")
|
||||
}
|
||||
71
vendor/k8s.io/cli-runtime/pkg/resource/helper.go
generated
vendored
71
vendor/k8s.io/cli-runtime/pkg/resource/helper.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package resource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
|
|
@ -38,6 +39,13 @@ type Helper struct {
|
|||
RESTClient RESTClient
|
||||
// True if the resource type is scoped to namespaces
|
||||
NamespaceScoped bool
|
||||
// If true, then use server-side dry-run to not persist changes to storage
|
||||
// for verbs and resources that support server-side dry-run.
|
||||
//
|
||||
// Note this should only be used against an apiserver with dry-run enabled,
|
||||
// and on resources that support dry-run. If the apiserver or the resource
|
||||
// does not support dry-run, then the change will be persisted to storage.
|
||||
ServerDryRun bool
|
||||
}
|
||||
|
||||
// NewHelper creates a Helper from a ResourceMapping
|
||||
|
|
@ -49,6 +57,13 @@ func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper {
|
|||
}
|
||||
}
|
||||
|
||||
// DryRun, if true, will use server-side dry-run to not persist changes to storage.
|
||||
// Otherwise, changes will be persisted to storage.
|
||||
func (m *Helper) DryRun(dryRun bool) *Helper {
|
||||
m.ServerDryRun = dryRun
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Helper) Get(namespace, name string, export bool) (runtime.Object, error) {
|
||||
req := m.RESTClient.Get().
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
|
|
@ -58,7 +73,7 @@ func (m *Helper) Get(namespace, name string, export bool) (runtime.Object, error
|
|||
// TODO: I should be part of GetOptions
|
||||
req.Param("export", strconv.FormatBool(export))
|
||||
}
|
||||
return req.Do().Get()
|
||||
return req.Do(context.TODO()).Get()
|
||||
}
|
||||
|
||||
func (m *Helper) List(namespace, apiVersion string, export bool, options *metav1.ListOptions) (runtime.Object, error) {
|
||||
|
|
@ -70,7 +85,7 @@ func (m *Helper) List(namespace, apiVersion string, export bool, options *metav1
|
|||
// TODO: I should be part of ListOptions
|
||||
req.Param("export", strconv.FormatBool(export))
|
||||
}
|
||||
return req.Do().Get()
|
||||
return req.Do(context.TODO()).Get()
|
||||
}
|
||||
|
||||
func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions) (watch.Interface, error) {
|
||||
|
|
@ -79,7 +94,7 @@ func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions
|
|||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
VersionedParams(options, metav1.ParameterCodec).
|
||||
Watch()
|
||||
Watch(context.TODO())
|
||||
}
|
||||
|
||||
func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Interface, error) {
|
||||
|
|
@ -91,7 +106,7 @@ func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Int
|
|||
Watch: true,
|
||||
FieldSelector: fields.OneTermEqualSelector("metadata.name", name).String(),
|
||||
}, metav1.ParameterCodec).
|
||||
Watch()
|
||||
Watch(context.TODO())
|
||||
}
|
||||
|
||||
func (m *Helper) Delete(namespace, name string) (runtime.Object, error) {
|
||||
|
|
@ -99,19 +114,33 @@ func (m *Helper) Delete(namespace, name string) (runtime.Object, error) {
|
|||
}
|
||||
|
||||
func (m *Helper) DeleteWithOptions(namespace, name string, options *metav1.DeleteOptions) (runtime.Object, error) {
|
||||
if options == nil {
|
||||
options = &metav1.DeleteOptions{}
|
||||
}
|
||||
if m.ServerDryRun {
|
||||
options.DryRun = []string{metav1.DryRunAll}
|
||||
}
|
||||
|
||||
return m.RESTClient.Delete().
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Do(context.TODO()).
|
||||
Get()
|
||||
}
|
||||
|
||||
func (m *Helper) Create(namespace string, modify bool, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
func (m *Helper) Create(namespace string, modify bool, obj runtime.Object) (runtime.Object, error) {
|
||||
return m.CreateWithOptions(namespace, modify, obj, nil)
|
||||
}
|
||||
|
||||
func (m *Helper) CreateWithOptions(namespace string, modify bool, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) {
|
||||
if options == nil {
|
||||
options = &metav1.CreateOptions{}
|
||||
}
|
||||
if m.ServerDryRun {
|
||||
options.DryRun = []string{metav1.DryRunAll}
|
||||
}
|
||||
if modify {
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := metadataAccessor.ResourceVersion(obj)
|
||||
|
|
@ -135,38 +164,45 @@ func (m *Helper) createResource(c RESTClient, resource, namespace string, obj ru
|
|||
Resource(resource).
|
||||
VersionedParams(options, metav1.ParameterCodec).
|
||||
Body(obj).
|
||||
Do().
|
||||
Do(context.TODO()).
|
||||
Get()
|
||||
}
|
||||
func (m *Helper) Patch(namespace, name string, pt types.PatchType, data []byte, options *metav1.PatchOptions) (runtime.Object, error) {
|
||||
if options == nil {
|
||||
options = &metav1.PatchOptions{}
|
||||
}
|
||||
if m.ServerDryRun {
|
||||
options.DryRun = []string{metav1.DryRunAll}
|
||||
}
|
||||
return m.RESTClient.Patch(pt).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
Name(name).
|
||||
VersionedParams(options, metav1.ParameterCodec).
|
||||
Body(data).
|
||||
Do().
|
||||
Do(context.TODO()).
|
||||
Get()
|
||||
}
|
||||
|
||||
func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Object) (runtime.Object, error) {
|
||||
c := m.RESTClient
|
||||
var options = &metav1.UpdateOptions{}
|
||||
if m.ServerDryRun {
|
||||
options.DryRun = []string{metav1.DryRunAll}
|
||||
}
|
||||
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := metadataAccessor.ResourceVersion(obj)
|
||||
if err != nil {
|
||||
// We don't know how to version this object, so send it to the server as is
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj)
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj, options)
|
||||
}
|
||||
if version == "" && overwrite {
|
||||
// Retrieve the current version of the object to overwrite the server object
|
||||
serverObj, err := c.Get().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(m.Resource).Name(name).Do().Get()
|
||||
serverObj, err := c.Get().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(m.Resource).Name(name).Do(context.TODO()).Get()
|
||||
if err != nil {
|
||||
// The object does not exist, but we want it to be created
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj)
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj, options)
|
||||
}
|
||||
serverVersion, err := metadataAccessor.ResourceVersion(serverObj)
|
||||
if err != nil {
|
||||
|
|
@ -177,9 +213,16 @@ func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Obj
|
|||
}
|
||||
}
|
||||
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj)
|
||||
return m.replaceResource(c, m.Resource, namespace, name, obj, options)
|
||||
}
|
||||
|
||||
func (m *Helper) replaceResource(c RESTClient, resource, namespace, name string, obj runtime.Object) (runtime.Object, error) {
|
||||
return c.Put().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Name(name).Body(obj).Do().Get()
|
||||
func (m *Helper) replaceResource(c RESTClient, resource, namespace, name string, obj runtime.Object, options *metav1.UpdateOptions) (runtime.Object, error) {
|
||||
return c.Put().
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(resource).
|
||||
Name(name).
|
||||
VersionedParams(options, metav1.ParameterCodec).
|
||||
Body(obj).
|
||||
Do(context.TODO()).
|
||||
Get()
|
||||
}
|
||||
|
|
|
|||
10
vendor/k8s.io/cli-runtime/pkg/resource/visitor.go
generated
vendored
10
vendor/k8s.io/cli-runtime/pkg/resource/visitor.go
generated
vendored
|
|
@ -18,6 +18,7 @@ package resource
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
|
@ -30,6 +31,8 @@ import (
|
|||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"sigs.k8s.io/kustomize/pkg/fs"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -40,7 +43,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/cli-runtime/pkg/kustomize"
|
||||
"sigs.k8s.io/kustomize/pkg/fs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -100,7 +102,7 @@ func (i *Info) Get() (err error) {
|
|||
obj, err := NewHelper(i.Client, i.Mapping).Get(i.Namespace, i.Name, i.Export)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) && len(i.Namespace) > 0 && i.Namespace != metav1.NamespaceDefault && i.Namespace != metav1.NamespaceAll {
|
||||
err2 := i.Client.Get().AbsPath("api", "v1", "namespaces", i.Namespace).Do().Error()
|
||||
err2 := i.Client.Get().AbsPath("api", "v1", "namespaces", i.Namespace).Do(context.TODO()).Error()
|
||||
if err2 != nil && errors.IsNotFound(err2) {
|
||||
return err2
|
||||
}
|
||||
|
|
@ -158,7 +160,7 @@ func (i *Info) ObjectName() string {
|
|||
|
||||
// String returns the general purpose string representation
|
||||
func (i *Info) String() string {
|
||||
basicInfo := fmt.Sprintf("Name: %q, Namespace: %q\nObject: %+q", i.Name, i.Namespace, i.Object)
|
||||
basicInfo := fmt.Sprintf("Name: %q, Namespace: %q", i.Name, i.Namespace)
|
||||
if i.Mapping != nil {
|
||||
mappingInfo := fmt.Sprintf("Resource: %q, GroupVersionKind: %q", i.Mapping.Resource.String(),
|
||||
i.Mapping.GroupVersionKind.String())
|
||||
|
|
@ -695,7 +697,7 @@ func RetrieveLazy(info *Info, err error) error {
|
|||
|
||||
// CreateAndRefresh creates an object from input info and refreshes info with that object
|
||||
func CreateAndRefresh(info *Info) error {
|
||||
obj, err := NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object, nil)
|
||||
obj, err := NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue