mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Merge pull request #50497 from dixudx/kubectl-include-uninitialized
Automatic merge from submit-queue (batch tested with PRs 51301, 50497, 50112, 48184, 50993) Introduce new flag "--include-uninitialized" to kubectl **What this PR does / why we need it**: Introduce `--include-uninitialized` as a global flag to kubectl **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #49035 **Special notes for your reviewer**: /assign @caesarxuchao @smarterclayton @ahmetb @deads2k **Release note**: ```release-note Add flag "--include-uninitialized" to kubectl annotate, apply, edit-last-applied, delete, describe, edit, get, label, set. "--include-uninitialized=true" makes kubectl commands apply to uninitialized objects, which by default are ignored if the names of the objects are not provided. "--all" also makes kubectl commands apply to uninitialized objects. Please see the [initializer](https://kubernetes.io/docs/admin/extensible-admission-controllers/) doc for more details. ```
This commit is contained in:
commit
5c0b265a9b
@ -4759,3 +4759,271 @@ runTests() {
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_initializer_tests() {
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
create_and_use_new_namespace
|
||||
kube::log::status "Testing --include-uninitialized"
|
||||
|
||||
### Create a deployment
|
||||
kubectl create --request-timeout=1 -f hack/testdata/initializer-deployments.yaml 2>&1 "${kube_flags[@]}" || true
|
||||
|
||||
### Test kubectl get --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl get deployments 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "No resources found" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'No resources found'
|
||||
# Command
|
||||
output_message=$(kubectl get deployments --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "No resources found" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'No resources found'
|
||||
# Command
|
||||
output_message=$(kubectl get deployments --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: I assume "web" is the deployment name
|
||||
kube::test::if_has_string "${output_message}" 'web'
|
||||
# Command
|
||||
output_message=$(kubectl get deployments web 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: I assume "web" is the deployment name
|
||||
kube::test::if_has_string "${output_message}" 'web'
|
||||
# Command
|
||||
output_message=$(kubectl get deployments --show-all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "No resources found" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'No resources found'
|
||||
|
||||
### Test kubectl describe --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl describe deployments 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "run=web" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'run=web'
|
||||
# Command
|
||||
output_message=$(kubectl describe deployments --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "run=web" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'run=web'
|
||||
# Command
|
||||
output_message=$(kubectl describe deployments --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl describe deployments web --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "run=web" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'run=web'
|
||||
# Command
|
||||
output_message=$(kubectl describe deployments web --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "run=web" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'run=web'
|
||||
|
||||
### Test kubectl label --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey1=labelvalue1 --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: web is labelled
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" labeled'
|
||||
kube::test::get_object_assert 'deployments web' "{{${labels_field}.labelkey1}}" 'labelvalue1'
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey2=labelvalue2 --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey3=labelvalue3 -l run=web 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey4=labelvalue4 -l run=web --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: web is labelled
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" labeled'
|
||||
kube::test::get_object_assert 'deployments web' "{{${labels_field}.labelkey4}}" 'labelvalue4'
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey5=labelvalue5 -l run=web --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl label deployments labelkey6=labelvalue6 -l run=web --all --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: web is labelled
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" labeled'
|
||||
kube::test::get_object_assert 'deployments web' "{{${labels_field}.labelkey6}}" 'labelvalue6'
|
||||
# Command
|
||||
output_message=$(kubectl label deployments web labelkey7=labelvalue7 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: web is labelled
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" labeled'
|
||||
kube::test::get_object_assert 'deployments web' "{{${labels_field}.labelkey7}}" 'labelvalue7'
|
||||
# Found All Labels
|
||||
kube::test::get_object_assert 'deployments web' "{{${labels_field}}}" 'map[labelkey1:labelvalue1 labelkey4:labelvalue4 labelkey6:labelvalue6 labelkey7:labelvalue7 run:web]'
|
||||
|
||||
### Test kubectl annotate --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey1=annotatevalue1 --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: DEPLOYMENT has annotation
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" annotated'
|
||||
kube::test::get_object_assert 'deployments web' "{{${annotations_field}.annotatekey1}}" 'annotatevalue1'
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey2=annotatevalue2 --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey3=annotatevalue3 -l run=web 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey4=annotatevalue4 -l run=web --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: DEPLOYMENT has annotation
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" annotated'
|
||||
kube::test::get_object_assert 'deployments web' "{{${annotations_field}.annotatekey4}}" 'annotatevalue4'
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey5=annotatevalue5 -l run=web --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments annotatekey6=annotatevalue6 -l run=web --all --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: DEPLOYMENT has annotation
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" annotated'
|
||||
kube::test::get_object_assert 'deployments web' "{{${annotations_field}.annotatekey6}}" 'annotatevalue6'
|
||||
# Command
|
||||
output_message=$(kubectl annotate deployments web annotatekey7=annotatevalue7 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: web DEPLOYMENT has annotation
|
||||
kube::test::if_has_string "${output_message}" 'deployment "web" annotated'
|
||||
kube::test::get_object_assert 'deployments web' "{{${annotations_field}.annotatekey7}}" 'annotatevalue7'
|
||||
|
||||
### Test kubectl edit --include-uninitialized
|
||||
[ "$(EDITOR=cat kubectl edit deployments 2>&1 "${kube_flags[@]}" | grep 'edit cancelled, no objects found')" ]
|
||||
[ "$(EDITOR=cat kubectl edit deployments --include-uninitialized 2>&1 "${kube_flags[@]}" | grep 'Edit cancelled, no changes made.')" ]
|
||||
|
||||
### Test kubectl set image --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl set image deployments *=nginx:1.11 --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "image updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'image updated'
|
||||
# Command
|
||||
output_message=$(kubectl set image deployments *=nginx:1.11 --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set image deployments *=nginx:1.11 -l run=web 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set image deployments *=nginx:1.12 -l run=web --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "image updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'image updated'
|
||||
# Command
|
||||
output_message=$(kubectl set image deployments *=nginx:1.13 -l run=web --include-uninitialized --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "image updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'image updated'
|
||||
|
||||
### Test kubectl set resources --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl set resources deployments --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=256Mi --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "resource requirements updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'resource requirements updated'
|
||||
# Command
|
||||
output_message=$(kubectl set resources deployments --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=256Mi --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set resources deployments --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=256Mi -l run=web 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set resources deployments --limits=cpu=200m,memory=512Mi --requests=cpu=200m,memory=256Mi -l run=web --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "resource requirements updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'resource requirements updated'
|
||||
# Command
|
||||
output_message=$(kubectl set resources deployments --limits=cpu=200m,memory=512Mi --requests=cpu=100m,memory=512Mi -l run=web --include-uninitialized --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "resource requirements updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'resource requirements updated'
|
||||
|
||||
### Test kubectl set selector --include-uninitialized
|
||||
# Create a service with initializer
|
||||
kubectl create --request-timeout=1 -f hack/testdata/initializer-redis-master-service.yaml 2>&1 "${kube_flags[@]}" || true
|
||||
# Command
|
||||
output_message=$(kubectl set selector services role=padawan --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "selector updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'selector updated'
|
||||
# Command
|
||||
output_message=$(kubectl set selector services role=padawan --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
|
||||
### Test kubectl set subject --include-uninitialized
|
||||
# Create a create clusterrolebinding with initializer
|
||||
kubectl create --request-timeout=1 -f hack/testdata/initializer-clusterrolebinding.yaml 2>&1 "${kube_flags[@]}" || true
|
||||
kube::test::get_object_assert clusterrolebinding/super-admin "{{range.subjects}}{{.name}}:{{end}}" 'super-admin:'
|
||||
# Command
|
||||
output_message=$(kubectl set subject clusterrolebinding --user=foo --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "subjects updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'subjects updated'
|
||||
# Command
|
||||
output_message=$(kubectl set subject clusterrolebinding --user=foo --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set subject clusterrolebinding --user=foo -l clusterrolebinding=super 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
# Command
|
||||
output_message=$(kubectl set subject clusterrolebinding --user=foo -l clusterrolebinding=super --include-uninitialized 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "subjects updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'subjects updated'
|
||||
# Command
|
||||
output_message=$(kubectl set subject clusterrolebinding --user=foo -l clusterrolebinding=super --include-uninitialized --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "subjects updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'subjects updated'
|
||||
|
||||
### Test kubectl set serviceaccount --include-uninitialized
|
||||
# Command
|
||||
output_message=$(kubectl set serviceaccount deployment serviceaccount1 --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "serviceaccount updated" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'serviceaccount updated'
|
||||
# Command
|
||||
output_message=$(kubectl set serviceaccount deployment serviceaccount1 --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The output should be empty
|
||||
kube::test::if_empty_string "${output_message}"
|
||||
|
||||
### Test kubectl delete --include-uninitialized
|
||||
kube::test::get_object_assert clusterrolebinding/super-admin "{{range.subjects}}{{.name}}:{{end}}" 'super-admin:'
|
||||
# Command
|
||||
output_message=$(kubectl delete clusterrolebinding --all --include-uninitialized=false 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "No resources found" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'No resources found'
|
||||
# Command
|
||||
output_message=$(kubectl delete clusterrolebinding --all 2>&1 "${kube_flags[@]}")
|
||||
# Post-condition: The text "deleted" should be part of the output
|
||||
kube::test::if_has_string "${output_message}" 'deleted'
|
||||
kube::test::get_object_assert clusterrolebinding/super-admin "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
|
||||
### Test kubectl apply --include-uninitialized
|
||||
# Pre-Condition: no POD exists
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# apply pod a
|
||||
kubectl apply --prune --request-timeout=20 --include-uninitialized=false --all -f hack/testdata/prune/a.yaml "${kube_flags[@]}" 2>&1
|
||||
# check right pod exists
|
||||
kube::test::get_object_assert pods/a "{{${id_field}}}" 'a'
|
||||
# Post-condition: Other uninitialized resources should not be pruned
|
||||
kube::test::get_object_assert deployments "{{range.items}}{{$id_field}}:{{end}}" 'web'
|
||||
kube::test::get_object_assert services/redis-master "{{range.items}}{{$id_field}}:{{end}}" 'redis-master'
|
||||
# cleanup
|
||||
kubectl delete pod a
|
||||
# apply pod a and prune uninitialized deployments web
|
||||
kubectl apply --prune --request-timeout=20 --all -f hack/testdata/prune/a.yaml "${kube_flags[@]}" 2>&1
|
||||
# check right pod exists
|
||||
kube::test::get_object_assert pods/a "{{${id_field}}}" 'a'
|
||||
# Post-condition: Other uninitialized resources should not be pruned
|
||||
kube::test::get_object_assert deployments/web "{{range.items}}{{$id_field}}:{{end}}" 'web'
|
||||
kube::test::get_object_assert services/redis-master "{{range.items}}{{$id_field}}:{{end}}" 'redis-master'
|
||||
# cleanup
|
||||
kubectl delete pod a
|
||||
# apply pod a and prune uninitialized deployments web
|
||||
kubectl apply --prune --request-timeout=20 --include-uninitialized --all -f hack/testdata/prune/a.yaml "${kube_flags[@]}" 2>&1
|
||||
# check right pod exists
|
||||
kube::test::get_object_assert pods/a "{{${id_field}}}" 'a'
|
||||
# Post-condition: Other uninitialized resources should not be pruned
|
||||
kube::test::get_object_assert deployments/web "{{range.items}}{{$id_field}}:{{end}}" 'web'
|
||||
kube::test::get_object_assert services/redis-master "{{range.items}}{{$id_field}}:{{end}}" 'redis-master'
|
||||
# cleanup
|
||||
kubectl delete pod a
|
||||
kubectl delete --request-timeout=1 deploy web
|
||||
kubectl delete --request-timeout=1 service redis-master
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
|
17
hack/testdata/initializer-clusterrolebinding.yaml
vendored
Normal file
17
hack/testdata/initializer-clusterrolebinding.yaml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: super-admin
|
||||
initializers:
|
||||
pending:
|
||||
- name: podimage.initializer.com
|
||||
labels:
|
||||
clusterrolebinding: super
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: admin
|
||||
subjects:
|
||||
- apiGroup: rbac.authorization.k8s.io
|
||||
kind: User
|
||||
name: super-admin
|
25
hack/testdata/initializer-deployments.yaml
vendored
Normal file
25
hack/testdata/initializer-deployments.yaml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
initializers:
|
||||
pending:
|
||||
- name: podimage.initializer.com
|
||||
labels:
|
||||
run: web
|
||||
spec:
|
||||
replicas: 5
|
||||
selector:
|
||||
matchLabels:
|
||||
run: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
run: web
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.10
|
||||
name: web
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
19
hack/testdata/initializer-redis-master-service.yaml
vendored
Normal file
19
hack/testdata/initializer-redis-master-service.yaml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-master
|
||||
labels:
|
||||
app: redis
|
||||
role: master
|
||||
tier: backend
|
||||
initializers:
|
||||
pending:
|
||||
- name: podimage.initializer.com
|
||||
spec:
|
||||
ports:
|
||||
- port: 6379
|
||||
targetPort: 6379
|
||||
selector:
|
||||
app: redis
|
||||
role: master
|
||||
tier: backend
|
@ -128,10 +128,11 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
ArgAliases: argAliases,
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
cmd.Flags().Bool("overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.")
|
||||
cmd.Flags().Bool("local", false, "If true, annotation will NOT contact api-server but run locally.")
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).")
|
||||
cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.")
|
||||
cmd.Flags().String("resource-version", "", i18n.T("If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource."))
|
||||
usage := "identifying the resource to update the annotation"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
@ -190,10 +191,12 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
b := builder.
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.local {
|
||||
|
@ -118,7 +118,7 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.MarkFlagRequired("filename")
|
||||
cmd.Flags().Bool("overwrite", true, "Automatically resolve conflicts between the modified and live configuration by using values from the modified configuration")
|
||||
cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.")
|
||||
cmd.Flags().BoolVar(&options.Prune, "prune", false, "Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.")
|
||||
cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "Only relevant during a prune or a force apply. If true, cascade the deletion of the resources managed by pruned or deleted resources (e.g. Pods created by a ReplicationController).")
|
||||
cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Only relevant during a prune or a force apply. Period of time in seconds given to pruned or deleted resources to terminate gracefully. Ignored if negative.")
|
||||
cmd.Flags().BoolVar(&options.Force, "force", false, fmt.Sprintf("Delete and re-create the specified resource, when PATCH encounters conflict and has retried for %d times.", maxPatchRetry))
|
||||
@ -131,6 +131,7 @@ func NewCmdApply(baseName string, f cmdutil.Factory, out, errOut io.Writer) *cob
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddInclude3rdPartyFlags(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
|
||||
// apply subcommands
|
||||
cmd.AddCommand(NewCmdApplyViewLastApplied(f, out, errOut))
|
||||
@ -214,12 +215,17 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti
|
||||
return err
|
||||
}
|
||||
|
||||
// include the uninitialized objects by default if --prune is true
|
||||
// unless explicitly set --include-uninitialized=false
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, options.Prune)
|
||||
|
||||
r := builder.
|
||||
Schema(schema).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
SelectorParam(options.Selector).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten().
|
||||
Do()
|
||||
err = r.Err()
|
||||
@ -381,13 +387,13 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti
|
||||
|
||||
for n := range visitedNamespaces {
|
||||
for _, m := range namespacedRESTMappings {
|
||||
if err := p.prune(n, m, shortOutput); err != nil {
|
||||
if err := p.prune(n, m, shortOutput, includeUninitialized); err != nil {
|
||||
return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, m := range nonNamespacedRESTMappings {
|
||||
if err := p.prune(metav1.NamespaceNone, m, shortOutput); err != nil {
|
||||
if err := p.prune(metav1.NamespaceNone, m, shortOutput, includeUninitialized); err != nil {
|
||||
return fmt.Errorf("error pruning nonNamespaced object %v: %v", m.GroupVersionKind, err)
|
||||
}
|
||||
}
|
||||
@ -460,13 +466,13 @@ type pruner struct {
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput bool) error {
|
||||
func (p *pruner) prune(namespace string, mapping *meta.RESTMapping, shortOutput, includeUninitialized bool) error {
|
||||
c, err := p.clientFunc(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objList, err := resource.NewHelper(c, mapping).List(namespace, mapping.GroupVersionKind.Version, p.selector, false)
|
||||
objList, err := resource.NewHelper(c, mapping).List(namespace, mapping.GroupVersionKind.Version, p.selector, false, includeUninitialized)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra
|
||||
Example: applyEditLastAppliedExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.ChangeCause = f.Command(cmd, false)
|
||||
if err := options.Complete(f, out, errOut, args); err != nil {
|
||||
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
if err := options.Run(); err != nil {
|
||||
@ -99,6 +99,7 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra
|
||||
cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", runtime.GOOS == "windows",
|
||||
"Defaults to the line ending native to your platform.")
|
||||
cmdutil.AddRecordVarFlag(cmd, &options.Record)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ func RunEditOnCreate(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Comman
|
||||
ChangeCause: f.Command(cmd, false),
|
||||
Include3rdParty: cmdutil.GetFlagBool(cmd, "include-extended-apis"),
|
||||
}
|
||||
err := editOptions.Complete(f, out, errOut, []string{})
|
||||
err := editOptions.Complete(f, out, errOut, []string{}, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
Example: delete_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
if err := options.Complete(f, out, errOut, args); err != nil {
|
||||
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
if err := options.Validate(cmd); err != nil {
|
||||
@ -149,8 +149,8 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
}
|
||||
usage := "containing the resource to delete."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on.")
|
||||
cmd.Flags().BoolVar(&options.DeleteAll, "all", false, "Select all resources in the namespace of the specified resource types.")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones.")
|
||||
cmd.Flags().BoolVar(&options.DeleteAll, "all", false, "Delete all resources, including uninitialized ones, in the namespace of the specified resource types.")
|
||||
cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.")
|
||||
cmd.Flags().BoolVar(&options.Cascade, "cascade", true, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.")
|
||||
cmd.Flags().IntVar(&options.GracePeriod, "grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
|
||||
@ -159,10 +159,11 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
cmd.Flags().DurationVar(&options.Timeout, "timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object")
|
||||
cmdutil.AddOutputVarFlagsForMutation(cmd, &options.Output)
|
||||
cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string) error {
|
||||
func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error {
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -180,11 +181,13 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
|
||||
}
|
||||
|
||||
o.Mapper = mapper
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
r := builder.
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
SelectorParam(o.Selector).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
SelectAllParam(o.DeleteAll).
|
||||
ResourceTypeOrNameArgs(false, args...).RequireObject(false).
|
||||
Flatten().
|
||||
|
@ -26,6 +26,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -41,6 +43,13 @@ import (
|
||||
|
||||
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
|
||||
|
||||
var fakecmd = &cobra.Command{
|
||||
Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
},
|
||||
}
|
||||
|
||||
func TestDeleteObjectByTuple(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
_, _, rc := testData()
|
||||
@ -345,7 +354,7 @@ func TestDeleteObjectNotFound(t *testing.T) {
|
||||
Cascade: false,
|
||||
Output: "name",
|
||||
}
|
||||
err := options.Complete(f, buf, errBuf, []string{})
|
||||
err := options.Complete(f, buf, errBuf, []string{}, fakecmd)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -426,7 +435,7 @@ func TestDeleteAllNotFound(t *testing.T) {
|
||||
IgnoreNotFound: false,
|
||||
Output: "name",
|
||||
}
|
||||
err := options.Complete(f, buf, errBuf, []string{"services"})
|
||||
err := options.Complete(f, buf, errBuf, []string{"services"}, fakecmd)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -546,7 +555,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
|
||||
Cascade: false,
|
||||
Output: "name",
|
||||
}
|
||||
err := options.Complete(f, buf, errBuf, []string{})
|
||||
err := options.Complete(f, buf, errBuf, []string{}, fakecmd)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -714,7 +723,7 @@ func TestResourceErrors(t *testing.T) {
|
||||
Cascade: false,
|
||||
Output: "name",
|
||||
}
|
||||
err := options.Complete(f, buf, errBuf, testCase.args)
|
||||
err := options.Complete(f, buf, errBuf, testCase.args, fakecmd)
|
||||
if !testCase.errFn(err) {
|
||||
t.Errorf("%s: unexpected error: %v", k, err)
|
||||
continue
|
||||
|
@ -39,6 +39,7 @@ import (
|
||||
var (
|
||||
describe_long = templates.LongDesc(`
|
||||
Show details of a specific resource or group of resources.
|
||||
It includes the uninitialized objects, unless --include-uninitialized=false is explicitly set.
|
||||
This command joins many API calls together to form a detailed description of a
|
||||
given resource or group of resources.
|
||||
|
||||
@ -97,6 +98,7 @@ func NewCmdDescribe(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command {
|
||||
cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
|
||||
cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.")
|
||||
cmdutil.AddInclude3rdPartyFlags(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -120,11 +122,16 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a
|
||||
return err
|
||||
}
|
||||
|
||||
// include the uninitialized objects by default
|
||||
// unless user explicitly set --include-uninitialized=false
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, true)
|
||||
|
||||
r := builder.
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
|
||||
FilenameParam(enforceNamespace, options).
|
||||
SelectorParam(selector).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
Flatten().
|
||||
Do()
|
||||
|
@ -93,7 +93,7 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
Example: fmt.Sprintf(editExample),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.ChangeCause = f.Command(cmd, false)
|
||||
if err := options.Complete(f, out, errOut, args); err != nil {
|
||||
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
if err := options.Run(); err != nil {
|
||||
@ -115,5 +115,6 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
cmdutil.AddApplyAnnotationVarFlags(cmd, &options.ApplyAnnotation)
|
||||
cmdutil.AddRecordVarFlag(cmd, &options.Record)
|
||||
cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ var (
|
||||
|
||||
This command will hide resources that have completed, such as pods that are
|
||||
in the Succeeded or Failed phases. You can see the full results for any
|
||||
resource by providing the '--show-all' flag.
|
||||
resource by providing the '--show-all' flag, but this flag does not include
|
||||
the uninitialized objects by default, unless '--include-uninitialized' is explicitly set.
|
||||
|
||||
By specifying the output as 'template' and providing a Go template as the value
|
||||
of the --template flag, you can filter the attributes of the fetched resources.`)
|
||||
@ -127,7 +128,8 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.")
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.")
|
||||
cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.")
|
||||
cmd.Flags().Bool("show-kind", false, "If present, list the resource type for the requested object(s).")
|
||||
cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
|
||||
@ -200,6 +202,15 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
|
||||
|
||||
// handle watch separately since we cannot watch multiple resource types
|
||||
isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only")
|
||||
|
||||
var includeUninitialized bool
|
||||
if isWatch && len(args) == 2 {
|
||||
// include the uninitialized one for watching on a single object
|
||||
// unless explicitly set --include-uninitialized=false
|
||||
includeUninitialized = true
|
||||
}
|
||||
includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, includeUninitialized)
|
||||
|
||||
if isWatch || isWatchOnly {
|
||||
builder, err := f.NewUnstructuredBuilder(true)
|
||||
if err != nil {
|
||||
@ -211,6 +222,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
SelectorParam(selector).
|
||||
ExportParam(export).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
SingleResourceType().
|
||||
Latest().
|
||||
@ -300,6 +312,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
SelectorParam(selector).
|
||||
ExportParam(export).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
ContinueOnError().
|
||||
Latest().
|
||||
|
@ -128,14 +128,15 @@ func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.")
|
||||
cmd.Flags().Bool("local", false, "If true, label will NOT contact api-server but run locally.")
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).")
|
||||
cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().String("resource-version", "", i18n.T("If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource."))
|
||||
usage := "identifying the resource to update the labels"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddInclude3rdPartyFlags(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -185,10 +186,12 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
b := builder.
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.local {
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
)
|
||||
|
||||
@ -62,7 +62,7 @@ func handlePodUpdateError(out io.Writer, err error, resource string) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if ok := kcmdutil.PrintErrorWithCauses(err, out); ok {
|
||||
if ok := cmdutil.PrintErrorWithCauses(err, out); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -105,11 +105,12 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
usage := "identifying the resource to get from a server."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.")
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -137,10 +138,12 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder(!o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
if !o.Local {
|
||||
builder = builder.
|
||||
|
@ -114,12 +114,13 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.
|
||||
//kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||
usage := "identifying the resource to get from a server."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones,supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", "*", "The names of containers in the selected pod templates to change, all containers are selected by default - may use wildcards")
|
||||
cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set resources will NOT contact api-server but run locally.")
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
cmd.Flags().StringVar(&options.Limits, "limits", options.Limits, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.")
|
||||
cmd.Flags().StringVar(&options.Requests, "requests", options.Requests, "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.")
|
||||
return cmd
|
||||
@ -141,11 +142,12 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder(!o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
//FilenameParam(enforceNamespace, o.Filenames...).
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.Local {
|
||||
|
@ -89,13 +89,14 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
},
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().Bool("all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().Bool("local", false, "If true, set selector will NOT contact api-server but run locally.")
|
||||
cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")
|
||||
usage := "the resource to update the selectors"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.fileOptions, usage)
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -121,10 +122,12 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
o.builder = f.NewBuilder(!o.local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.fileOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.local {
|
||||
|
@ -95,10 +95,11 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command
|
||||
|
||||
usage := "identifying the resource to get from a server."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &saConfig.fileNameOptions, usage)
|
||||
cmd.Flags().BoolVar(&saConfig.all, "all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().BoolVar(&saConfig.all, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().BoolVar(&saConfig.local, "local", false, "If true, set image will NOT contact api-server but run locally.")
|
||||
cmdutil.AddRecordFlag(cmd)
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -124,9 +125,11 @@ func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Com
|
||||
}
|
||||
saConfig.serviceAccountName = args[len(args)-1]
|
||||
resources := args[:len(args)-1]
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder(!saConfig.local).ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &saConfig.fileNameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
if !saConfig.local {
|
||||
builder.ResourceTypeOrNameArgs(saConfig.all, resources...).
|
||||
|
@ -98,13 +98,14 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
usage := "the resource to update the subjects"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.All, "all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", "", "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set resources will NOT contact api-server but run locally.")
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmd.Flags().StringArrayVar(&options.Users, "user", []string{}, "Usernames to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&options.Groups, "group", []string{}, "Groups to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&options.ServiceAccounts, "serviceaccount", []string{}, "Service accounts to bind to the role")
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -123,10 +124,12 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder(!o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.Local {
|
||||
|
@ -23,6 +23,7 @@ go_library(
|
||||
"//pkg/printers:go_default_library",
|
||||
"//vendor/github.com/evanphx/json-patch:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
|
||||
"github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@ -86,7 +87,7 @@ type editPrinterOptions struct {
|
||||
}
|
||||
|
||||
// Complete completes all the required options
|
||||
func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string) error {
|
||||
func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error {
|
||||
if o.EditMode != NormalEditMode && o.EditMode != EditBeforeCreateMode && o.EditMode != ApplyEditMode {
|
||||
return fmt.Errorf("unsupported edit mode %q", o.EditMode)
|
||||
}
|
||||
@ -118,8 +119,10 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []
|
||||
// when do normal edit or apply edit we need to always retrieve the latest resource from server
|
||||
b = b.ResourceTypeOrNameArgs(true, args...).Latest()
|
||||
}
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
r := b.NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
ContinueOnError().
|
||||
Flatten().
|
||||
Do()
|
||||
@ -133,6 +136,7 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []
|
||||
// resource builder to read objects from edited data
|
||||
return resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Stream(bytes.NewReader(data), "edited-file").
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
ContinueOnError().
|
||||
Flatten().
|
||||
Do()
|
||||
|
@ -52,8 +52,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ApplyAnnotationsFlag = "save-config"
|
||||
DefaultErrorExitCode = 1
|
||||
ApplyAnnotationsFlag = "save-config"
|
||||
DefaultErrorExitCode = 1
|
||||
IncludeUninitializedFlag = "include-uninitialized"
|
||||
)
|
||||
|
||||
type debugError interface {
|
||||
@ -420,6 +421,10 @@ func AddDryRunFlag(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
|
||||
}
|
||||
|
||||
func AddIncludeUninitializedFlag(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool(IncludeUninitializedFlag, false, `If true, the kubectl command applies to uninitialized objects. If explicitly set to false, this flag overrides other flags that make the kubectl commands apply to uninitialized objects, e.g., "--all". Objects with empty metadata.initializers are regarded as initialized.`)
|
||||
}
|
||||
|
||||
func AddPodRunningTimeoutFlag(cmd *cobra.Command, defaultTimeout time.Duration) {
|
||||
cmd.Flags().Duration("pod-running-timeout", defaultTimeout, "The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one pod is running")
|
||||
}
|
||||
@ -826,3 +831,25 @@ func ManualStrip(file []byte) []byte {
|
||||
}
|
||||
return stripped
|
||||
}
|
||||
|
||||
// ShouldIncludeUninitialized identifies whether to include uninitialized objects.
|
||||
// includeUninitialized is the default value.
|
||||
// Assume we can parse `all` and `selector` from cmd.
|
||||
func ShouldIncludeUninitialized(cmd *cobra.Command, includeUninitialized bool) bool {
|
||||
shouldIncludeUninitialized := includeUninitialized
|
||||
if cmd.Flags().Lookup("all") != nil && GetFlagBool(cmd, "all") {
|
||||
// include the uninitialized objects by default
|
||||
// unless explicitly set --include-uninitialized=false
|
||||
shouldIncludeUninitialized = true
|
||||
}
|
||||
if cmd.Flags().Lookup("selector") != nil && GetFlagString(cmd, "selector") != "" {
|
||||
// does not include the uninitialized objects by default
|
||||
// unless explicitly set --include-uninitialized=true
|
||||
shouldIncludeUninitialized = false
|
||||
}
|
||||
if cmd.Flags().Changed(IncludeUninitializedFlag) {
|
||||
// get explicit value
|
||||
shouldIncludeUninitialized = GetFlagBool(cmd, IncludeUninitializedFlag)
|
||||
}
|
||||
return shouldIncludeUninitialized
|
||||
}
|
||||
|
@ -51,8 +51,9 @@ type Builder struct {
|
||||
stream bool
|
||||
dir bool
|
||||
|
||||
selector labels.Selector
|
||||
selectAll bool
|
||||
selector labels.Selector
|
||||
selectAll bool
|
||||
includeUninitialized bool
|
||||
|
||||
resources []string
|
||||
|
||||
@ -279,6 +280,12 @@ func (b *Builder) ExportParam(export bool) *Builder {
|
||||
return b
|
||||
}
|
||||
|
||||
// IncludeUninitialized accepts the include-uninitialized boolean for these resources
|
||||
func (b *Builder) IncludeUninitialized(includeUninitialized bool) *Builder {
|
||||
b.includeUninitialized = includeUninitialized
|
||||
return b
|
||||
}
|
||||
|
||||
// NamespaceParam accepts the namespace that these resources should be
|
||||
// considered under from - used by DefaultNamespace() and RequireNamespace()
|
||||
func (b *Builder) NamespaceParam(namespace string) *Builder {
|
||||
@ -607,7 +614,7 @@ func (b *Builder) visitBySelector() *Result {
|
||||
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
|
||||
selectorNamespace = ""
|
||||
}
|
||||
visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, b.selector, b.export))
|
||||
visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, b.selector, b.export, b.includeUninitialized))
|
||||
}
|
||||
if b.continueOnError {
|
||||
result.visitor = EagerVisitorList(visitors)
|
||||
|
@ -65,7 +65,7 @@ func (m *Helper) Get(namespace, name string, export bool) (runtime.Object, error
|
||||
}
|
||||
|
||||
// TODO: add field selector
|
||||
func (m *Helper) List(namespace, apiVersion string, selector labels.Selector, export bool) (runtime.Object, error) {
|
||||
func (m *Helper) List(namespace, apiVersion string, selector labels.Selector, export, includeUninitialized bool) (runtime.Object, error) {
|
||||
req := m.RESTClient.Get().
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
@ -76,6 +76,9 @@ func (m *Helper) List(namespace, apiVersion string, selector labels.Selector, ex
|
||||
// TODO: I should be part of ListOptions
|
||||
req.Param("export", strconv.FormatBool(export))
|
||||
}
|
||||
if includeUninitialized {
|
||||
req.Param("includeUninitialized", strconv.FormatBool(includeUninitialized))
|
||||
}
|
||||
return req.Do().Get()
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ func TestHelperList(t *testing.T) {
|
||||
RESTClient: client,
|
||||
NamespaceScoped: true,
|
||||
}
|
||||
obj, err := modifier.List("bar", api.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), labels.SelectorFromSet(labels.Set{"foo": "baz"}), false)
|
||||
obj, err := modifier.List("bar", api.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), labels.SelectorFromSet(labels.Set{"foo": "baz"}), false, false)
|
||||
if (err != nil) != test.Err {
|
||||
t.Errorf("unexpected error: %t %v", test.Err, err)
|
||||
}
|
||||
|
@ -27,27 +27,29 @@ import (
|
||||
|
||||
// Selector is a Visitor for resources that match a label selector.
|
||||
type Selector struct {
|
||||
Client RESTClient
|
||||
Mapping *meta.RESTMapping
|
||||
Namespace string
|
||||
Selector labels.Selector
|
||||
Export bool
|
||||
Client RESTClient
|
||||
Mapping *meta.RESTMapping
|
||||
Namespace string
|
||||
Selector labels.Selector
|
||||
Export bool
|
||||
IncludeUninitialized bool
|
||||
}
|
||||
|
||||
// NewSelector creates a resource selector which hides details of getting items by their label selector.
|
||||
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector labels.Selector, export bool) *Selector {
|
||||
func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace string, selector labels.Selector, export, includeUninitialized bool) *Selector {
|
||||
return &Selector{
|
||||
Client: client,
|
||||
Mapping: mapping,
|
||||
Namespace: namespace,
|
||||
Selector: selector,
|
||||
Export: export,
|
||||
Client: client,
|
||||
Mapping: mapping,
|
||||
Namespace: namespace,
|
||||
Selector: selector,
|
||||
Export: export,
|
||||
IncludeUninitialized: includeUninitialized,
|
||||
}
|
||||
}
|
||||
|
||||
// Visit implements Visitor
|
||||
func (r *Selector) Visit(fn VisitorFunc) error {
|
||||
list, err := NewHelper(r.Client, r.Mapping).List(r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), r.Selector, r.Export)
|
||||
list, err := NewHelper(r.Client, r.Mapping).List(r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), r.Selector, r.Export, r.IncludeUninitialized)
|
||||
if err != nil {
|
||||
if errors.IsBadRequest(err) || errors.IsNotFound(err) {
|
||||
if se, ok := err.(*errors.StatusError); ok {
|
||||
|
@ -36,7 +36,7 @@ type ConfigOverrides struct {
|
||||
Timeout string
|
||||
}
|
||||
|
||||
// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
|
||||
// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
|
||||
// corresponds to ConfigOverrides
|
||||
type ConfigOverrideFlags struct {
|
||||
AuthOverrideFlags AuthOverrideFlags
|
||||
|
Loading…
Reference in New Issue
Block a user