Git Product home page Git Product logo

cli-runtime's Introduction

cli-runtime

Set of helpers for creating kubectl commands, as well as kubectl plugins.

Purpose

This library is a shared dependency for clients to work with Kubernetes API infrastructure which allows to maintain kubectl compatible behavior. Its first consumer is k8s.io/kubectl.

Compatibility

There are NO compatibility guarantees for this repository. It is in direct support of Kubernetes, so branches will track Kubernetes and be compatible with that repo. As we more cleanly separate the layers, we will review the compatibility guarantee.

Where does it come from?

cli-runtime is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/cli-runtime. Code changes are made in that location, merged into k8s.io/kubernetes and later synced here.

Things you should NOT do

  1. Add API types to this repo. This is for the helpers, not for the types.
  2. Directly modify any files under pkg in this repo. Those are driven from k8s.io/kubernetes/staging/src/k8s.io/cli-runtime.
  3. Expect compatibility. This repo is direct support of Kubernetes and the API isn't yet stable enough for API guarantees.
  4. Add any type that only makes sense only for kubectl.

cli-runtime's People

Contributors

alexzielenski avatar apelisse avatar ardaguclu avatar benluddy avatar cici37 avatar danielqsj avatar dims avatar humblec avatar ivogoman avatar jefftree avatar jiahuif avatar jpbetz avatar julianvmodesto avatar justaugustus avatar k8s-publishing-bot avatar kevindelgado avatar liggitt avatar liujingfang1 avatar madhavjivrajani avatar monopole avatar natasha41575 avatar pacoxu avatar pohly avatar seans3 avatar skitt avatar soltysh avatar sttts avatar thockin avatar tossmilestone avatar wojtek-t avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cli-runtime's Issues

Improve documentation for plugin writers

It seems this package is targeted for use by plugin writers, but its documentation is extremely sparse, making it really hard to use. The primary documentation I could find is the https://github.com/kubernetes/sample-cli-plugin/ which only got me through the very basics

It would be nice to have some higher level documentation of how to use this, as well as lower level documentation such as what individual fields will do. I routinely found myself digging into the implementation to figure out how to use the library

genericclioptions: Inferring namespace from config flag or kubeconfig

I'm trying to implement a very simple "kubectl get" using pkg/genericclioptions.

In my command, I see --namespace option registered.
When I invoke my command, I don't specify any value for --namespace, because I expect that it will read the kubeconfig (using default loading rules) and find the current namespace name (if set), otherwise will assume "default".

However, when I create a client and query, I get no namespace segment in URLs, so my Get() requests are failing with 404.

How is someone supposed to automatically have namespace field populated while using genericclioptions?

Here's what I'm doing:

    cf = genericclioptions.NewConfigFlags(true)
    cf.AddFlags(rootCmd.Flags()) 

    restConfig, err := cf.ToRESTConfig()
	if err != nil {
		return err
	}

    dyn, err := dynamic.NewForConfig(config)
	if err != nil {
		return nil, fmt.Errorf("failed to construct dynamic client: %w", err)
	}

    result, err := dyn.Resource(apiRes).Get(name, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("failed to get: %w", err)
	}
    // debugging shows Get() call above doesn't add a "namespace" segment to the URL

I have tried doing dyn.Resource(apiRes).Namespace(*cf.Namespace).Get(...) but since --namespace is not specified it won't do anything.

Since I use ToRESTConfig() method, I expect this package to automatically find my namespace (from kubeconfig) or assume "default" and inject that to the URL.

Why is this not happening?

Help message for '--output' is generated non-deterministically

The reason is that the keys of a map are joined together without defined order.

The help message

-o, --output string Output format. One of: json|yaml|name|go-template-file|templatefile|template|go-template|jsonpath|jsonpath-file. (default "yaml")

generated in

cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(f.AllowedFormats(), "|")))

uses the keys of the map in

