mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #4667 from endocode/kbeecher/multi-resource
Adds support for multiple resources to kubectl
This commit is contained in:
commit
28dd73dd8c
@ -153,6 +153,15 @@ for version in "${kube_api_versions[@]}"; do
|
|||||||
kubectl get pods "${kube_flags[@]}" -lname=redis-master | grep -q 'redis-master'
|
kubectl get pods "${kube_flags[@]}" -lname=redis-master | grep -q 'redis-master'
|
||||||
[ ! $(delete pods --all pods -l name=redis-master "${kube_flags[@]}" ) ] # not --all and label selector together
|
[ ! $(delete pods --all pods -l name=redis-master "${kube_flags[@]}" ) ] # not --all and label selector together
|
||||||
kubectl delete --all pods "${kube_flags[@]}" # --all remove all the pods
|
kubectl delete --all pods "${kube_flags[@]}" # --all remove all the pods
|
||||||
|
kubectl create -f examples/guestbook/redis-master.json "${kube_flags[@]}"
|
||||||
|
kubectl create -f examples/redis/redis-proxy.yaml "${kube_flags[@]}"
|
||||||
|
kubectl get pods redis-master redis-proxy "${kube_flags[@]}"
|
||||||
|
kubectl delete pods redis-master redis-proxy # delete multiple pods at once
|
||||||
|
howmanypods="$(kubectl get pods -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
|
[ "$howmanypods" -eq 0 ]
|
||||||
|
kubectl create -f examples/guestbook/redis-master.json "${kube_flags[@]}"
|
||||||
|
kubectl create -f examples/redis/redis-proxy.yaml "${kube_flags[@]}"
|
||||||
|
kubectl stop pods redis-master redis-proxy # stop multiple pods at once
|
||||||
howmanypods="$(kubectl get pods -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
howmanypods="$(kubectl get pods -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
[ "$howmanypods" -eq 0 ]
|
[ "$howmanypods" -eq 0 ]
|
||||||
kubectl create -f examples/guestbook/redis-master.json "${kube_flags[@]}"
|
kubectl create -f examples/guestbook/redis-master.json "${kube_flags[@]}"
|
||||||
@ -202,6 +211,12 @@ __EOF__
|
|||||||
kubectl get services "${kube_flags[@]}"
|
kubectl get services "${kube_flags[@]}"
|
||||||
kubectl get services "service-${version}-test" "${kube_flags[@]}"
|
kubectl get services "service-${version}-test" "${kube_flags[@]}"
|
||||||
kubectl delete service frontend "${kube_flags[@]}"
|
kubectl delete service frontend "${kube_flags[@]}"
|
||||||
|
servicesbefore="$(kubectl get services -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
|
kubectl create -f examples/guestbook/frontend-service.json "${kube_flags[@]}"
|
||||||
|
kubectl create -f examples/guestbook/redis-slave-service.json "${kube_flags[@]}"
|
||||||
|
kubectl delete services frontend redisslave # delete multiple services at once
|
||||||
|
servicesafter="$(kubectl get services -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
|
[ "$((${servicesafter} - ${servicesbefore}))" -eq 0 ]
|
||||||
|
|
||||||
kube::log::status "Testing kubectl(${version}:replicationcontrollers)"
|
kube::log::status "Testing kubectl(${version}:replicationcontrollers)"
|
||||||
kubectl get replicationcontrollers "${kube_flags[@]}"
|
kubectl get replicationcontrollers "${kube_flags[@]}"
|
||||||
@ -216,6 +231,12 @@ __EOF__
|
|||||||
#resize replicas-only
|
#resize replicas-only
|
||||||
kubectl resize --replicas=3 replicationcontrollers frontend-controller "${kube_flags[@]}"
|
kubectl resize --replicas=3 replicationcontrollers frontend-controller "${kube_flags[@]}"
|
||||||
kubectl delete rc frontend-controller "${kube_flags[@]}"
|
kubectl delete rc frontend-controller "${kube_flags[@]}"
|
||||||
|
rcsbefore="$(kubectl get replicationcontrollers -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
|
kubectl create -f examples/guestbook/frontend-controller.json "${kube_flags[@]}"
|
||||||
|
kubectl create -f examples/guestbook/redis-slave-controller.json "${kube_flags[@]}"
|
||||||
|
kubectl delete rc frontend-controller redis-slave-controller "${kube_flags[@]}" # delete multiple controllers at once
|
||||||
|
rcsafter="$(kubectl get replicationcontrollers -o template -t "{{ len .items }}" "${kube_flags[@]}")"
|
||||||
|
[ "$((${rcsafter} - ${rcsbefore}))" -eq 0 ]
|
||||||
|
|
||||||
kube::log::status "Testing kubectl(${version}:nodes)"
|
kube::log::status "Testing kubectl(${version}:nodes)"
|
||||||
kubectl get nodes "${kube_flags[@]}"
|
kubectl get nodes "${kube_flags[@]}"
|
||||||
|
@ -48,7 +48,7 @@ type Builder struct {
|
|||||||
resources []string
|
resources []string
|
||||||
|
|
||||||
namespace string
|
namespace string
|
||||||
name string
|
names []string
|
||||||
|
|
||||||
defaultNamespace bool
|
defaultNamespace bool
|
||||||
requireNamespace bool
|
requireNamespace bool
|
||||||
@ -217,22 +217,25 @@ func (b *Builder) SelectAllParam(selectAll bool) *Builder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResourceTypeOrNameArgs indicates that the builder should accept one or two arguments
|
// ResourceTypeOrNameArgs indicates that the builder should accept arguments
|
||||||
// of the form `(<type1>[,<type2>,...]|<type> <name>)`. When one argument is received, the types
|
// of the form `(<type1>[,<type2>,...]|<type> <name1>[,<name2>,...])`. When one argument is
|
||||||
// provided will be retrieved from the server (and be comma delimited). When two arguments are
|
// received, the types provided will be retrieved from the server (and be comma delimited).
|
||||||
// received, they must be a single type and name. If more than two arguments are provided an
|
// When two or more arguments are received, they must be a single type and resource name(s).
|
||||||
// error is set. The allowEmptySelector permits to select all the resources (via Everything func).
|
// The allowEmptySelector permits to select all the resources (via Everything func).
|
||||||
func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string) *Builder {
|
func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string) *Builder {
|
||||||
switch len(args) {
|
switch {
|
||||||
case 2:
|
case len(args) > 2:
|
||||||
b.name = args[1]
|
b.names = append(b.names, args[1:]...)
|
||||||
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
||||||
case 1:
|
case len(args) == 2:
|
||||||
|
b.names = append(b.names, args[1])
|
||||||
|
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
||||||
|
case len(args) == 1:
|
||||||
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
||||||
if b.selector == nil && allowEmptySelector {
|
if b.selector == nil && allowEmptySelector {
|
||||||
b.selector = labels.Everything()
|
b.selector = labels.Everything()
|
||||||
}
|
}
|
||||||
case 0:
|
case len(args) == 0:
|
||||||
default:
|
default:
|
||||||
b.errs = append(b.errs, fmt.Errorf("when passing arguments, must be resource or resource and name"))
|
b.errs = append(b.errs, fmt.Errorf("when passing arguments, must be resource or resource and name"))
|
||||||
}
|
}
|
||||||
@ -244,7 +247,7 @@ func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string
|
|||||||
func (b *Builder) ResourceTypeAndNameArgs(args ...string) *Builder {
|
func (b *Builder) ResourceTypeAndNameArgs(args ...string) *Builder {
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 2:
|
case 2:
|
||||||
b.name = args[1]
|
b.names = append(b.names, args[1])
|
||||||
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
b.ResourceTypes(SplitResourceArgument(args[0])...)
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
@ -312,7 +315,7 @@ func (b *Builder) visitorResult() *Result {
|
|||||||
|
|
||||||
// visit selectors
|
// visit selectors
|
||||||
if b.selector != nil {
|
if b.selector != nil {
|
||||||
if len(b.name) != 0 {
|
if len(b.names) != 0 {
|
||||||
return &Result{err: fmt.Errorf("name cannot be provided when a selector is specified")}
|
return &Result{err: fmt.Errorf("name cannot be provided when a selector is specified")}
|
||||||
}
|
}
|
||||||
if len(b.resources) == 0 {
|
if len(b.resources) == 0 {
|
||||||
@ -349,38 +352,49 @@ func (b *Builder) visitorResult() *Result {
|
|||||||
return &Result{visitor: VisitorList(visitors), sources: visitors}
|
return &Result{visitor: VisitorList(visitors), sources: visitors}
|
||||||
}
|
}
|
||||||
|
|
||||||
// visit single item specified by name
|
// visit items specified by name
|
||||||
if len(b.name) != 0 {
|
if len(b.names) != 0 {
|
||||||
|
isSingular := len(b.names) == 1
|
||||||
|
|
||||||
if len(b.paths) != 0 {
|
if len(b.paths) != 0 {
|
||||||
return &Result{singular: true, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify a resource by arguments as well")}
|
return &Result{singular: isSingular, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify a resource by arguments as well")}
|
||||||
}
|
}
|
||||||
if len(b.resources) == 0 {
|
if len(b.resources) == 0 {
|
||||||
return &Result{singular: true, err: fmt.Errorf("you must provide a resource and a resource name together")}
|
return &Result{singular: isSingular, err: fmt.Errorf("you must provide a resource and a resource name together")}
|
||||||
}
|
}
|
||||||
if len(b.resources) > 1 {
|
if len(b.resources) > 1 {
|
||||||
return &Result{singular: true, err: fmt.Errorf("you must specify only one resource")}
|
return &Result{singular: isSingular, err: fmt.Errorf("you must specify only one resource")}
|
||||||
}
|
}
|
||||||
|
|
||||||
mappings, err := b.resourceMappings()
|
mappings, err := b.resourceMappings()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Result{singular: true, err: err}
|
return &Result{singular: isSingular, err: err}
|
||||||
}
|
}
|
||||||
mapping := mappings[0]
|
mapping := mappings[0]
|
||||||
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
|
|
||||||
b.namespace = ""
|
|
||||||
} else {
|
|
||||||
if len(b.namespace) == 0 {
|
|
||||||
return &Result{singular: true, err: fmt.Errorf("namespace may not be empty when retrieving a resource by name")}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client, err := b.mapper.ClientForMapping(mapping)
|
client, err := b.mapper.ClientForMapping(mapping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Result{singular: true, err: err}
|
return &Result{err: err}
|
||||||
}
|
}
|
||||||
info := NewInfo(client, mappings[0], b.namespace, b.name)
|
|
||||||
if err := info.Get(); err != nil {
|
selectorNamespace := b.namespace
|
||||||
return &Result{singular: true, err: err}
|
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
|
||||||
|
selectorNamespace = ""
|
||||||
|
} else {
|
||||||
|
if len(b.namespace) == 0 {
|
||||||
|
return &Result{singular: isSingular, err: fmt.Errorf("namespace may not be empty when retrieving a resource by name")}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &Result{singular: true, visitor: info, sources: []Visitor{info}}
|
|
||||||
|
visitors := []Visitor{}
|
||||||
|
for _, name := range b.names {
|
||||||
|
info := NewInfo(client, mapping, selectorNamespace, name)
|
||||||
|
if err := info.Get(); err != nil {
|
||||||
|
return &Result{singular: isSingular, err: err}
|
||||||
|
}
|
||||||
|
visitors = append(visitors, info)
|
||||||
|
}
|
||||||
|
return &Result{singular: isSingular, visitor: VisitorList(visitors), sources: visitors}
|
||||||
}
|
}
|
||||||
|
|
||||||
// visit items specified by paths
|
// visit items specified by paths
|
||||||
|
Loading…
Reference in New Issue
Block a user