var templateFormats = map[string]bool{
"template": true,
"go-template": true,
"go-template-file": true,
"templatefile": true,
}

for generating this list in

func (f *GoTemplatePrintFlags) AllowedFormats() []string {
formats := make([]string, 0, len(templateFormats))
for format := range templateFormats {
formats = append(formats, format)
}
sort.Strings(formats)
return formats
}

This means that this help message is different from time to time it's called and, more seriously, also when auto-generating documentation.

Instead, the order should be deterministic. I suggest to alphabetically order the keys.

cannot find kubernetes-1.11.0-alpha.2 tag of repo k8s.io/cli-runtime

dear approvers and reviewers of k8s, @caesarxuchao @sttts @dims @mfojtik @nikhita

I am using Client-go(v8.0.0) to develop some debug-tools for our k8s platform, while it relys on the library of k8s.io/cli-runtime when I built, but the version of kubernetes-1.11.x of this repo is empty.

I follow the guide and find your contact info on there. Then, I wonder if I should submit a PR on staging directory or just call you members for help.

If further repos under staging are need, adding them to the bot is easy. Contact one of the [owners of the bot](https://github.com/kubernetes/publishing-bot/blob/master/OWNERS).

some references info listed below:

# github.com/huya/huyactl-debug/vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource
../../vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource/helper.go:111:85: undefined: "github.com/huya/huyactl-debug/vendor/k8s.io/apimachinery/pkg/apis/meta/v1".CreateOptions
../../vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource/helper.go:113:14: undefined: "github.com/huya/huyactl-debug/vendor/k8s.io/apimachinery/pkg/apis/meta/v1".CreateOptions
../../vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource/helper.go:132:104: undefined: "github.com/huya/huyactl-debug/vendor/k8s.io/apimachinery/pkg/apis/meta/v1".CreateOptions
../../vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource/helper.go:141:90: undefined: "github.com/huya/huyactl-debug/vendor/k8s.io/apimachinery/pkg/apis/meta/v1".UpdateOptions
../../vendor/k8s.io/cli-runtime/pkg/genericclioptions/resource/helper.go:143:14: undefined: "github.com/huya/huyactl-debug/vendor/k8s.io/apimachinery/pkg/apis/meta/v1".UpdateOptions

go.mod


replace (
	k8s.io/api => k8s.io/api v0.0.0-20181216230433-16e3e9a3868f
	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20181216234223-6a481390bade
	k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20181203235515-3d8ee2261517
	k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20181004125037-79bf4e0b6454
	k8s.io/client-go => k8s.io/client-go v8.0.0+incompatible
)

list types are not supported by name printing

Hi

I'm a developer of Knative Client kn which is a command line tool for Knative. I meet with an issue when I'm trying to call kn service list -o name. It's supposed to use the default name printer. I get an error list types are not supported by name printing: *v1.ServiceList. And the error happens at this statement.

While I'm calling the default name printer, I pass serving.knative.dev/ServiceList to the printer. I have the error. After I change ServiceList to unstructured.UnstructuredList, the error is gone.

I'm curious why the default name printer won't support a structured list. Is changing from structure list to unstructuredList the best way to solve this issue ? What else shall I try ?

Inline patch kustomization does not work

Using k8s.io/cli-runtime/pkg/kustomize to build with kustomization.yaml that contains inline patch (https://github.com/kubernetes-sigs/kustomize/blob/master/examples/inlinePatch.md) fails with SliceFromPatches: evalsymlink failure error.

Here is my simple test code. In the first block, I use the k8s.io/cli-runtime/pkg/kustomize module and it fails. The second block does kustomize build in command line and it works fine.

package main

import (
	"bytes"
	"fmt"
	"log"
	"os/exec"

	"k8s.io/cli-runtime/pkg/kustomize"
	"sigs.k8s.io/kustomize/pkg/fs"
)

func main() {

	kustomizeDir := "/tmp/test"

	fSys := fs.MakeRealFS()

	var out bytes.Buffer

	err := kustomize.RunKustomizeBuild(&out, fSys, kustomizeDir)

	if err != nil {
		fmt.Println("Failed, error: ", err.Error())
	}

	fmt.Println("----------------------OUTPUT1--------------------------")
	fmt.Println(out.String())
	fmt.Println("----------------------OUTPUT1--------------------------")

	cmd := exec.Command("kustomize", "build", kustomizeDir)
	var out2 bytes.Buffer
	cmd.Stdout = &out2
	err = cmd.Run()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("----------------------OUTPUT2--------------------------")
	fmt.Println(out2.String())
	fmt.Println("----------------------OUTPUT2--------------------------")

}

Here is my go.mod.

go 1.14

require (
	k8s.io/cli-runtime v0.18.6
	sigs.k8s.io/kustomize v2.0.3+incompatible
)

kOpts.DoLegacyResourceSort undefined

While running tests in my repo, I noticed this error:

k8s.io/cli-runtime/pkg/resource/kustomizevisitor.go:41:8: kOpts.DoLegacyResourceSort undefined (type *krusty.Options has no field or method DoLegacyResourceSort)

The error is located here:

// Visit passes the result of a kustomize build to a StreamVisitor.
func (v *KustomizeVisitor) Visit(fn VisitorFunc) error {
	kOpts := krusty.MakeDefaultOptions()
	kOpts.DoLegacyResourceSort = true  // <- this is not defined
	k := krusty.MakeKustomizer(kOpts)
	m, err := k.Run(v.fSys, v.dirPath)
	if err != nil {
		return err
	}
	v.yml, err = m.AsYaml()
	if err != nil {
		return err
	}
	sv := NewStreamVisitor(
		bytes.NewReader(v.yml), v.mapper, v.dirPath, v.schema)
	return sv.Visit(fn)
}

In go.mod I have following lines:

	helm.sh/helm/v3 v3.11.2

	k8s.io/cli-runtime v0.26.3 // indirect
	sigs.k8s.io/kustomize/api v0.13.2 // indirect

In go.sum I have following lines:

helm.sh/helm/v3 v3.11.2 h1:P3cLaFxfoxaGLGJVnoPrhf1j86LC5EDINSpYSpMUkkA=
helm.sh/helm/v3 v3.11.2/go.mod h1:Hw+09mfpDiRRKAgAIZlFkPSeOkvv7Acl5McBvQyNPVw=
k8s.io/cli-runtime v0.26.3 h1:3ULe0oI28xmgeLMVXIstB+ZL5CTGvWSMVMLeHxitIuc=
k8s.io/cli-runtime v0.26.3/go.mod h1:5YEhXLV4kLt/OSy9yQwtSSNZU2Z7aTEYta1A+Jg4VC4=
sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA=
sigs.k8s.io/kustomize/api v0.13.2/go.mod h1:DUp325VVMFVcQSq+ZxyDisA8wtldwHxLZbr1g94UHsw=

sigs.k8s.io/kustomize/api is indirect, because:

sigs.k8s.io/kustomize/api
This module is necessary because sigs.k8s.io/kustomize/api/krusty is imported in:

- <REDACTED>
-- helm.sh/helm/v3/pkg/action
--- k8s.io/cli-runtime/pkg/resource

k8s.io/cli-runtime is indirect, because:

k8s.io/cli-runtime
This module is necessary because k8s.io/cli-runtime/pkg/genericclioptions is imported in:

- <REDACTED>
-- helm.sh/helm/v3/pkg/action

BearerToken ignore by ConfigFlags

Impacts helm -> this
Follow the issue here

BearerToken when provided to genericclioptions.ConfigFlags, it is ignored by while generating rest client.

Solution -

func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) {
	config, err := f.ToRawKubeConfigLoader().ClientConfig()
	// replace client-go's ErrEmptyConfig error with our custom, more verbose version
	if clientcmd.IsEmptyConfig(err) {
		return nil, ErrEmptyConfig
	}

	config.BearerToken = *f.BearerToken

	return config, err
}

Actually, this is a bug in clientcmd.DirectClientConfig. It can also be solved as listed above. However, to solve it elegantly, it should be fixed in clientcmd.

kubectl client version - v1.19.x

Inconsistency in the field `envs` for secretGenerator between the CLI and this pkg

Hello,

It seems that the latest version of kustomize CLI (3.8.2) requires for the field envs in a secretGenerator a list of the possibles files. And the latest version of this pkg, requires for that field, the property env with a string.

It would be nice if this pkg is aligned with the cli, and I can work on a PR if that's ok.

cannot find "sigs.k8s.io/kustomize/pkg/factory"

The dependency "sigs.k8s.io/kustomize/pkg/factory" does not exists.

If I do a go get ./... in my project I get:
cannot find package "sigs.k8s.io/kustomize/pkg/factory"

my Intellj Idea explains:
../k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go:24:2: cannot find package "sigs.k8s.io/kustomize/pkg/factory"

Thats right, it was deleted: kubernetes-sigs/kustomize@bce894a

I deleted my complete $GOROOT/src/k8s.io and $GOROOT/src/sigs.k8s.io directories and re-run the go get - it did not help

The cli-runtime is pulled in as sub-dependency by any other package I use for my development., not by my own. How should I deal with this?

dependency on kustomize causing compilation issues

Relevant section of the go.mod file is as below -:
k8s.io/api v0.19.4
k8s.io/apiextensions-apiserver v0.19.4 // indirect
k8s.io/apimachinery v0.19.4
k8s.io/cli-runtime v0.19.4
k8s.io/client-go v0.19.4

On compiling some kubectl plugin code, i get this error -:
go vet ./...

sigs.k8s.io/kustomize/pkg/transformers/config

vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go:71:47: cannot use api.Schema.SchemaProps.Properties (type spec.SchemaProperties) as type myProperties in argument to looksLikeAk8sType
make: *** [Makefile:95: vet] Error 2

Graph dependency shows -:
go mod graph | grep kustomize
k8s.io/[email protected] sigs.k8s.io/[email protected]+incompatible

Similar issue also noted by helm package users
kubernetes-sigs/kustomize#3262

Looks like the latest version v0.21.0 uses a fixed version of kustomize in the go.mod file.
Could we get a patch release for v0.19.x or v0.20.x ?
Its going to be a while till we get to use kubernetes1.21 and it seems that anything below [email protected] is unusable at this time ? If not, please let me know what i could do as a work around ?

The kustomize version in the mod file is quite old and it looks like the kustomize package structure has changed along the way.

genericclioptions: --version option isn't worded accurately for imported tools

I just integrated genericclioptions with my kubectl plugin https://github.com/ahmetb/kubectl-tree/

The help message prints:

      --user string                    The name of the kubeconfig user to use
  -v, --v Level                        number for the log level verbosity
      --version                        version for kubectl

However when executed, this actually prints the version of my plugin (not kubectl)

$ kubectl tree --version
kubectl version v0.4.0

I recommend we reword these "version for kubectl" and "kubectl version %s" strings to something like "print version" and "version %s".

Funny enough, kubectl --version does not actually work. :) So I'm not even sure why these strings are the way they are.

allow a cutstom io.Reader for stdin in resource.Builder

k8s.io/kubectl affords genericclioptions.IOStreams to allow overriding stdin, stdout, and stderr. However, the resource.Builder and resource.Visitor abstractions don't have the option to allow configuring a custom stdin, which ultimately leads to unexpected behavior when a consumer of the k8s.io/kubectl library overrides the stdin but their program end up still getting IO blocked on os.Stdin. So resource.Builder and resource.Visitor should provide the ability for stdin to be overridden so that k8s.io/kubectl can use that ability to override stdin when appropriate.

When using ToRawKubeConfigLoader(), the QPS/Burst Values revert to their defaults

package main

import (
	"fmt"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/client-go/rest"
)

type Option func(*genericclioptions.ConfigFlags)

func WithQPS(qps float32) Option {
	return func(o *genericclioptions.ConfigFlags) {
		fmt.Println("Setting QPS to", qps)
		o.WithDiscoveryQPS(qps)
	}
}

// WithBurst sets the burst limit for the client
func WithBurst(burst int) Option {
	return func(o *genericclioptions.ConfigFlags) {
		fmt.Println("Setting burst to", burst)
		o.WithDiscoveryBurst(burst)
	}
}

func GetKubeConfig(opts ...Option) (*rest.Config, error) {
	cf := genericclioptions.NewConfigFlags(true)
	for _, opt := range opts {
		opt(cf)
	}
	
        fmt.Printf("ConfigFlags: %+v\n", cf)

	kubeConfig, err := cf.ToRawKubeConfigLoader().ClientConfig()
	if err != nil {
		return nil, err
	}

	return kubeConfig, nil

}
func main() {
	kubeConfig, err := GetKubeConfig(WithQPS(100.0), WithBurst(100))
	if err != nil {
		panic(err)
	}
	fmt.Printf("QPS: %f\n", kubeConfig.QPS)
	fmt.Printf("Burst: %d\n", kubeConfig.Burst)
}

Program Output:

Setting QPS to 100
Setting burst to 100
ConfigFlags: &{CacheDir:0x14000395fa0 KubeConfig:0x14000395f90 ClusterName:0x14000395fb0 AuthInfoName:0x14000395fc0 Context:0x14000395fd0 Namespace:0x14000395fe0 APIServer:0x14000395ff0 TLSServerName:0x1400042a000 Insecure:0x14000217cbc CertFile:0x1400042a010 KeyFile:0x1400042a020 CAFile:0x1400042a030 BearerToken:0x1400042a040 Impersonate:0x1400042a050 ImpersonateUID:0x1400042a060 ImpersonateGroup:0x140003f4528 Username:<nil> Password:<nil> Timeout:0x14000395f80 DisableCompression:0x14000217cbd WrapConfigFn:<nil> clientConfig:<nil> clientConfigLock:{state:0 sema:0} restMapper:<nil> restMapperLock:{state:0 sema:0} discoveryClient:<nil> discoveryClientLock:{state:0 sema:0} usePersistentConfig:true discoveryBurst:100 discoveryQPS:100}
QPS: 0.000000
Burst: 0

Expected Output:

Setting QPS to 100
Setting burst to 100
QPS: 100.000000
Burst: 100

go mod file

go 1.20

require (
	k8s.io/cli-runtime v0.28.4
	k8s.io/client-go v0.28.4
)

Is there any thing that I'm missing here?

Add CertData, KeyData and CAData to genericclioptions.configflags

Add CertData, KeyData and CAData to let developper provider certificate and key as [byte] and not only throught file. These already exist in rest.config and other kubernetes interfaces.

Something like this:

type ConfigFlags struct {
	CacheDir   *string
	KubeConfig *string

	// config flags
	ClusterName      *string
	AuthInfoName     *string
	Context          *string
	Namespace        *string
	APIServer        *string
	Insecure         *bool
	CertFile         *string
	KeyFile          *string
	CAFile           *string
	BearerToken      *string
	Impersonate      *string
	ImpersonateGroup *[]string
	Username         *string
	Password         *string
	Timeout          *string

	// CertData holds PEM-encoded bytes (typically read from a client certificate file).
	// CertData takes precedence over CertFile
	CertData []byte
	// KeyData holds PEM-encoded bytes (typically read from a client certificate key file).
	// KeyData takes precedence over KeyFile
	KeyData []byte
	// CAData holds PEM-encoded bytes (typically read from a root certificates bundle).
	// CAData takes precedence over CAFile
	CAData []byte
        // ...
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.