From eceadec69c4c22d3f415932d4a40ceb35471a039 Mon Sep 17 00:00:00 2001 From: zryfish Date: Thu, 2 Jan 2020 20:52:00 +0800 Subject: [PATCH] devlopment branch (#1736) --- cmd/controller-manager/app/options/options.go | 20 +- cmd/controller-manager/app/server.go | 20 +- cmd/ks-apiserver/app/options/options.go | 47 +- cmd/ks-apiserver/app/server.go | 122 +- cmd/ks-iam/app/options/options.go | 22 +- cmd/ks-iam/app/server.go | 35 +- go.mod | 17 +- go.sum | 27 + hack/generate_client.sh | 2 +- pkg/api/resource/resource.go | 1 + pkg/api/resource/v1alpha2/types.go | 29 + pkg/api/types.go | 170 + .../caddy-plugin/authenticate/authenticate.go | 12 +- .../caddy-plugin/authenticate/auto_load.go | 11 +- .../authentication/authentication.go | 35 +- .../caddy-plugin/authentication/auto_load.go | 29 +- pkg/apis/addtoscheme_logging_v1alpha2.go | 8 + .../devops/v1alpha1/zz_generated.deepcopy.go | 2 +- pkg/apis/logging/group.go | 1 + pkg/apis/logging/v1alpha2/doc.go | 23 + pkg/apis/logging/v1alpha2/fluentbit_types.go | 71 + pkg/apis/logging/v1alpha2/register.go | 44 + .../logging/v1alpha2/zz_generated.deepcopy.go | 251 + .../network/v1alpha1/zz_generated.deepcopy.go | 4 +- .../v1alpha2/zz_generated.deepcopy.go | 4 +- .../tenant/v1alpha1/zz_generated.deepcopy.go | 2 +- pkg/apiserver/apiserver.go | 81 + pkg/apiserver/components/components.go | 64 - pkg/apiserver/git/git.go | 30 - pkg/apiserver/logging/logging.go | 1 - pkg/apiserver/openpitrix/applications.go | 10 +- pkg/apiserver/operations/job.go | 57 - pkg/apiserver/operations/node.go | 41 - pkg/apiserver/query/field.go | 30 + pkg/apiserver/query/types.go | 145 + pkg/apiserver/query/types_test.go | 72 + pkg/apiserver/quotas/quotas.go | 51 - pkg/apiserver/registries/registries.go | 127 - pkg/apiserver/resources/resources.go | 54 - pkg/apiserver/resources/storage.go | 71 - pkg/apiserver/revisions/revisions.go | 82 - pkg/apiserver/routers/routers.go | 151 - pkg/apiserver/tenant/tenant.go | 4 +- .../workloadstatuses/workloadstatuses.go | 45 - pkg/client/clientset/versioned/clientset.go | 14 + .../versioned/fake/clientset_generated.go | 7 + .../clientset/versioned/fake/register.go | 2 + .../clientset/versioned/scheme/register.go | 2 + .../versioned/typed/logging/v1alpha2/doc.go | 20 + .../typed/logging/v1alpha2/fake/doc.go | 20 + .../logging/v1alpha2/fake/fake_fluentbit.go | 140 + .../v1alpha2/fake/fake_logging_client.go | 40 + .../typed/logging/v1alpha2/fluentbit.go | 191 + .../logging/v1alpha2/generated_expansion.go | 21 + .../typed/logging/v1alpha2/logging_client.go | 89 + .../informers/externalversions/factory.go | 6 + .../informers/externalversions/generic.go | 11 +- .../externalversions/logging/interface.go | 46 + .../logging/v1alpha2/fluentbit.go | 89 + .../logging/v1alpha2/interface.go | 45 + .../logging/v1alpha2/expansion_generated.go | 27 + .../listers/logging/v1alpha2/fluentbit.go | 94 + pkg/constants/constants.go | 2 - .../namespace/namespace_controller.go | 31 +- .../s2ibinary/s2ibinary_controller.go | 32 +- .../workspace/workspace_controller.go | 9 - pkg/informers/informers.go | 77 +- pkg/kapis/kapis.go | 7 +- pkg/kapis/logging/v1alpha2/register.go | 1 - pkg/kapis/openpitrix/v1/handler.go | 14 + pkg/kapis/operations/install/install.go | 2 +- pkg/kapis/operations/v1alpha2/handler.go | 48 + pkg/kapis/operations/v1alpha2/register.go | 18 +- pkg/kapis/resources/install/install.go | 33 - pkg/kapis/resources/v1alpha2/handler.go | 345 + pkg/kapis/resources/v1alpha2/register.go | 135 +- pkg/kapis/resources/v1alpha3/handler.go | 91 + pkg/kapis/resources/v1alpha3/handler_test.go | 7 + pkg/kapis/resources/v1alpha3/register.go | 81 + pkg/models/components/components.go | 62 +- pkg/models/components/components_test.go | 356 + pkg/models/devops/devops.go | 6 + pkg/models/devops/s2ibinary_handler.go | 161 +- pkg/models/git/git.go | 29 +- pkg/models/git/git_test.go | 6 +- pkg/models/iam/am.go | 15 +- pkg/models/iam/im.go | 7 +- pkg/models/log/logcrd.go | 1 - pkg/models/log/types.go | 4 - pkg/models/nodes/nodes.go | 279 - pkg/models/openpitrix/applications.go | 104 +- pkg/models/quotas/quotas.go | 97 +- pkg/models/registries/image_type.go | 21 +- pkg/models/registries/registries.go | 108 +- pkg/models/resources/deployments.go | 167 - pkg/models/resources/extraannotations.go | 120 - pkg/models/resources/resources.go | 186 - .../application}/appplications.go | 48 +- .../clusterrole}/clusterroles.go | 50 +- .../{ => v1alpha2/configmap}/configmaps.go | 48 +- .../{ => v1alpha2/cronjob}/cronjobs.go | 60 +- .../{ => v1alpha2/daemonset}/daemonsets.go | 60 +- .../hpa}/horizontalpodautoscalers.go | 52 +- .../{ => v1alpha2/ingress}/ingresses.go | 54 +- pkg/models/resources/v1alpha2/interface.go | 80 + .../resources/{ => v1alpha2/job}/jobs.go | 64 +- .../{ => v1alpha2/namespace}/namespaces.go | 45 +- .../resources/{ => v1alpha2/node}/nodes.go | 71 +- .../persistentvolumeclaims.go | 82 +- .../resources/{ => v1alpha2/pod}/pods.go | 73 +- .../resources/v1alpha2/resource/resources.go | 137 + .../resources/{ => v1alpha2/role}/roles.go | 43 +- .../s2buildertemplate}/s2ibuildertemplate.go | 41 +- .../{ => v1alpha2/s2ibuilder}/s2ibuilder.go | 45 +- .../resources/{ => v1alpha2/s2irun}/s2irun.go | 47 +- .../{ => v1alpha2/secret}/secrets.go | 45 +- .../{ => v1alpha2/service}/services.go | 45 +- .../statefulset}/statefulsets.go | 55 +- .../storageclass}/storageclasses.go | 67 +- .../{ => v1alpha2/workspace}/workspaces.go | 45 +- .../v1alpha3/deployment/deployments.go | 131 + .../v1alpha3/deployment/deployments_test.go | 150 + pkg/models/resources/v1alpha3/interface.go | 19 + .../resources/v1alpha3/resource/resource.go | 98 + pkg/models/revisions/revisions.go | 40 +- pkg/models/routers/routers.go | 192 +- pkg/models/status/status.go | 67 - pkg/models/storage/storage.go | 28 +- pkg/models/storage/volumes.go | 50 - pkg/models/tenant/namespaces.go | 8 +- pkg/models/tenant/workspaces.go | 12 +- pkg/models/types.go | 25 - pkg/models/workloads/jobs.go | 28 +- pkg/models/workspaces/workspaces.go | 144 +- pkg/server/config/config.go | 36 +- pkg/server/config/config_test.go | 30 +- pkg/server/options/options.go | 12 +- pkg/simple/client/alerting/options.go | 8 +- pkg/simple/client/cache/cache.go | 60 + pkg/simple/client/{redis => cache}/options.go | 16 +- pkg/simple/client/{redis => cache}/redis.go | 47 +- pkg/simple/client/db/db.go | 5 + pkg/simple/client/devops/devops.go | 39 +- pkg/simple/client/devops/interface.go | 18 + pkg/simple/client/devops/options.go | 22 +- pkg/simple/client/elasticsearch/esclient.go | 2 +- pkg/simple/client/elasticsearch/options.go | 18 +- pkg/simple/client/factory.go | 123 +- .../client/fluentbit/fluentbitcrdclient.go | 288 - pkg/simple/client/k8s/kubernetes.go | 34 +- pkg/simple/client/k8s/options.go | 6 +- pkg/simple/client/kubesphere/kubesphere.go | 20 +- pkg/simple/client/kubesphere/options.go | 12 +- pkg/simple/client/ldap/ldap.go | 14 +- pkg/simple/client/ldap/options.go | 22 +- pkg/simple/client/logging/logging.go | 4 + pkg/simple/client/logging/query.go | 4 + pkg/simple/client/monitoring/monitoring.go | 4 + pkg/simple/client/mysql/mysql.go | 12 +- pkg/simple/client/mysql/options.go | 26 +- pkg/simple/client/notification/options.go | 8 +- .../client/openpitrix/openpitrixclient.go | 30 +- pkg/simple/client/openpitrix/options.go | 28 +- pkg/simple/client/prometheus/options.go | 19 +- pkg/simple/client/prometheus/prometheus.go | 15 +- pkg/simple/client/s3/interface.go | 17 + pkg/simple/client/{s2is3 => s3}/options.go | 36 +- pkg/simple/client/{s2is3 => s3}/s3.go | 34 +- pkg/simple/client/servicemesh/options.go | 18 +- pkg/simple/client/sonarqube/interface.go | 8 + pkg/simple/client/sonarqube/options.go | 22 +- pkg/simple/client/sonarqube/sonarqube.go | 12 +- vendor/github.com/MakeNowJust/heredoc/LICENSE | 21 + .../github.com/MakeNowJust/heredoc/README.md | 53 + .../github.com/MakeNowJust/heredoc/heredoc.go | 98 + vendor/github.com/chai2010/gettext-go/LICENSE | 27 + .../chai2010/gettext-go/gettext/caller.go | 39 + .../chai2010/gettext-go/gettext/doc.go | 66 + .../chai2010/gettext-go/gettext/domain.go | 119 + .../gettext-go/gettext/domain_helper.go | 50 + .../chai2010/gettext-go/gettext/fs.go | 187 + .../chai2010/gettext-go/gettext/gettext.go | 184 + .../chai2010/gettext-go/gettext/local.go | 34 + .../chai2010/gettext-go/gettext/mo/doc.go | 74 + .../chai2010/gettext-go/gettext/mo/encoder.go | 124 + .../chai2010/gettext-go/gettext/mo/file.go | 193 + .../chai2010/gettext-go/gettext/mo/header.go | 109 + .../chai2010/gettext-go/gettext/mo/message.go | 39 + .../chai2010/gettext-go/gettext/mo/util.go | 110 + .../chai2010/gettext-go/gettext/plural/doc.go | 36 + .../gettext-go/gettext/plural/formula.go | 181 + .../gettext-go/gettext/plural/table.go | 55 + .../chai2010/gettext-go/gettext/po/comment.go | 270 + .../chai2010/gettext-go/gettext/po/doc.go | 24 + .../chai2010/gettext-go/gettext/po/file.go | 75 + .../chai2010/gettext-go/gettext/po/header.go | 106 + .../gettext-go/gettext/po/line_reader.go | 62 + .../chai2010/gettext-go/gettext/po/message.go | 189 + .../chai2010/gettext-go/gettext/po/re.go | 58 + .../chai2010/gettext-go/gettext/po/util.go | 110 + .../chai2010/gettext-go/gettext/tr.go | 128 + .../exponent-io/jsonpath/.gitignore | 24 + .../exponent-io/jsonpath/.travis.yml | 5 + .../github.com/exponent-io/jsonpath/LICENSE | 21 + .../github.com/exponent-io/jsonpath/README.md | 66 + .../exponent-io/jsonpath/decoder.go | 210 + .../github.com/exponent-io/jsonpath/path.go | 67 + .../exponent-io/jsonpath/pathaction.go | 61 + vendor/github.com/google/btree/.travis.yml | 1 + vendor/github.com/google/btree/LICENSE | 202 + vendor/github.com/google/btree/README.md | 12 + vendor/github.com/google/btree/btree.go | 890 + .../gregjones/httpcache/.travis.yml | 18 + .../gregjones/httpcache/LICENSE.txt | 7 + .../github.com/gregjones/httpcache/README.md | 24 + .../httpcache/diskcache/diskcache.go | 61 + .../gregjones/httpcache/httpcache.go | 553 + .../github.com/liggitt/tabwriter/.travis.yml | 11 + vendor/github.com/liggitt/tabwriter/LICENSE | 27 + vendor/github.com/liggitt/tabwriter/README.md | 7 + .../github.com/liggitt/tabwriter/tabwriter.go | 637 + .../mitchellh/go-wordwrap/LICENSE.md | 21 + .../mitchellh/go-wordwrap/README.md | 39 + .../github.com/mitchellh/go-wordwrap/go.mod | 1 + .../mitchellh/go-wordwrap/wordwrap.go | 73 + vendor/github.com/peterbourgon/diskv/LICENSE | 19 + .../github.com/peterbourgon/diskv/README.md | 141 + .../peterbourgon/diskv/compression.go | 64 + vendor/github.com/peterbourgon/diskv/diskv.go | 624 + vendor/github.com/peterbourgon/diskv/index.go | 115 + vendor/k8s.io/api/imagepolicy/v1alpha1/doc.go | 23 + .../api/imagepolicy/v1alpha1/generated.pb.go | 1412 + .../api/imagepolicy/v1alpha1/generated.proto | 86 + .../api/imagepolicy/v1alpha1/register.go | 51 + .../k8s.io/api/imagepolicy/v1alpha1/types.go | 80 + .../v1alpha1/types_swagger_doc_generated.go | 71 + .../v1alpha1/zz_generated.deepcopy.go | 120 + .../unstructured/unstructuredscheme/scheme.go | 133 + .../pkg/util/duration/duration.go | 89 + vendor/k8s.io/cli-runtime/LICENSE | 202 + .../pkg/genericclioptions/builder_flags.go | 220 + .../genericclioptions/builder_flags_fake.go | 54 + .../pkg/genericclioptions/config_flags.go | 357 + .../genericclioptions/config_flags_fake.go | 110 + .../cli-runtime/pkg/genericclioptions/doc.go | 19 + .../pkg/genericclioptions/filename_flags.go | 79 + .../pkg/genericclioptions/io_options.go | 57 + .../pkg/genericclioptions/json_yaml_flags.go | 68 + .../pkg/genericclioptions/jsonpath_flags.go | 130 + .../genericclioptions/kube_template_flags.go | 89 + .../pkg/genericclioptions/name_flags.go | 81 + .../pkg/genericclioptions/print_flags.go | 158 + .../pkg/genericclioptions/record_flags.go | 199 + .../pkg/genericclioptions/template_flags.go | 135 + .../cli-runtime/pkg/kustomize/builder.go | 32 + .../configmapandsecret/configmapfactory.go | 125 + .../k8sdeps/configmapandsecret/kv.go | 107 + .../configmapandsecret/secretfactory.go | 106 + .../cli-runtime/pkg/kustomize/k8sdeps/doc.go | 76 + .../pkg/kustomize/k8sdeps/factory.go | 34 + .../kustomize/k8sdeps/kunstruct/factory.go | 118 + .../pkg/kustomize/k8sdeps/kunstruct/helper.go | 71 + .../kustomize/k8sdeps/kunstruct/kunstruct.go | 92 + .../pkg/kustomize/k8sdeps/kv/kv.go | 102 + .../kustomize/k8sdeps/transformer/factory.go | 43 + .../k8sdeps/transformer/hash/hash.go | 168 + .../k8sdeps/transformer/hash/namehash.go | 47 + .../k8sdeps/transformer/patch/patch.go | 174 + .../patch/patchconflictdetector.go | 137 + .../kustomize/k8sdeps/validator/validators.go | 61 + .../cli-runtime/pkg/printers/discard.go | 30 + vendor/k8s.io/cli-runtime/pkg/printers/doc.go | 19 + .../cli-runtime/pkg/printers/interface.go | 54 + .../k8s.io/cli-runtime/pkg/printers/json.go | 142 + .../cli-runtime/pkg/printers/jsonpath.go | 147 + .../k8s.io/cli-runtime/pkg/printers/name.go | 130 + .../cli-runtime/pkg/printers/sourcechecker.go | 60 + .../cli-runtime/pkg/printers/tableprinter.go | 574 + .../cli-runtime/pkg/printers/tabwriter.go | 36 + .../cli-runtime/pkg/printers/template.go | 118 + .../cli-runtime/pkg/printers/typesetter.go | 95 + .../cli-runtime/pkg/resource/builder.go | 1193 + .../k8s.io/cli-runtime/pkg/resource/client.go | 58 + vendor/k8s.io/cli-runtime/pkg/resource/doc.go | 24 + .../k8s.io/cli-runtime/pkg/resource/fake.go | 40 + .../k8s.io/cli-runtime/pkg/resource/helper.go | 185 + .../cli-runtime/pkg/resource/interfaces.go | 103 + .../k8s.io/cli-runtime/pkg/resource/mapper.go | 161 + .../pkg/resource/metadata_decoder.go | 59 + .../k8s.io/cli-runtime/pkg/resource/result.go | 242 + .../k8s.io/cli-runtime/pkg/resource/scheme.go | 82 + .../cli-runtime/pkg/resource/selector.go | 118 + .../cli-runtime/pkg/resource/visitor.go | 762 + .../discovery/cached/disk/cached_discovery.go | 300 + .../discovery/cached/disk/round_tripper.go | 65 + vendor/k8s.io/client-go/scale/client.go | 225 + vendor/k8s.io/client-go/scale/doc.go | 21 + vendor/k8s.io/client-go/scale/interfaces.go | 44 + .../client-go/scale/scheme/appsint/doc.go | 22 + .../scale/scheme/appsint/register.go | 55 + .../scale/scheme/appsv1beta1/conversion.go | 87 + .../client-go/scale/scheme/appsv1beta1/doc.go | 20 + .../scale/scheme/appsv1beta1/register.go | 45 + .../appsv1beta1/zz_generated.conversion.go | 143 + .../scale/scheme/appsv1beta2/conversion.go | 87 + .../client-go/scale/scheme/appsv1beta2/doc.go | 20 + .../scale/scheme/appsv1beta2/register.go | 45 + .../appsv1beta2/zz_generated.conversion.go | 143 + .../scale/scheme/autoscalingv1/conversion.go | 69 + .../scale/scheme/autoscalingv1/doc.go | 20 + .../scale/scheme/autoscalingv1/register.go | 45 + .../autoscalingv1/zz_generated.conversion.go | 142 + vendor/k8s.io/client-go/scale/scheme/doc.go | 22 + .../scale/scheme/extensionsint/doc.go | 22 + .../scale/scheme/extensionsint/register.go | 55 + .../scheme/extensionsv1beta1/conversion.go | 87 + .../scale/scheme/extensionsv1beta1/doc.go | 20 + .../scheme/extensionsv1beta1/register.go | 45 + .../zz_generated.conversion.go | 143 + .../k8s.io/client-go/scale/scheme/register.go | 54 + vendor/k8s.io/client-go/scale/scheme/types.go | 60 + .../scale/scheme/zz_generated.deepcopy.go | 91 + vendor/k8s.io/client-go/scale/util.go | 197 + .../client-go/tools/watch/informerwatcher.go | 150 + .../client-go/tools/watch/retrywatcher.go | 287 + vendor/k8s.io/client-go/tools/watch/until.go | 236 + .../pkg/util/proto/validation/errors.go | 79 + .../pkg/util/proto/validation/types.go | 299 + .../pkg/util/proto/validation/validation.go | 30 + vendor/k8s.io/kubectl/LICENSE | 201 + .../kubectl/pkg/cmd/get/customcolumn.go | 260 + .../kubectl/pkg/cmd/get/customcolumn_flags.go | 111 + vendor/k8s.io/kubectl/pkg/cmd/get/get.go | 853 + .../k8s.io/kubectl/pkg/cmd/get/get_flags.go | 187 + .../pkg/cmd/get/humanreadable_flags.go | 138 + .../kubectl/pkg/cmd/get/skip_printer.go | 48 + vendor/k8s.io/kubectl/pkg/cmd/get/sorter.go | 400 + .../kubectl/pkg/cmd/get/table_printer.go | 87 + .../k8s.io/kubectl/pkg/cmd/util/crdfinder.go | 109 + vendor/k8s.io/kubectl/pkg/cmd/util/factory.go | 66 + .../pkg/cmd/util/factory_client_access.go | 177 + vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go | 661 + .../pkg/cmd/util/kubectl_match_version.go | 129 + .../k8s.io/kubectl/pkg/cmd/util/printing.go | 29 + .../k8s.io/kubectl/pkg/generated/bindata.go | 22850 ++++++++++++++++ vendor/k8s.io/kubectl/pkg/rawhttp/raw.go | 94 + vendor/k8s.io/kubectl/pkg/scheme/install.go | 83 + vendor/k8s.io/kubectl/pkg/scheme/scheme.go | 39 + vendor/k8s.io/kubectl/pkg/util/i18n/i18n.go | 147 + .../kubectl/pkg/util/interrupt/interrupt.go | 104 + vendor/k8s.io/kubectl/pkg/util/openapi/OWNERS | 6 + vendor/k8s.io/kubectl/pkg/util/openapi/doc.go | 21 + .../k8s.io/kubectl/pkg/util/openapi/dryrun.go | 65 + .../kubectl/pkg/util/openapi/extensions.go | 27 + .../kubectl/pkg/util/openapi/openapi.go | 128 + .../pkg/util/openapi/openapi_getter.go | 65 + .../pkg/util/openapi/validation/validation.go | 140 + .../pkg/util/templates/command_groups.go | 59 + .../kubectl/pkg/util/templates/markdown.go | 147 + .../kubectl/pkg/util/templates/normalizers.go | 97 + .../kubectl/pkg/util/templates/templater.go | 297 + .../kubectl/pkg/util/templates/templates.go | 103 + vendor/k8s.io/kubectl/pkg/util/term/resize.go | 132 + .../kubectl/pkg/util/term/resizeevents.go | 61 + .../pkg/util/term/resizeevents_windows.go | 62 + vendor/k8s.io/kubectl/pkg/util/term/term.go | 110 + .../kubectl/pkg/util/term/term_writer.go | 124 + .../k8s.io/kubectl/pkg/validation/schema.go | 103 + vendor/k8s.io/utils/exec/doc.go | 18 + vendor/k8s.io/utils/exec/exec.go | 252 + vendor/modules.txt | 104 +- vendor/sigs.k8s.io/kustomize/LICENSE | 201 + .../kustomize/pkg/commands/build/build.go | 129 + .../kustomize/pkg/constants/constants.go | 28 + .../kustomize/pkg/expansion/expand.go | 121 + .../kustomize/pkg/factory/factory.go | 39 + .../kustomize/pkg/fs/confirmeddir.go | 93 + .../sigs.k8s.io/kustomize/pkg/fs/fakefile.go | 69 + .../kustomize/pkg/fs/fakefileinfo.go | 47 + vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go | 185 + vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go | 44 + .../sigs.k8s.io/kustomize/pkg/fs/realfile.go | 40 + vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go | 122 + .../sigs.k8s.io/kustomize/pkg/git/cloner.go | 75 + .../sigs.k8s.io/kustomize/pkg/git/repospec.go | 214 + vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go | 180 + vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go | 73 + .../kustomize/pkg/ifc/transformer/factory.go | 29 + .../kustomize/pkg/image/deprecatedimage.go | 32 + .../sigs.k8s.io/kustomize/pkg/image/image.go | 36 + .../pkg/internal/error/configmaperror.go | 30 + .../pkg/internal/error/kustomizationerror.go | 61 + .../pkg/internal/error/patcherror.go | 32 + .../pkg/internal/error/resourceerror.go | 30 + .../pkg/internal/error/secreterror.go | 30 + .../pkg/internal/error/yamlformaterror.go | 48 + .../kustomize/pkg/loader/fileloader.go | 312 + .../kustomize/pkg/loader/loader.go | 39 + .../kustomize/pkg/patch/json6902.go | 40 + .../kustomize/pkg/patch/strategicmerge.go | 40 + .../pkg/patch/transformer/factory.go | 83 + .../patch/transformer/patchjson6902json.go | 108 + .../sigs.k8s.io/kustomize/pkg/resid/resid.go | 207 + .../kustomize/pkg/resmap/factory.go | 123 + .../kustomize/pkg/resmap/idslice.go | 37 + .../kustomize/pkg/resmap/resmap.go | 200 + .../kustomize/pkg/resource/factory.go | 148 + .../kustomize/pkg/resource/resource.go | 107 + .../kustomize/pkg/target/kusttarget.go | 315 + .../kustomize/pkg/target/resaccumulator.go | 161 + .../config/defaultconfig/commonannotations.go | 60 + .../config/defaultconfig/commonlabels.go | 162 + .../config/defaultconfig/defaultconfig.go | 49 + .../config/defaultconfig/nameprefix.go | 24 + .../config/defaultconfig/namereference.go | 317 + .../config/defaultconfig/namespace.go | 25 + .../config/defaultconfig/varreference.go | 162 + .../pkg/transformers/config/factory.go | 87 + .../pkg/transformers/config/factorycrd.go | 201 + .../pkg/transformers/config/fieldspec.go | 139 + .../transformers/config/namebackreferences.go | 105 + .../transformers/config/transformerconfig.go | 134 + .../kustomize/pkg/transformers/image.go | 171 + .../pkg/transformers/labelsandannotations.go | 86 + .../pkg/transformers/multitransformer.go | 95 + .../kustomize/pkg/transformers/mutatefield.go | 81 + .../pkg/transformers/namereference.go | 144 + .../kustomize/pkg/transformers/namespace.go | 121 + .../pkg/transformers/nooptransformer.go | 34 + .../pkg/transformers/prefixsuffixname.go | 109 + .../kustomize/pkg/transformers/refvars.go | 94 + .../kustomize/pkg/transformers/transformer.go | 26 + .../kustomize/pkg/types/genargs.go | 64 + .../kustomize/pkg/types/generationbehavior.go | 59 + .../kustomize/pkg/types/kustomization.go | 250 + vendor/sigs.k8s.io/kustomize/pkg/types/var.go | 145 + vendor/vbom.ml/util/LICENSE | 17 + vendor/vbom.ml/util/sortorder/README.md | 5 + vendor/vbom.ml/util/sortorder/doc.go | 5 + vendor/vbom.ml/util/sortorder/natsort.go | 76 + 440 files changed, 61524 insertions(+), 3699 deletions(-) create mode 100644 pkg/api/resource/resource.go create mode 100644 pkg/api/resource/v1alpha2/types.go create mode 100644 pkg/api/types.go create mode 100644 pkg/apis/addtoscheme_logging_v1alpha2.go create mode 100644 pkg/apis/logging/group.go create mode 100644 pkg/apis/logging/v1alpha2/doc.go create mode 100644 pkg/apis/logging/v1alpha2/fluentbit_types.go create mode 100644 pkg/apis/logging/v1alpha2/register.go create mode 100644 pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go create mode 100644 pkg/apiserver/apiserver.go delete mode 100644 pkg/apiserver/components/components.go delete mode 100644 pkg/apiserver/git/git.go delete mode 100644 pkg/apiserver/operations/job.go delete mode 100644 pkg/apiserver/operations/node.go create mode 100644 pkg/apiserver/query/field.go create mode 100644 pkg/apiserver/query/types.go create mode 100644 pkg/apiserver/query/types_test.go delete mode 100644 pkg/apiserver/quotas/quotas.go delete mode 100644 pkg/apiserver/registries/registries.go delete mode 100644 pkg/apiserver/resources/resources.go delete mode 100644 pkg/apiserver/resources/storage.go delete mode 100644 pkg/apiserver/revisions/revisions.go delete mode 100644 pkg/apiserver/routers/routers.go delete mode 100644 pkg/apiserver/workloadstatuses/workloadstatuses.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/doc.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_fluentbit.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_logging_client.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/fluentbit.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/generated_expansion.go create mode 100644 pkg/client/clientset/versioned/typed/logging/v1alpha2/logging_client.go create mode 100644 pkg/client/informers/externalversions/logging/interface.go create mode 100644 pkg/client/informers/externalversions/logging/v1alpha2/fluentbit.go create mode 100644 pkg/client/informers/externalversions/logging/v1alpha2/interface.go create mode 100644 pkg/client/listers/logging/v1alpha2/expansion_generated.go create mode 100644 pkg/client/listers/logging/v1alpha2/fluentbit.go create mode 100644 pkg/kapis/openpitrix/v1/handler.go create mode 100644 pkg/kapis/operations/v1alpha2/handler.go delete mode 100644 pkg/kapis/resources/install/install.go create mode 100644 pkg/kapis/resources/v1alpha2/handler.go create mode 100644 pkg/kapis/resources/v1alpha3/handler.go create mode 100644 pkg/kapis/resources/v1alpha3/handler_test.go create mode 100644 pkg/kapis/resources/v1alpha3/register.go create mode 100644 pkg/models/components/components_test.go delete mode 100644 pkg/models/nodes/nodes.go delete mode 100644 pkg/models/resources/deployments.go delete mode 100644 pkg/models/resources/extraannotations.go delete mode 100644 pkg/models/resources/resources.go rename pkg/models/resources/{ => v1alpha2/application}/appplications.go (67%) rename pkg/models/resources/{ => v1alpha2/clusterrole}/clusterroles.go (71%) rename pkg/models/resources/{ => v1alpha2/configmap}/configmaps.go (67%) rename pkg/models/resources/{ => v1alpha2/cronjob}/cronjobs.go (65%) rename pkg/models/resources/{ => v1alpha2/daemonset}/daemonsets.go (64%) rename pkg/models/resources/{ => v1alpha2/hpa}/horizontalpodautoscalers.go (66%) rename pkg/models/resources/{ => v1alpha2/ingress}/ingresses.go (59%) create mode 100644 pkg/models/resources/v1alpha2/interface.go rename pkg/models/resources/{ => v1alpha2/job}/jobs.go (69%) rename pkg/models/resources/{ => v1alpha2/namespace}/namespaces.go (70%) rename pkg/models/resources/{ => v1alpha2/node}/nodes.go (69%) rename pkg/models/resources/{ => v1alpha2/persistentvolumeclaim}/persistentvolumeclaims.go (59%) rename pkg/models/resources/{ => v1alpha2/pod}/pods.go (71%) create mode 100644 pkg/models/resources/v1alpha2/resource/resources.go rename pkg/models/resources/{ => v1alpha2/role}/roles.go (72%) rename pkg/models/resources/{ => v1alpha2/s2buildertemplate}/s2ibuildertemplate.go (69%) rename pkg/models/resources/{ => v1alpha2/s2ibuilder}/s2ibuilder.go (69%) rename pkg/models/resources/{ => v1alpha2/s2irun}/s2irun.go (69%) rename pkg/models/resources/{ => v1alpha2/secret}/secrets.go (68%) rename pkg/models/resources/{ => v1alpha2/service}/services.go (67%) rename pkg/models/resources/{ => v1alpha2/statefulset}/statefulsets.go (67%) rename pkg/models/resources/{ => v1alpha2/storageclass}/storageclasses.go (59%) rename pkg/models/resources/{ => v1alpha2/workspace}/workspaces.go (70%) create mode 100644 pkg/models/resources/v1alpha3/deployment/deployments.go create mode 100644 pkg/models/resources/v1alpha3/deployment/deployments_test.go create mode 100644 pkg/models/resources/v1alpha3/interface.go create mode 100644 pkg/models/resources/v1alpha3/resource/resource.go delete mode 100644 pkg/models/status/status.go delete mode 100644 pkg/models/storage/volumes.go create mode 100644 pkg/simple/client/cache/cache.go rename pkg/simple/client/{redis => cache}/options.go (67%) rename pkg/simple/client/{redis => cache}/redis.go (58%) create mode 100644 pkg/simple/client/db/db.go create mode 100644 pkg/simple/client/devops/interface.go delete mode 100644 pkg/simple/client/fluentbit/fluentbitcrdclient.go create mode 100644 pkg/simple/client/logging/logging.go create mode 100644 pkg/simple/client/logging/query.go create mode 100644 pkg/simple/client/monitoring/monitoring.go create mode 100644 pkg/simple/client/s3/interface.go rename pkg/simple/client/{s2is3 => s3}/options.go (64%) rename pkg/simple/client/{s2is3 => s3}/s3.go (68%) create mode 100644 pkg/simple/client/sonarqube/interface.go create mode 100644 vendor/github.com/MakeNowJust/heredoc/LICENSE create mode 100644 vendor/github.com/MakeNowJust/heredoc/README.md create mode 100644 vendor/github.com/MakeNowJust/heredoc/heredoc.go create mode 100644 vendor/github.com/chai2010/gettext-go/LICENSE create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/caller.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/doc.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/domain.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/fs.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/gettext.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/local.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/file.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/header.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/message.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/mo/util.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/plural/table.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/comment.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/doc.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/file.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/header.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/message.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/re.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/po/util.go create mode 100644 vendor/github.com/chai2010/gettext-go/gettext/tr.go create mode 100644 vendor/github.com/exponent-io/jsonpath/.gitignore create mode 100644 vendor/github.com/exponent-io/jsonpath/.travis.yml create mode 100644 vendor/github.com/exponent-io/jsonpath/LICENSE create mode 100644 vendor/github.com/exponent-io/jsonpath/README.md create mode 100644 vendor/github.com/exponent-io/jsonpath/decoder.go create mode 100644 vendor/github.com/exponent-io/jsonpath/path.go create mode 100644 vendor/github.com/exponent-io/jsonpath/pathaction.go create mode 100644 vendor/github.com/google/btree/.travis.yml create mode 100644 vendor/github.com/google/btree/LICENSE create mode 100644 vendor/github.com/google/btree/README.md create mode 100644 vendor/github.com/google/btree/btree.go create mode 100644 vendor/github.com/gregjones/httpcache/.travis.yml create mode 100644 vendor/github.com/gregjones/httpcache/LICENSE.txt create mode 100644 vendor/github.com/gregjones/httpcache/README.md create mode 100644 vendor/github.com/gregjones/httpcache/diskcache/diskcache.go create mode 100644 vendor/github.com/gregjones/httpcache/httpcache.go create mode 100644 vendor/github.com/liggitt/tabwriter/.travis.yml create mode 100644 vendor/github.com/liggitt/tabwriter/LICENSE create mode 100644 vendor/github.com/liggitt/tabwriter/README.md create mode 100644 vendor/github.com/liggitt/tabwriter/tabwriter.go create mode 100644 vendor/github.com/mitchellh/go-wordwrap/LICENSE.md create mode 100644 vendor/github.com/mitchellh/go-wordwrap/README.md create mode 100644 vendor/github.com/mitchellh/go-wordwrap/go.mod create mode 100644 vendor/github.com/mitchellh/go-wordwrap/wordwrap.go create mode 100644 vendor/github.com/peterbourgon/diskv/LICENSE create mode 100644 vendor/github.com/peterbourgon/diskv/README.md create mode 100644 vendor/github.com/peterbourgon/diskv/compression.go create mode 100644 vendor/github.com/peterbourgon/diskv/diskv.go create mode 100644 vendor/github.com/peterbourgon/diskv/index.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/doc.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/register.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/types.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go create mode 100644 vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/duration/duration.go create mode 100644 vendor/k8s.io/cli-runtime/LICENSE create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags_fake.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags_fake.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/doc.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/filename_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/io_options.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/json_yaml_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/jsonpath_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/kube_template_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/name_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/print_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/genericclioptions/template_flags.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/builder.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv/kv.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/discard.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/doc.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/interface.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/json.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/name.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/template.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/builder.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/client.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/doc.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/fake.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/helper.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/interfaces.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/mapper.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/metadata_decoder.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/result.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/scheme.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/selector.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/resource/visitor.go create mode 100644 vendor/k8s.io/client-go/discovery/cached/disk/cached_discovery.go create mode 100644 vendor/k8s.io/client-go/discovery/cached/disk/round_tripper.go create mode 100644 vendor/k8s.io/client-go/scale/client.go create mode 100644 vendor/k8s.io/client-go/scale/doc.go create mode 100644 vendor/k8s.io/client-go/scale/interfaces.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsint/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsint/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta1/conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta1/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta1/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta2/conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta2/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta2/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/autoscalingv1/conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/autoscalingv1/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/autoscalingv1/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsint/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsint/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/doc.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/register.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/types.go create mode 100644 vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go create mode 100644 vendor/k8s.io/client-go/scale/util.go create mode 100644 vendor/k8s.io/client-go/tools/watch/informerwatcher.go create mode 100644 vendor/k8s.io/client-go/tools/watch/retrywatcher.go create mode 100644 vendor/k8s.io/client-go/tools/watch/until.go create mode 100644 vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go create mode 100644 vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go create mode 100644 vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go create mode 100644 vendor/k8s.io/kubectl/LICENSE create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn_flags.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/get.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/get_flags.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/humanreadable_flags.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/skip_printer.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/sorter.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/get/table_printer.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/crdfinder.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/factory.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/factory_client_access.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/kubectl_match_version.go create mode 100644 vendor/k8s.io/kubectl/pkg/cmd/util/printing.go create mode 100644 vendor/k8s.io/kubectl/pkg/generated/bindata.go create mode 100644 vendor/k8s.io/kubectl/pkg/rawhttp/raw.go create mode 100644 vendor/k8s.io/kubectl/pkg/scheme/install.go create mode 100644 vendor/k8s.io/kubectl/pkg/scheme/scheme.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/i18n/i18n.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/OWNERS create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/doc.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/dryrun.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/extensions.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/openapi.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/openapi_getter.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/openapi/validation/validation.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/markdown.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/templater.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/templates.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resize.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/term.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/term_writer.go create mode 100644 vendor/k8s.io/kubectl/pkg/validation/schema.go create mode 100644 vendor/k8s.io/utils/exec/doc.go create mode 100644 vendor/k8s.io/utils/exec/exec.go create mode 100644 vendor/sigs.k8s.io/kustomize/LICENSE create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/confirmeddir.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/git/cloner.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/git/repospec.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/image/deprecatedimage.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/image/image.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/target/resaccumulator.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/image.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/mutatefield.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/types/genargs.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/types/generationbehavior.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go create mode 100644 vendor/sigs.k8s.io/kustomize/pkg/types/var.go create mode 100644 vendor/vbom.ml/util/LICENSE create mode 100644 vendor/vbom.ml/util/sortorder/README.md create mode 100644 vendor/vbom.ml/util/sortorder/doc.go create mode 100644 vendor/vbom.ml/util/sortorder/natsort.go diff --git a/cmd/controller-manager/app/options/options.go b/cmd/controller-manager/app/options/options.go index 9a2bbb46a..89b3703a2 100644 --- a/cmd/controller-manager/app/options/options.go +++ b/cmd/controller-manager/app/options/options.go @@ -10,16 +10,16 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/devops" "kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" - "kubesphere.io/kubesphere/pkg/simple/client/s2is3" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "strings" "time" ) type KubeSphereControllerManagerOptions struct { KubernetesOptions *k8s.KubernetesOptions - DevopsOptions *devops.DevopsOptions - S3Options *s2is3.S3Options - OpenPitrixOptions *openpitrix.OpenPitrixOptions + DevopsOptions *devops.Options + S3Options *s3.Options + OpenPitrixOptions *openpitrix.Options LeaderElection *leaderelection.LeaderElectionConfig } @@ -28,7 +28,7 @@ func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions s := &KubeSphereControllerManagerOptions{ KubernetesOptions: k8s.NewKubernetesOptions(), DevopsOptions: devops.NewDevopsOptions(), - S3Options: s2is3.NewS3Options(), + S3Options: s3.NewS3Options(), OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(), LeaderElection: &leaderelection.LeaderElectionConfig{ LeaseDuration: 30 * time.Second, @@ -47,13 +47,13 @@ func (s *KubeSphereControllerManagerOptions) ApplyTo(conf *kubesphereconfig.Conf s.OpenPitrixOptions.ApplyTo(conf.OpenPitrixOptions) } -func (s *KubeSphereControllerManagerOptions) Flags() cliflag.NamedFlagSets { +func (s *KubeSphereControllerManagerOptions) Flags(o *KubeSphereControllerManagerOptions) cliflag.NamedFlagSets { fss := cliflag.NamedFlagSets{} - s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes")) - s.DevopsOptions.AddFlags(fss.FlagSet("devops")) - s.S3Options.AddFlags(fss.FlagSet("s3")) - s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix")) + s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), o.KubernetesOptions) + s.DevopsOptions.AddFlags(fss.FlagSet("devops"), o.DevopsOptions) + s.S3Options.AddFlags(fss.FlagSet("s3"), o.S3Options) + s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), o.OpenPitrixOptions) fs := fss.FlagSet("leaderelection") s.bindLeaderElectionFlags(s.LeaderElection, fs) diff --git a/cmd/controller-manager/app/server.go b/cmd/controller-manager/app/server.go index 0e113bab0..6d8bc614c 100644 --- a/cmd/controller-manager/app/server.go +++ b/cmd/controller-manager/app/server.go @@ -69,8 +69,10 @@ func NewControllerManagerCommand() *cobra.Command { }, } + conf := loadConfFromFile() + fs := cmd.Flags() - namedFlagSets := s.Flags() + namedFlagSets := s.Flags(conf) for _, f := range namedFlagSets.FlagSets { fs.AddFlagSet(f) @@ -119,6 +121,22 @@ func CreateClientSet(conf *controllerconfig.Config, stopCh <-chan struct{}) erro return nil } +func loadConfFromFile() *options.KubeSphereControllerManagerOptions { + err := controllerconfig.Load() + if err != nil { + klog.Fatalf("error happened while loading config file") + } + + conf := controllerconfig.Get() + + return &options.KubeSphereControllerManagerOptions{ + KubernetesOptions: conf.KubernetesOptions, + DevopsOptions: conf.DevopsOptions, + S3Options: conf.S3Options, + OpenPitrixOptions: conf.OpenPitrixOptions, + } +} + func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) error { err := CreateClientSet(controllerconfig.Get(), stopCh) if err != nil { diff --git a/cmd/ks-apiserver/app/options/options.go b/cmd/ks-apiserver/app/options/options.go index e8de49030..66d02c95b 100644 --- a/cmd/ks-apiserver/app/options/options.go +++ b/cmd/ks-apiserver/app/options/options.go @@ -11,24 +11,24 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/mysql" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/prometheus" - "kubesphere.io/kubesphere/pkg/simple/client/s2is3" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/simple/client/servicemesh" "kubesphere.io/kubesphere/pkg/simple/client/sonarqube" "strings" ) type ServerRunOptions struct { + ConfigFile string GenericServerRunOptions *genericoptions.ServerRunOptions - - KubernetesOptions *k8s.KubernetesOptions - DevopsOptions *devops.DevopsOptions - SonarQubeOptions *sonarqube.SonarQubeOptions - ServiceMeshOptions *servicemesh.ServiceMeshOptions - MySQLOptions *mysql.MySQLOptions - MonitoringOptions *prometheus.PrometheusOptions - S3Options *s2is3.S3Options - OpenPitrixOptions *openpitrix.OpenPitrixOptions - LoggingOptions *esclient.ElasticSearchOptions + KubernetesOptions *k8s.KubernetesOptions + DevopsOptions *devops.Options + SonarQubeOptions *sonarqube.Options + ServiceMeshOptions *servicemesh.Options + MySQLOptions *mysql.Options + MonitoringOptions *prometheus.Options + S3Options *s3.Options + OpenPitrixOptions *openpitrix.Options + LoggingOptions *esclient.Options } func NewServerRunOptions() *ServerRunOptions { @@ -41,7 +41,7 @@ func NewServerRunOptions() *ServerRunOptions { ServiceMeshOptions: servicemesh.NewServiceMeshOptions(), MySQLOptions: mysql.NewMySQLOptions(), MonitoringOptions: prometheus.NewPrometheusOptions(), - S3Options: s2is3.NewS3Options(), + S3Options: s3.NewS3Options(), OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(), LoggingOptions: esclient.NewElasticSearchOptions(), } @@ -49,18 +49,17 @@ func NewServerRunOptions() *ServerRunOptions { return &s } -func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { - - s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic")) - s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes")) - s.MySQLOptions.AddFlags(fss.FlagSet("mysql")) - s.DevopsOptions.AddFlags(fss.FlagSet("devops")) - s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube")) - s.S3Options.AddFlags(fss.FlagSet("s3")) - s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix")) - s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh")) - s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring")) - s.LoggingOptions.AddFlags(fss.FlagSet("logging")) +func (s *ServerRunOptions) Flags(c *ServerRunOptions) (fss cliflag.NamedFlagSets) { + s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic"), c.GenericServerRunOptions) + s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), c.KubernetesOptions) + s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), c.MySQLOptions) + s.DevopsOptions.AddFlags(fss.FlagSet("devops"), c.DevopsOptions) + s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube"), c.SonarQubeOptions) + s.S3Options.AddFlags(fss.FlagSet("s3"), c.S3Options) + s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), c.OpenPitrixOptions) + s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh"), c.ServiceMeshOptions) + s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring"), c.MonitoringOptions) + s.LoggingOptions.AddFlags(fss.FlagSet("logging"), c.LoggingOptions) fs := fss.FlagSet("klog") local := flag.NewFlagSet("klog", flag.ExitOnError) diff --git a/cmd/ks-apiserver/app/server.go b/cmd/ks-apiserver/app/server.go index 5a7f789f6..98f106ac9 100644 --- a/cmd/ks-apiserver/app/server.go +++ b/cmd/ks-apiserver/app/server.go @@ -26,14 +26,18 @@ import ( cliflag "k8s.io/component-base/cli/flag" "k8s.io/klog" "kubesphere.io/kubesphere/cmd/ks-apiserver/app/options" + "kubesphere.io/kubesphere/pkg/apiserver" "kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/apiserver/servicemesh/tracing" - "kubesphere.io/kubesphere/pkg/informers" + kinformers "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/kapis" "kubesphere.io/kubesphere/pkg/server" apiserverconfig "kubesphere.io/kubesphere/pkg/server/config" "kubesphere.io/kubesphere/pkg/server/filter" "kubesphere.io/kubesphere/pkg/simple/client" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/utils/signals" "kubesphere.io/kubesphere/pkg/utils/term" "net/http" @@ -48,16 +52,6 @@ func NewAPIServerCommand() *cobra.Command { The API Server services REST operations and provides the frontend to the cluster's shared state through which all other components interact.`, RunE: func(cmd *cobra.Command, args []string) error { - err := apiserverconfig.Load() - if err != nil { - return err - } - - err = Complete(s) - if err != nil { - return err - } - if errs := s.Validate(); len(errs) != 0 { return utilerrors.NewAggregate(errs) } @@ -66,8 +60,10 @@ cluster's shared state through which all other components interact.`, }, } + configOptions := load() + fs := cmd.Flags() - namedFlagSets := s.Flags() + namedFlagSets := s.Flags(configOptions) for _, f := range namedFlagSets.FlagSets { fs.AddFlagSet(f) @@ -125,9 +121,13 @@ func initializeServicemeshConfig(s *options.ServerRunOptions) { } // -func CreateAPIServer(s *options.ServerRunOptions) error { +func CreateAPIServer(s *options.ServerRunOptions, stopCh <-chan struct{}) error { var err error + deps := createDeps(s, stopCh) + + apiserver := apiserver.New(deps) + container := runtime.Container container.DoNotRecover(false) container.Filter(filter.Logging) @@ -155,23 +155,35 @@ func CreateAPIServer(s *options.ServerRunOptions) error { return err } -func CreateClientSet(conf *apiserverconfig.Config, stopCh <-chan struct{}) error { - csop := &client.ClientSetOptions{} +func createDeps(s *options.ServerRunOptions, stopCh <-chan struct{}) *apiserver.Dependencies { + deps := &apiserver.Dependencies{} - csop.SetDevopsOptions(conf.DevopsOptions). - SetSonarQubeOptions(conf.SonarQubeOptions). - SetKubernetesOptions(conf.KubernetesOptions). - SetMySQLOptions(conf.MySQLOptions). - SetLdapOptions(conf.LdapOptions). - SetS3Options(conf.S3Options). - SetOpenPitrixOptions(conf.OpenPitrixOptions). - SetPrometheusOptions(conf.MonitoringOptions). - SetKubeSphereOptions(conf.KubeSphereOptions). - SetElasticSearchOptions(conf.LoggingOptions) + if s.KubernetesOptions == nil || s.KubernetesOptions.KubeConfig == "" { + klog.Warning("kubeconfig not provided, will use in-cluster config") + } - client.NewClientSetFactory(csop, stopCh) + var err error + deps.KubeClient, err = k8s.NewKubernetesClient(s.KubernetesOptions) + if err != nil { + klog.Fatalf("error happened when initializing kubernetes client, %v", err) + } + + if s.S3Options != nil && s.S3Options.Endpoint != "" { + deps.S3, err = s3.NewS3Client(s.S3Options) + if err != nil { + klog.Fatalf("error initializing s3 client, %v", err) + } + } + + if s.OpenPitrixOptions != nil && !s.OpenPitrixOptions.IsEmpty() { + deps.OpenPitrix, err = openpitrix.NewOpenPitrixClient(s.OpenPitrixOptions) + if err != nil { + klog.Fatalf("error happened when initializing openpitrix client, %v", err) + } + } + + return deps - return nil } func WaitForResourceSync(stopCh <-chan struct{}) error { @@ -196,7 +208,8 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { return false } - informerFactory := informers.SharedInformerFactory() + informerFactory := kinformers.NewInformerFactories(client.ClientSets().K8s().Kubernetes(), client.ClientSets().K8s().KubeSphere(), client.ClientSets().K8s().S2i(), + client.ClientSets().K8s().Application()) // resources we have to create informer first k8sGVRs := []schema.GroupVersionResource{ @@ -234,7 +247,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { if !isResourceExists(gvr) { klog.Warningf("resource %s not exists in the cluster", gvr) } else { - _, err := informerFactory.ForResource(gvr) + _, err := informerFactory.KubernetesSharedInformerFactory().ForResource(gvr) if err != nil { klog.Errorf("cannot create informer for %s", gvr) return err @@ -242,10 +255,10 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { } } - informerFactory.Start(stopCh) - informerFactory.WaitForCacheSync(stopCh) + informerFactory.KubernetesSharedInformerFactory().Start(stopCh) + informerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopCh) - s2iInformerFactory := informers.S2iSharedInformerFactory() + s2iInformerFactory := informerFactory.S2iSharedInformerFactory() s2iGVRs := []schema.GroupVersionResource{ {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"}, @@ -267,7 +280,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { s2iInformerFactory.Start(stopCh) s2iInformerFactory.WaitForCacheSync(stopCh) - ksInformerFactory := informers.KsSharedInformerFactory() + ksInformerFactory := informerFactory.KubeSphereSharedInformerFactory() ksGVRs := []schema.GroupVersionResource{ {Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"}, @@ -291,7 +304,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { ksInformerFactory.Start(stopCh) ksInformerFactory.WaitForCacheSync(stopCh) - appInformerFactory := informers.AppSharedInformerFactory() + appInformerFactory := informerFactory.ApplicationSharedInformerFactory() appGVRs := []schema.GroupVersionResource{ {Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}, @@ -317,36 +330,23 @@ func WaitForResourceSync(stopCh <-chan struct{}) error { } -// apply server run options to configuration -func Complete(s *options.ServerRunOptions) error { - - // loading configuration file +// load options from config file +func load() *options.ServerRunOptions { conf := apiserverconfig.Get() - conf.Apply(&apiserverconfig.Config{ - MySQLOptions: s.MySQLOptions, - DevopsOptions: s.DevopsOptions, - SonarQubeOptions: s.SonarQubeOptions, - KubernetesOptions: s.KubernetesOptions, - ServiceMeshOptions: s.ServiceMeshOptions, - MonitoringOptions: s.MonitoringOptions, - S3Options: s.S3Options, - OpenPitrixOptions: s.OpenPitrixOptions, - LoggingOptions: s.LoggingOptions, - }) - - *s = options.ServerRunOptions{ - GenericServerRunOptions: s.GenericServerRunOptions, - KubernetesOptions: conf.KubernetesOptions, - DevopsOptions: conf.DevopsOptions, - SonarQubeOptions: conf.SonarQubeOptions, - ServiceMeshOptions: conf.ServiceMeshOptions, - MySQLOptions: conf.MySQLOptions, - MonitoringOptions: conf.MonitoringOptions, - S3Options: conf.S3Options, - OpenPitrixOptions: conf.OpenPitrixOptions, - LoggingOptions: conf.LoggingOptions, + return &options.ServerRunOptions{ + KubernetesOptions: conf.KubernetesOptions, + DevopsOptions: conf.DevopsOptions, + SonarQubeOptions: conf.SonarQubeOptions, + ServiceMeshOptions: conf.ServiceMeshOptions, + MySQLOptions: conf.MySQLOptions, + MonitoringOptions: conf.MonitoringOptions, + S3Options: conf.S3Options, + OpenPitrixOptions: conf.OpenPitrixOptions, + LoggingOptions: conf.LoggingOptions, } +} +func initConfigz() error { return nil } diff --git a/cmd/ks-iam/app/options/options.go b/cmd/ks-iam/app/options/options.go index 07a7529dd..89e10cf4d 100644 --- a/cmd/ks-iam/app/options/options.go +++ b/cmd/ks-iam/app/options/options.go @@ -22,10 +22,10 @@ import ( cliflag "k8s.io/component-base/cli/flag" "k8s.io/klog" genericoptions "kubesphere.io/kubesphere/pkg/server/options" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/simple/client/ldap" "kubesphere.io/kubesphere/pkg/simple/client/mysql" - "kubesphere.io/kubesphere/pkg/simple/client/redis" "strings" "time" ) @@ -33,9 +33,9 @@ import ( type ServerRunOptions struct { GenericServerRunOptions *genericoptions.ServerRunOptions KubernetesOptions *k8s.KubernetesOptions - LdapOptions *ldap.LdapOptions - RedisOptions *redis.RedisOptions - MySQLOptions *mysql.MySQLOptions + LdapOptions *ldap.Options + RedisOptions *cache.Options + MySQLOptions *mysql.Options AdminEmail string AdminPassword string TokenIdleTimeout time.Duration @@ -51,16 +51,16 @@ func NewServerRunOptions() *ServerRunOptions { KubernetesOptions: k8s.NewKubernetesOptions(), LdapOptions: ldap.NewLdapOptions(), MySQLOptions: mysql.NewMySQLOptions(), - RedisOptions: redis.NewRedisOptions(), + RedisOptions: cache.NewRedisOptions(), } return s } -func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { +func (s *ServerRunOptions) Flags(conf *ServerRunOptions) (fss cliflag.NamedFlagSets) { fs := fss.FlagSet("generic") - s.GenericServerRunOptions.AddFlags(fs) + s.GenericServerRunOptions.AddFlags(fs, conf.GenericServerRunOptions) fs.StringVar(&s.AdminEmail, "admin-email", "admin@kubesphere.io", "default administrator's email") fs.StringVar(&s.AdminPassword, "admin-password", "passw0rd", "default administrator's password") fs.DurationVar(&s.TokenIdleTimeout, "token-idle-timeout", 30*time.Minute, "tokens that are idle beyond that time will expire,0s means the token has no expiration time. valid time units are \"ns\",\"us\",\"ms\",\"s\",\"m\",\"h\"") @@ -69,10 +69,10 @@ func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { fs.BoolVar(&s.EnableMultiLogin, "enable-multi-login", false, "allow one account to have multiple sessions") fs.BoolVar(&s.GenerateKubeConfig, "generate-kubeconfig", true, "generate kubeconfig for new users, kubeconfig is required in devops pipeline, set to false if you don't need devops.") - s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes")) - s.LdapOptions.AddFlags(fss.FlagSet("ldap")) - s.RedisOptions.AddFlags(fss.FlagSet("redis")) - s.MySQLOptions.AddFlags(fss.FlagSet("mysql")) + s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), conf.KubernetesOptions) + s.LdapOptions.AddFlags(fss.FlagSet("ldap"), conf.LdapOptions) + s.RedisOptions.AddFlags(fss.FlagSet("redis"), conf.RedisOptions) + s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), conf.MySQLOptions) kfs := fss.FlagSet("klog") local := flag.NewFlagSet("klog", flag.ExitOnError) diff --git a/cmd/ks-iam/app/server.go b/cmd/ks-iam/app/server.go index 89db7d97b..2ac4b5b4c 100644 --- a/cmd/ks-iam/app/server.go +++ b/cmd/ks-iam/app/server.go @@ -53,11 +53,6 @@ cluster's shared state through which all other components interact.`, return err } - err = Complete(s) - if err != nil { - return err - } - if errs := s.Validate(); len(errs) != 0 { return utilerrors.NewAggregate(errs) } @@ -66,8 +61,10 @@ cluster's shared state through which all other components interact.`, }, } + conf := loadFromFile() + fs := cmd.Flags() - namedFlagSets := s.Flags() + namedFlagSets := s.Flags(conf) for _, f := range namedFlagSets.FlagSets { fs.AddFlagSet(f) @@ -122,22 +119,20 @@ func Run(s *options.ServerRunOptions, stopChan <-chan struct{}) error { return err } -func Complete(s *options.ServerRunOptions) error { +func loadFromFile() *options.ServerRunOptions { + err := apiserverconfig.Load() + if err != nil { + klog.Fatal(err) + } + conf := apiserverconfig.Get() - conf.Apply(&apiserverconfig.Config{ - KubernetesOptions: s.KubernetesOptions, - LdapOptions: s.LdapOptions, - RedisOptions: s.RedisOptions, - MySQLOptions: s.MySQLOptions, - }) - - s.KubernetesOptions = conf.KubernetesOptions - s.LdapOptions = conf.LdapOptions - s.RedisOptions = conf.RedisOptions - s.MySQLOptions = conf.MySQLOptions - - return nil + return &options.ServerRunOptions{ + KubernetesOptions: conf.KubernetesOptions, + LdapOptions: conf.LdapOptions, + RedisOptions: conf.RedisOptions, + MySQLOptions: conf.MySQLOptions, + } } func waitForResourceSync(stopCh <-chan struct{}) { diff --git a/go.mod b/go.mod index 36a9f0e39..a659c9311 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/gocraft/dbr v0.0.0-20180507214907-a0fd650918f6 github.com/golang/example v0.0.0-20170904185048-46695d81d1fa github.com/golang/protobuf v1.3.2 + github.com/google/go-cmp v0.3.0 github.com/google/go-querystring v1.0.0 // indirect github.com/google/uuid v1.1.1 github.com/gophercloud/gophercloud v0.3.0 // indirect @@ -63,8 +64,8 @@ require ( github.com/mholt/certmagic v0.5.1 // indirect github.com/miekg/dns v1.1.9 // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect - github.com/onsi/ginkgo v1.8.0 - github.com/onsi/gomega v1.5.0 + github.com/onsi/ginkgo v1.10.1 + github.com/onsi/gomega v1.7.0 github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/image-spec v1.0.1 // indirect github.com/openshift/api v3.9.0+incompatible // indirect @@ -87,16 +88,16 @@ require ( gopkg.in/yaml.v2 v2.2.4 istio.io/api v0.0.0-20191111210003-35e06ef8d838 istio.io/client-go v0.0.0-20191113122552-9bd0ba57c3d2 - k8s.io/api v0.0.0-20191114100352-16d7abae0d2a + k8s.io/api v0.17.0 k8s.io/apiextensions-apiserver v0.0.0-20191114105449-027877536833 - k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb + k8s.io/apimachinery v0.17.0 k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 - k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 - k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 - k8s.io/component-base v0.0.0-20191114102325-35a9586014f7 + k8s.io/client-go v0.17.0 + k8s.io/code-generator v0.17.0 + k8s.io/component-base v0.17.0 k8s.io/klog v1.0.0 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a - k8s.io/utils v0.0.0-20191114184206-e782cd3c129f // indirect + k8s.io/kubectl v0.17.0 kubesphere.io/im v0.1.0 // indirect openpitrix.io/iam v0.1.0 // indirect openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c diff --git a/go.sum b/go.sum index f6b4405a8..3c4b61c5e 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VY github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= +github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= @@ -60,6 +62,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -77,6 +81,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= @@ -115,6 +120,8 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= @@ -191,6 +198,9 @@ github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= @@ -213,6 +223,7 @@ github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -285,6 +296,9 @@ github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= @@ -309,6 +323,8 @@ github.com/miekg/dns v1.1.9 h1:OIdC9wT96RzuZMf2PfKRhFgsStHUUBZLM/lo1LqiM9E= github.com/miekg/dns v1.1.9/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -343,6 +359,7 @@ github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWo github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -416,6 +433,7 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= @@ -517,6 +535,8 @@ k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb h1:ZUNsbuPdXWrj0rZziRfCWc k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 h1:+FvAOv/4JyYgZanQI8h+UW9FCmLzyEz7EZunuET6p5g= k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682/go.mod h1:Idob8Va6/sMX5SmwPLsU0pdvFlkwxuJ5x+fXMG8NbKE= +k8s.io/cli-runtime v0.17.0 h1:XEuStbJBHCQlEKFyTQmceDKEWOSYHZkcYWKp3SsQ9Hk= +k8s.io/cli-runtime v0.17.0/go.mod h1:1E5iQpMODZq2lMWLUJELwRu2MLWIzwvMgDBpn3Y81Qo= k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 h1:07mhG/2oEoo3N+sHVOo0L9PJ/qvbk3N5n2dj8IWefnQ= k8s.io/client-go v0.0.0-20191114101535-6c5935290e33/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw= k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI= @@ -529,6 +549,9 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kubectl v0.17.0 h1:xD4EWlL+epc/JTO1gvSjmV9yiYF0Z2wiHK2DIek6URY= +k8s.io/kubectl v0.17.0/go.mod h1:jIPrUAW656Vzn9wZCCe0PC+oTcu56u2HgFD21Xbfk1s= +k8s.io/metrics v0.17.0/go.mod h1:EH1D3YAwN6d7bMelrElnLhLg72l/ERStyv2SIQVt6Do= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= kubesphere.io/application v0.0.0-20190404151855-67ae7f915d4e/go.mod h1:NhUQ0ZUdFz8NTQ+SvQG0JUKAn+q71v3TPExjsjRPIZI= @@ -549,9 +572,13 @@ sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9 sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA= sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= +sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= +sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM= sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/hack/generate_client.sh b/hack/generate_client.sh index 9d094b8b0..106db5a04 100755 --- a/hack/generate_client.sh +++ b/hack/generate_client.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 devops:v1alpha1" +GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 devops:v1alpha1 logging:v1alpha2" rm -rf ./pkg/client ./hack/generate_group.sh "client,lister,informer" kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "$GV" --output-base=./ -h "$PWD/hack/boilerplate.go.txt" diff --git a/pkg/api/resource/resource.go b/pkg/api/resource/resource.go new file mode 100644 index 000000000..958e3540f --- /dev/null +++ b/pkg/api/resource/resource.go @@ -0,0 +1 @@ +package resource diff --git a/pkg/api/resource/v1alpha2/types.go b/pkg/api/resource/v1alpha2/types.go new file mode 100644 index 000000000..a263140da --- /dev/null +++ b/pkg/api/resource/v1alpha2/types.go @@ -0,0 +1,29 @@ +package v1alpha2 + +import "time" + +// ComponentStatus represents system component status. +type ComponentStatus struct { + Name string `json:"name" description:"component name"` + Namespace string `json:"namespace" description:"the name of the namespace"` + SelfLink string `json:"selfLink" description:"self link"` + Label interface{} `json:"label" description:"labels"` + StartedAt time.Time `json:"startedAt" description:"started time"` + TotalBackends int `json:"totalBackends" description:"the total replicas of each backend system component"` + HealthyBackends int `json:"healthyBackends" description:"the number of healthy backend components"` +} + +// NodeStatus assembles cluster nodes status, simply wrap unhealthy and total nodes. +type NodeStatus struct { + // total nodes of cluster, including master nodes + TotalNodes int `json:"totalNodes" description:"total number of nodes"` + + // healthy nodes means nodes whose state is NodeReady + HealthyNodes int `json:"healthyNodes" description:"the number of healthy nodes"` +} + +// +type HealthStatus struct { + KubeSphereComponents []ComponentStatus `json:"kubesphereStatus" description:"kubesphere components status"` + NodeStatus NodeStatus `json:"nodeStatus" description:"nodes status"` +} diff --git a/pkg/api/types.go b/pkg/api/types.go new file mode 100644 index 000000000..5086582a2 --- /dev/null +++ b/pkg/api/types.go @@ -0,0 +1,170 @@ +package api + +import ( + "github.com/emicklei/go-restful" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "net/http" +) + +type ListResult struct { + Items []interface{} `json:"items,omitempty"` + TotalItems int `json:"totalItems,omitempty"` +} + +type ResourceQuota struct { + Namespace string `json:"namespace" description:"namespace"` + Data corev1.ResourceQuotaStatus `json:"data" description:"resource quota status"` +} + +type NamespacedResourceQuota struct { + Namespace string `json:"namespace,omitempty"` + + Data struct { + corev1.ResourceQuotaStatus + + // quota left status, do the math on the side, cause it's + // a lot easier with go-client library + Left corev1.ResourceList `json:"left,omitempty"` + } `json:"data,omitempty"` +} + +type Router struct { + RouterType string `json:"type"` + Annotations map[string]string `json:"annotations"` +} + +type GitCredential struct { + RemoteUrl string `json:"remoteUrl" description:"git server url"` + SecretRef *corev1.SecretReference `json:"secretRef,omitempty" description:"auth secret reference"` +} + +type RegistryCredential struct { + Username string `json:"username" description:"username"` + Password string `json:"password" description:"password"` + ServerHost string `json:"serverhost" description:"registry server host"` +} + +type Workloads struct { + Namespace string `json:"namespace" description:"the name of the namespace"` + Count map[string]int `json:"data" description:"the number of unhealthy workloads"` + Items map[string]interface{} `json:"items,omitempty" description:"unhealthy workloads"` +} + +type ClientType string + +const ( + ClientKubernetes ClientType = "Kubernetes" + ClientKubeSphere ClientType = "Kubesphere" + ClientIstio ClientType = "Istio" + ClientS2i ClientType = "S2i" + ClientApplication ClientType = "Application" + + StatusOK = "ok" +) + +var SupportedGroupVersionResources = map[ClientType][]schema.GroupVersionResource{ + // all supported kubernetes api objects + ClientKubernetes: { + {Group: "", Version: "v1", Resource: "namespaces"}, + {Group: "", Version: "v1", Resource: "nodes"}, + {Group: "", Version: "v1", Resource: "resourcequotas"}, + {Group: "", Version: "v1", Resource: "pods"}, + {Group: "", Version: "v1", Resource: "services"}, + {Group: "", Version: "v1", Resource: "persistentvolumeclaims"}, + {Group: "", Version: "v1", Resource: "secrets"}, + {Group: "", Version: "v1", Resource: "configmaps"}, + + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"}, + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"}, + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"}, + {Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"}, + + {Group: "apps", Version: "v1", Resource: "deployments"}, + {Group: "apps", Version: "v1", Resource: "daemonsets"}, + {Group: "apps", Version: "v1", Resource: "replicasets"}, + {Group: "apps", Version: "v1", Resource: "statefulsets"}, + {Group: "apps", Version: "v1", Resource: "controllerrevisions"}, + + {Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"}, + + {Group: "batch", Version: "v1", Resource: "jobs"}, + {Group: "batch", Version: "v1beta1", Resource: "cronjobs"}, + + {Group: "extensions", Version: "v1beta1", Resource: "ingresses"}, + + {Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"}, + }, + + // all supported kubesphere api objects + ClientKubeSphere: { + {Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"}, + {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibinaries"}, + + {Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "strategies"}, + {Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "servicepolicies"}, + }, + + // all supported istio api objects + ClientIstio: {}, + + // all supported s2i api objects + // TODO: move s2i clientset into kubesphere + ClientS2i: { + {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"}, + {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"}, + {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"}, + }, + + // kubernetes-sigs application api objects + ClientApplication: { + {Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}, + }, +} + +// List of all resource kinds supported by the UI. +const ( + ResourceKindConfigMap = "configmaps" + ResourceKindDaemonSet = "daemonsets" + ResourceKindDeployment = "deployments" + ResourceKindEvent = "events" + ResourceKindHorizontalPodAutoscaler = "horizontalpodautoscalers" + ResourceKindIngress = "ingresses" + ResourceKindJob = "jobs" + ResourceKindCronJob = "cronjobs" + ResourceKindLimitRange = "limitranges" + ResourceKindNamespace = "namespaces" + ResourceKindNode = "nodes" + ResourceKindPersistentVolumeClaim = "persistentvolumeclaims" + ResourceKindPersistentVolume = "persistentvolumes" + ResourceKindCustomResourceDefinition = "customresourcedefinitions" + ResourceKindPod = "pods" + ResourceKindReplicaSet = "replicasets" + ResourceKindResourceQuota = "resourcequota" + ResourceKindSecret = "secrets" + ResourceKindService = "services" + ResourceKindStatefulSet = "statefulsets" + ResourceKindStorageClass = "storageclasses" + ResourceKindClusterRole = "clusterroles" + ResourceKindClusterRoleBinding = "clusterrolebindings" + ResourceKindRole = "roles" + ResourceKindRoleBinding = "rolebindings" + ResourceKindWorkspace = "workspaces" + ResourceKindS2iBinary = "s2ibinaries" + ResourceKindStrategy = "strategy" + ResourceKindServicePolicy = "servicepolicies" + ResourceKindS2iBuilderTemplate = "s2ibuildertemplates" + ResourceKindeS2iRun = "s2iruns" + ResourceKindS2iBuilder = "s2ibuilders" + ResourceKindApplication = "applications" +) + +func HandleInternalError(response *restful.Response, err error) { + statusCode := http.StatusInternalServerError + + response.WriteError(statusCode, err) +} + +func HandleBadRequest(response *restful.Response, err error) { + +} diff --git a/pkg/apigateway/caddy-plugin/authenticate/authenticate.go b/pkg/apigateway/caddy-plugin/authenticate/authenticate.go index 6cb0aaff8..e37efb9b9 100644 --- a/pkg/apigateway/caddy-plugin/authenticate/authenticate.go +++ b/pkg/apigateway/caddy-plugin/authenticate/authenticate.go @@ -25,7 +25,7 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" - "kubesphere.io/kubesphere/pkg/simple/client/redis" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "log" "net/http" "strconv" @@ -44,9 +44,9 @@ type Auth struct { type Rule struct { Secret []byte Path string - RedisOptions *redis.RedisOptions + RedisOptions *cache.Options TokenIdleTimeout time.Duration - RedisClient *redis.RedisClient + RedisClient cache.Interface ExclusionRules []internal.ExclusionRule } @@ -194,15 +194,15 @@ func (h Auth) Validate(uToken string) (*jwt.Token, error) { tokenKey := fmt.Sprintf("kubesphere:users:%s:token:%s", username, uToken) - exist, err := h.Rule.RedisClient.Redis().Exists(tokenKey).Result() + exist, err := h.Rule.RedisClient.Exists(tokenKey) if err != nil { klog.Error(err) return nil, err } - if exist == 1 { + if exist { // reset expiration time if token exist - h.Rule.RedisClient.Redis().Expire(tokenKey, h.Rule.TokenIdleTimeout) + h.Rule.RedisClient.Expire(tokenKey, h.Rule.TokenIdleTimeout) return token, nil } else { return nil, errors.New("illegal token") diff --git a/pkg/apigateway/caddy-plugin/authenticate/auto_load.go b/pkg/apigateway/caddy-plugin/authenticate/auto_load.go index 58ba4b485..111293ac0 100644 --- a/pkg/apigateway/caddy-plugin/authenticate/auto_load.go +++ b/pkg/apigateway/caddy-plugin/authenticate/auto_load.go @@ -20,7 +20,7 @@ package authenticate import ( "fmt" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" - "kubesphere.io/kubesphere/pkg/simple/client/redis" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "time" @@ -36,8 +36,10 @@ func Setup(c *caddy.Controller) error { return err } + stopCh := make(chan struct{}) + c.OnStartup(func() error { - rule.RedisClient, err = redis.NewRedisClient(rule.RedisOptions, nil) + rule.RedisClient, err = cache.NewRedisClient(rule.RedisOptions, stopCh) // ensure redis is connected when startup if err != nil { return err @@ -47,7 +49,8 @@ func Setup(c *caddy.Controller) error { }) c.OnShutdown(func() error { - return rule.RedisClient.Redis().Close() + close(stopCh) + return nil }) httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { @@ -96,7 +99,7 @@ func parse(c *caddy.Controller) (*Rule, error) { return nil, c.ArgErr() } - options := &redis.RedisOptions{RedisURL: c.Val()} + options := &cache.Options{RedisURL: c.Val()} if err := options.Validate(); len(err) > 0 { return nil, c.ArgErr() diff --git a/pkg/apigateway/caddy-plugin/authentication/authentication.go b/pkg/apigateway/caddy-plugin/authentication/authentication.go index d2e7a621d..40e765101 100644 --- a/pkg/apigateway/caddy-plugin/authentication/authentication.go +++ b/pkg/apigateway/caddy-plugin/authentication/authentication.go @@ -23,7 +23,9 @@ import ( "fmt" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/utils/k8sutil" "log" "net/http" @@ -34,21 +36,22 @@ import ( k8serr "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" - "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/utils/sliceutil" ) type Authentication struct { - Rule *Rule - Next httpserver.Handler + Rule *Rule + Next httpserver.Handler + informerFactory informers.SharedInformerFactory } type Rule struct { - Path string - ExclusionRules []internal.ExclusionRule + Path string + KubernetesOptions *k8s.KubernetesOptions + ExclusionRules []internal.ExclusionRule } -func (c Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { +func (c *Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { if httpserver.Path(r.URL.Path).Matches(c.Rule.Path) { @@ -65,7 +68,7 @@ func (c Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, return c.Next.ServeHTTP(w, r) } - permitted, err := permissionValidate(attrs) + permitted, err := c.permissionValidate(attrs) if err != nil { return http.StatusInternalServerError, err @@ -88,13 +91,13 @@ func handleForbidden(w http.ResponseWriter, err error) int { return http.StatusForbidden } -func permissionValidate(attrs authorizer.Attributes) (bool, error) { +func (c *Authentication) permissionValidate(attrs authorizer.Attributes) (bool, error) { if attrs.GetResource() == "users" && attrs.GetUser().GetName() == attrs.GetName() { return true, nil } - permitted, err := clusterRoleValidate(attrs) + permitted, err := c.clusterRoleValidate(attrs) if err != nil { log.Println("lister error", err) @@ -106,7 +109,7 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) { } if attrs.GetNamespace() != "" { - permitted, err = roleValidate(attrs) + permitted, err = c.roleValidate(attrs) if err != nil { log.Println("lister error", err) @@ -121,9 +124,9 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) { return false, nil } -func roleValidate(attrs authorizer.Attributes) (bool, error) { - roleBindingLister := informers.SharedInformerFactory().Rbac().V1().RoleBindings().Lister() - roleLister := informers.SharedInformerFactory().Rbac().V1().Roles().Lister() +func (c *Authentication) roleValidate(attrs authorizer.Attributes) (bool, error) { + roleBindingLister := c.informerFactory.Rbac().V1().RoleBindings().Lister() + roleLister := c.informerFactory.Rbac().V1().Roles().Lister() roleBindings, err := roleBindingLister.RoleBindings(attrs.GetNamespace()).List(labels.Everything()) if err != nil { @@ -158,10 +161,10 @@ func roleValidate(attrs authorizer.Attributes) (bool, error) { return false, nil } -func clusterRoleValidate(attrs authorizer.Attributes) (bool, error) { - clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() +func (c *Authentication) clusterRoleValidate(attrs authorizer.Attributes) (bool, error) { + clusterRoleBindingLister := c.informerFactory.Rbac().V1().ClusterRoleBindings().Lister() clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything()) - clusterRoleLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister() + clusterRoleLister := c.informerFactory.Rbac().V1().ClusterRoles().Lister() if err != nil { return false, err } diff --git a/pkg/apigateway/caddy-plugin/authentication/auto_load.go b/pkg/apigateway/caddy-plugin/authentication/auto_load.go index ee94d9eaf..24f0f17c9 100644 --- a/pkg/apigateway/caddy-plugin/authentication/auto_load.go +++ b/pkg/apigateway/caddy-plugin/authentication/auto_load.go @@ -21,7 +21,9 @@ import ( "fmt" "github.com/mholt/caddy" "github.com/mholt/caddy/caddyhttp/httpserver" + "k8s.io/klog" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/informers" @@ -31,19 +33,28 @@ import ( func Setup(c *caddy.Controller) error { rule, err := parse(c) - if err != nil { return err } + + if rule.KubernetesOptions == nil && rule.KubernetesOptions.KubeConfig == "" { + klog.Warning("no kubeconfig provided, will use in cluster config, this may not work") + } + + kubeClient, err := k8s.NewKubernetesClient(rule.KubernetesOptions) + if err != nil { + return err + } + informerFactory := informers.NewInformerFactories(kubeClient.Kubernetes(), nil, nil, nil) + stopChan := make(chan struct{}, 0) c.OnStartup(func() error { - informerFactory := informers.SharedInformerFactory() - informerFactory.Rbac().V1().Roles().Lister() - informerFactory.Rbac().V1().RoleBindings().Lister() - informerFactory.Rbac().V1().ClusterRoles().Lister() - informerFactory.Rbac().V1().ClusterRoleBindings().Lister() - informerFactory.Start(stopChan) - informerFactory.WaitForCacheSync(stopChan) + informerFactory.KubernetesSharedInformerFactory().Rbac().V1().Roles().Lister() + informerFactory.KubernetesSharedInformerFactory().Rbac().V1().RoleBindings().Lister() + informerFactory.KubernetesSharedInformerFactory().Rbac().V1().ClusterRoles().Lister() + informerFactory.KubernetesSharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() + informerFactory.KubernetesSharedInformerFactory().Start(stopChan) + informerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopChan) fmt.Println("Authentication middleware is initiated") return nil }) @@ -54,7 +65,7 @@ func Setup(c *caddy.Controller) error { }) httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { - return &Authentication{Next: next, Rule: rule} + return &Authentication{Next: next, Rule: rule, informerFactory: informerFactory.KubernetesSharedInformerFactory()} }) return nil } diff --git a/pkg/apis/addtoscheme_logging_v1alpha2.go b/pkg/apis/addtoscheme_logging_v1alpha2.go new file mode 100644 index 000000000..7f71b1184 --- /dev/null +++ b/pkg/apis/addtoscheme_logging_v1alpha2.go @@ -0,0 +1,8 @@ +package apis + +import "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme) +} diff --git a/pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go index 42481f051..b0023388b 100644 --- a/pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go @@ -56,7 +56,7 @@ func (in *S2iBinary) DeepCopyObject() runtime.Object { func (in *S2iBinaryList) DeepCopyInto(out *S2iBinaryList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]S2iBinary, len(*in)) diff --git a/pkg/apis/logging/group.go b/pkg/apis/logging/group.go new file mode 100644 index 000000000..2b43acc6b --- /dev/null +++ b/pkg/apis/logging/group.go @@ -0,0 +1 @@ +package logging diff --git a/pkg/apis/logging/v1alpha2/doc.go b/pkg/apis/logging/v1alpha2/doc.go new file mode 100644 index 000000000..8a66e4368 --- /dev/null +++ b/pkg/apis/logging/v1alpha2/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha2 contains API Schema definitions for the servicemesh v1alpha2 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/logging +// +k8s:defaulter-gen=TypeMeta +// +groupName=logging.kubesphere.io +package v1alpha2 diff --git a/pkg/apis/logging/v1alpha2/fluentbit_types.go b/pkg/apis/logging/v1alpha2/fluentbit_types.go new file mode 100644 index 000000000..91587d821 --- /dev/null +++ b/pkg/apis/logging/v1alpha2/fluentbit_types.go @@ -0,0 +1,71 @@ +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type FluentBit struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + Spec FluentBitSpec `json:"spec"` + Status FluentBitStatus `json:"status,omitempty"` +} + +// FluentBitSpec holds the spec for the operator +type FluentBitSpec struct { + Service []Plugin `json:"service"` + Input []Plugin `json:"input"` + Filter []Plugin `json:"filter"` + Output []Plugin `json:"output"` + Settings []Plugin `json:"settings"` +} + +// FluentBitStatus holds the status info for the operator +type FluentBitStatus struct { + // Fill me +} + +// Plugin struct for fluent-bit plugins +type Plugin struct { + Type string `json:"type" description:"output plugin type, eg. fluentbit-output-es"` + Name string `json:"name" description:"output plugin name, eg. fluentbit-output-es"` + Parameters []Parameter `json:"parameters" description:"output plugin configuration parameters"` +} + +// Fluent-bit output plugins +type OutputPlugin struct { + Plugin + Id string `json:"id,omitempty" description:"output uuid"` + Enable bool `json:"enable" description:"active status, one of true, false"` + Updatetime *metav1.Time `json:"updatetime,omitempty" description:"last updatetime"` +} + +// Parameter generic parameter type to handle values from different sources +type Parameter struct { + Name string `json:"name" description:"configuration parameter key, eg. Name. refer to Fluent bit's Output Plugins Section for more configuration parameters."` + ValueFrom *ValueFrom `json:"valueFrom,omitempty"` + Value string `json:"value" description:"configuration parameter value, eg. es. refer to Fluent bit's Output Plugins Section for more configuration parameters."` +} + +// ValueFrom generic type to determine value origin +type ValueFrom struct { + SecretKeyRef KubernetesSecret `json:"secretKeyRef"` +} + +// KubernetesSecret is a ValueFrom type +type KubernetesSecret struct { + Name string `json:"name"` + Key string `json:"key"` + Namespace string `json:"namespace"` +} + +// FluentBitList auto generated by the sdk +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type FluentBitList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []FluentBit `json:"items"` +} diff --git a/pkg/apis/logging/v1alpha2/register.go b/pkg/apis/logging/v1alpha2/register.go new file mode 100644 index 000000000..8307c8c67 --- /dev/null +++ b/pkg/apis/logging/v1alpha2/register.go @@ -0,0 +1,44 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 contains API Schema definitions for the tenant v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/logging +// +k8s:defaulter-gen=TypeMeta +// +groupName=logging.kubesphere.io +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "logging.kubesphere.io", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme is required by pkg/client/... + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource is required by pkg/client/listers/... +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 000000000..0fecefdf8 --- /dev/null +++ b/pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,251 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentBit) DeepCopyInto(out *FluentBit) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBit. +func (in *FluentBit) DeepCopy() *FluentBit { + if in == nil { + return nil + } + out := new(FluentBit) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentBit) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentBitList) DeepCopyInto(out *FluentBitList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FluentBit, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitList. +func (in *FluentBitList) DeepCopy() *FluentBitList { + if in == nil { + return nil + } + out := new(FluentBitList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FluentBitList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentBitSpec) DeepCopyInto(out *FluentBitSpec) { + *out = *in + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Input != nil { + in, out := &in.Input, &out.Input + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Output != nil { + in, out := &in.Output, &out.Output + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Settings != nil { + in, out := &in.Settings, &out.Settings + *out = make([]Plugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitSpec. +func (in *FluentBitSpec) DeepCopy() *FluentBitSpec { + if in == nil { + return nil + } + out := new(FluentBitSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluentBitStatus) DeepCopyInto(out *FluentBitStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitStatus. +func (in *FluentBitStatus) DeepCopy() *FluentBitStatus { + if in == nil { + return nil + } + out := new(FluentBitStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubernetesSecret) DeepCopyInto(out *KubernetesSecret) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesSecret. +func (in *KubernetesSecret) DeepCopy() *KubernetesSecret { + if in == nil { + return nil + } + out := new(KubernetesSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OutputPlugin) DeepCopyInto(out *OutputPlugin) { + *out = *in + in.Plugin.DeepCopyInto(&out.Plugin) + if in.Updatetime != nil { + in, out := &in.Updatetime, &out.Updatetime + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutputPlugin. +func (in *OutputPlugin) DeepCopy() *OutputPlugin { + if in == nil { + return nil + } + out := new(OutputPlugin) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Parameter) DeepCopyInto(out *Parameter) { + *out = *in + if in.ValueFrom != nil { + in, out := &in.ValueFrom, &out.ValueFrom + *out = new(ValueFrom) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parameter. +func (in *Parameter) DeepCopy() *Parameter { + if in == nil { + return nil + } + out := new(Parameter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Plugin) DeepCopyInto(out *Plugin) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make([]Parameter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugin. +func (in *Plugin) DeepCopy() *Plugin { + if in == nil { + return nil + } + out := new(Plugin) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ValueFrom) DeepCopyInto(out *ValueFrom) { + *out = *in + out.SecretKeyRef = in.SecretKeyRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueFrom. +func (in *ValueFrom) DeepCopy() *ValueFrom { + if in == nil { + return nil + } + out := new(ValueFrom) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go index d2a563ca8..ae35ee8ab 100644 --- a/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/network/v1alpha1/zz_generated.deepcopy.go @@ -168,7 +168,7 @@ func (in *NamespaceNetworkPolicy) DeepCopyObject() runtime.Object { func (in *NamespaceNetworkPolicyList) DeepCopyInto(out *NamespaceNetworkPolicyList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]NamespaceNetworkPolicy, len(*in)) @@ -398,7 +398,7 @@ func (in *WorkspaceNetworkPolicyIngressRule) DeepCopy() *WorkspaceNetworkPolicyI func (in *WorkspaceNetworkPolicyList) DeepCopyInto(out *WorkspaceNetworkPolicyList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]WorkspaceNetworkPolicy, len(*in)) diff --git a/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go index fb56a0ea7..23e36c5f8 100644 --- a/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/servicemesh/v1alpha2/zz_generated.deepcopy.go @@ -93,7 +93,7 @@ func (in *ServicePolicyCondition) DeepCopy() *ServicePolicyCondition { func (in *ServicePolicyList) DeepCopyInto(out *ServicePolicyList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]ServicePolicy, len(*in)) @@ -225,7 +225,7 @@ func (in *StrategyCondition) DeepCopy() *StrategyCondition { func (in *StrategyList) DeepCopyInto(out *StrategyList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Strategy, len(*in)) diff --git a/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go index 2bb7f7349..b50a8d568 100644 --- a/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/tenant/v1alpha1/zz_generated.deepcopy.go @@ -56,7 +56,7 @@ func (in *Workspace) DeepCopyObject() runtime.Object { func (in *WorkspaceList) DeepCopyInto(out *WorkspaceList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Workspace, len(*in)) diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go new file mode 100644 index 000000000..b3ab9bf0c --- /dev/null +++ b/pkg/apiserver/apiserver.go @@ -0,0 +1,81 @@ +package apiserver + +import ( + "github.com/emicklei/go-restful" + "kubesphere.io/kubesphere/pkg/informers" + resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3" + "kubesphere.io/kubesphere/pkg/server/options" + "kubesphere.io/kubesphere/pkg/simple/client/cache" + "kubesphere.io/kubesphere/pkg/simple/client/db" + "kubesphere.io/kubesphere/pkg/simple/client/devops" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "kubesphere.io/kubesphere/pkg/simple/client/logging" + "kubesphere.io/kubesphere/pkg/simple/client/monitoring" + "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" + "kubesphere.io/kubesphere/pkg/simple/client/s3" +) + +const ( + // ApiRootPath defines the root path of all KubeSphere apis. + ApiRootPath = "/kapis" + + // MimeMergePatchJson is the mime header used in merge request + MimeMergePatchJson = "application/merge-patch+json" + + // + MimeJsonPatchJson = "application/json-patch+json" +) + +// Dependencies is objects constructed at runtime that are necessary for running apiserver. +type Dependencies struct { + + // Injected Dependencies + KubeClient k8s.Client + S3 s3.Interface + OpenPitrix openpitrix.Interface + Monitoring monitoring.Interface + Logging logging.Interface + Devops devops.Interface + DB db.Interface +} + +type APIServer struct { + + // number of kubesphere apiserver + apiserverCount int + + // + genericServerOptions *options.ServerRunOptions + + // webservice container, where all webservice defines + container *restful.Container + + // kubeClient is a collection of all kubernetes(include CRDs) objects clientset + kubeClient k8s.Client + + // informerFactory is a collection of all kubernetes(include CRDs) objects informers, + // mainly for fast query + informerFactory informers.InformerFactory + + // cache is used for short lived objects, like session + cache cache.Interface + + // + +} + +func New(deps *Dependencies) *APIServer { + + server := &APIServer{} + + return server +} + +func (s *APIServer) InstallKubeSphereAPIs() { + + resourcev1alpha3.AddWebService(s.container, s.kubeClient) +} + +func (s *APIServer) Serve() error { + panic("implement me") +} diff --git a/pkg/apiserver/components/components.go b/pkg/apiserver/components/components.go deleted file mode 100644 index be8b692da..000000000 --- a/pkg/apiserver/components/components.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package components - -import ( - "github.com/emicklei/go-restful" - "kubesphere.io/kubesphere/pkg/models/components" - "kubesphere.io/kubesphere/pkg/server/errors" - "net/http" -) - -func GetSystemHealthStatus(request *restful.Request, response *restful.Response) { - result, err := components.GetSystemHealthStatus() - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(result) -} - -// get a specific component status -func GetComponentStatus(request *restful.Request, response *restful.Response) { - component := request.PathParameter("component") - - result, err := components.GetComponentStatus(component) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(result) -} - -// get all componentsHandler -func GetComponents(request *restful.Request, response *restful.Response) { - - result, err := components.GetAllComponentsStatus() - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(result) -} diff --git a/pkg/apiserver/git/git.go b/pkg/apiserver/git/git.go deleted file mode 100644 index 6f7ae3148..000000000 --- a/pkg/apiserver/git/git.go +++ /dev/null @@ -1,30 +0,0 @@ -package git - -import ( - "net/http" - - "github.com/emicklei/go-restful" - "kubesphere.io/kubesphere/pkg/models/git" - "kubesphere.io/kubesphere/pkg/server/errors" -) - -func GitReadVerify(request *restful.Request, response *restful.Response) { - - authInfo := git.AuthInfo{} - - err := request.ReadEntity(&authInfo) - ns := request.PathParameter("namespace") - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - err = git.GitReadVerify(ns, authInfo) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(errors.None) -} diff --git a/pkg/apiserver/logging/logging.go b/pkg/apiserver/logging/logging.go index 39a73e608..40d7ffc72 100644 --- a/pkg/apiserver/logging/logging.go +++ b/pkg/apiserver/logging/logging.go @@ -28,7 +28,6 @@ import ( "kubesphere.io/kubesphere/pkg/models/log" "kubesphere.io/kubesphere/pkg/server/errors" cs "kubesphere.io/kubesphere/pkg/simple/client" - fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit" "kubesphere.io/kubesphere/pkg/utils/stringutils" "net/http" "strconv" diff --git a/pkg/apiserver/openpitrix/applications.go b/pkg/apiserver/openpitrix/applications.go index f536cf85f..bc2b337b6 100644 --- a/pkg/apiserver/openpitrix/applications.go +++ b/pkg/apiserver/openpitrix/applications.go @@ -28,7 +28,7 @@ import ( "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models/openpitrix" - "kubesphere.io/kubesphere/pkg/models/resources" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/simple/client" @@ -53,7 +53,7 @@ func ListApplications(req *restful.Request, resp *restful.Response) { } if namespaceName != "" { - namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) + namespace, err := v1alpha2.GetResource("", v1alpha2.Namespaces, namespaceName) if err != nil { klog.Errorln(err) @@ -109,7 +109,7 @@ func DescribeApplication(req *restful.Request, resp *restful.Response) { return } - namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) + namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName) if err != nil { klog.Errorln(err) @@ -186,7 +186,7 @@ func ModifyApplication(req *restful.Request, resp *restful.Response) { return } - namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) + namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName) if err != nil { klog.Errorln(err) @@ -243,7 +243,7 @@ func DeleteApplication(req *restful.Request, resp *restful.Response) { return } - namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) + namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName) if err != nil { klog.Errorln(err) diff --git a/pkg/apiserver/operations/job.go b/pkg/apiserver/operations/job.go deleted file mode 100644 index db10b3455..000000000 --- a/pkg/apiserver/operations/job.go +++ /dev/null @@ -1,57 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package operations - -import ( - k8serr "k8s.io/apimachinery/pkg/api/errors" - "kubesphere.io/kubesphere/pkg/models/workloads" - "kubesphere.io/kubesphere/pkg/server/errors" - "net/http" - - "github.com/emicklei/go-restful" - - "fmt" -) - -func RerunJob(req *restful.Request, resp *restful.Response) { - var err error - - job := req.PathParameter("job") - namespace := req.PathParameter("namespace") - action := req.QueryParameter("action") - resourceVersion := req.QueryParameter("resourceVersion") - - switch action { - case "rerun": - err = workloads.JobReRun(namespace, job, resourceVersion) - default: - resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("invalid operation %s", action))) - return - } - if err != nil { - if k8serr.IsConflict(err) { - resp.WriteHeaderAndEntity(http.StatusConflict, errors.Wrap(err)) - return - } - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(errors.None) -} diff --git a/pkg/apiserver/operations/node.go b/pkg/apiserver/operations/node.go deleted file mode 100644 index b70bf67f4..000000000 --- a/pkg/apiserver/operations/node.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package operations - -import ( - "github.com/emicklei/go-restful" - "net/http" - - "kubesphere.io/kubesphere/pkg/models/nodes" - "kubesphere.io/kubesphere/pkg/server/errors" -) - -func DrainNode(request *restful.Request, response *restful.Response) { - - nodeName := request.PathParameter("node") - - err := nodes.DrainNode(nodeName) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(errors.None) -} diff --git a/pkg/apiserver/query/field.go b/pkg/apiserver/query/field.go new file mode 100644 index 000000000..228a6b301 --- /dev/null +++ b/pkg/apiserver/query/field.go @@ -0,0 +1,30 @@ +package query + +type Field string + +const ( + FieldName = "name" + FieldCreationTimeStamp = "creationTimestamp" + FieldLastUpdateTimestamp = "lastUpdateTimestamp" + FieldNamespace = "namespace" + FieldStatus = "status" + FieldApplication = "application" + FieldOwner = "owner" + FieldOwnerKind = "ownerKind" +) + +var SortableFields = []Field{ + FieldCreationTimeStamp, + FieldLastUpdateTimestamp, + FieldName, +} + +// Field contains all the query field that can be compared +var ComparableFields = []Field{ + FieldName, + FieldNamespace, + FieldStatus, + FieldApplication, + FieldOwner, + FieldOwnerKind, +} diff --git a/pkg/apiserver/query/types.go b/pkg/apiserver/query/types.go new file mode 100644 index 000000000..6bc4054e6 --- /dev/null +++ b/pkg/apiserver/query/types.go @@ -0,0 +1,145 @@ +package query + +import ( + "github.com/emicklei/go-restful" + "strconv" + "strings" +) + +const ( + ParameterName = "name" + ParameterLabelSelector = "labelSelector" + ParameterFieldSelector = "fieldSelector" + ParameterPage = "page" + ParameterLimit = "limit" + ParameterOrderBy = "sortBy" + ParameterAscending = "ascending" +) + +type Comparable interface { + Compare(Comparable) int + + Contains(Comparable) bool +} + +type ComparableString string + +func (c ComparableString) Compare(comparable Comparable) int { + other := comparable.(ComparableString) + return strings.Compare(string(c), string(other)) +} + +func (c ComparableString) Contains(comparable Comparable) bool { + other := comparable.(ComparableString) + return strings.Contains(string(c), string(other)) +} + +// Query represents api search terms +type Query struct { + Pagination *Pagination + + // sort result in which field, default to FieldCreationTimeStamp + SortBy Field + + // sort result in ascending or descending order, default to descending + Ascending bool + + // + Filters []Filter +} + +type Pagination struct { + // items per page + Limit int + + // page number + Page int +} + +var NoPagination = newPagination(-1, -1) + +func newPagination(limit int, page int) *Pagination { + return &Pagination{ + Limit: limit, + Page: page, + } +} + +func (p *Pagination) IsValidPagintaion() bool { + return p.Limit >= 0 && p.Page >= 0 +} + +func (p *Pagination) IsPageAvailable(total, startIndex int) bool { + return total > startIndex && p.Limit > 0 +} + +func (p *Pagination) GetPaginationSettings(total int) (startIndex, endIndex int) { + startIndex = p.Limit * p.Page + endIndex = startIndex + p.Limit + + if endIndex > total { + endIndex = total + } + + return startIndex, endIndex +} + +func New() *Query { + return &Query{ + Pagination: &Pagination{ + Limit: -1, + Page: -1, + }, + SortBy: "", + Ascending: false, + Filters: []Filter{}, + } +} + +type Filter struct { + Field Field + Value Comparable +} + +func ParseQueryParameter(request *restful.Request) *Query { + query := New() + + limit, err := strconv.ParseInt(request.QueryParameter("limit"), 10, 0) + if err != nil { + query.Pagination = NoPagination + } + + page, err := strconv.ParseInt(request.QueryParameter("page"), 10, 0) + if err == nil { + query.Pagination = newPagination(int(limit), int(page-1)) + } + + query.SortBy = Field(defaultString(request.QueryParameter("sortBy"), FieldCreationTimeStamp)) + + ascending, err := strconv.ParseBool(defaultString(request.QueryParameter("ascending"), "false")) + if err != nil { + query.Ascending = false + } else { + query.Ascending = ascending + } + + for _, field := range ComparableFields { + f := request.QueryParameter(string(field)) + if len(f) != 0 { + query.Filters = append(query.Filters, Filter{ + Field: field, + Value: ComparableString(f), + }) + } + } + + return query + +} + +func defaultString(value, defaultValue string) string { + if len(value) == 0 { + return defaultValue + } + return value +} diff --git a/pkg/apiserver/query/types_test.go b/pkg/apiserver/query/types_test.go new file mode 100644 index 000000000..a62fb0b61 --- /dev/null +++ b/pkg/apiserver/query/types_test.go @@ -0,0 +1,72 @@ +package query + +import ( + "fmt" + "github.com/emicklei/go-restful" + "github.com/google/go-cmp/cmp" + "net/http" + "testing" +) + +func TestParseQueryParameter(t *testing.T) { + tests := []struct { + description string + queryString string + expected *Query + }{ + { + "test normal case", + "name=foo&status=Running&application=book&page=1&limit=10&ascending=true", + &Query{ + Pagination: newPagination(10, 0), + SortBy: FieldCreationTimeStamp, + Ascending: true, + Filters: []Filter{ + { + FieldName, + ComparableString("foo"), + }, + { + FieldStatus, + ComparableString("Running"), + }, + { + FieldApplication, + ComparableString("book"), + }, + }, + }, + }, + { + "test bad case", + "xxxx=xxxx&dsfsw=xxxx&page=abc&limit=add&ascending=ssss", + &Query{ + Pagination: &Pagination{ + Limit: -1, + Page: -1, + }, + SortBy: FieldCreationTimeStamp, + Ascending: false, + Filters: []Filter{}, + }, + }, + } + + for _, test := range tests { + req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost?%s", test.queryString), nil) + if err != nil { + t.Fatal(err) + } + + request := restful.NewRequest(req) + + t.Run(test.description, func(t *testing.T) { + got := ParseQueryParameter(request) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("%T differ (-got, +want): %s", test.expected, diff) + return + } + }) + } +} diff --git a/pkg/apiserver/quotas/quotas.go b/pkg/apiserver/quotas/quotas.go deleted file mode 100644 index 3d9376ef4..000000000 --- a/pkg/apiserver/quotas/quotas.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package quotas - -import ( - "github.com/emicklei/go-restful" - "net/http" - - "kubesphere.io/kubesphere/pkg/server/errors" - - "kubesphere.io/kubesphere/pkg/models/quotas" -) - -func GetNamespaceQuotas(req *restful.Request, resp *restful.Response) { - namespace := req.PathParameter("namespace") - quota, err := quotas.GetNamespaceQuotas(namespace) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(quota) -} - -func GetClusterQuotas(req *restful.Request, resp *restful.Response) { - quota, err := quotas.GetClusterQuotas() - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(quota) -} diff --git a/pkg/apiserver/registries/registries.go b/pkg/apiserver/registries/registries.go deleted file mode 100644 index ef785013a..000000000 --- a/pkg/apiserver/registries/registries.go +++ /dev/null @@ -1,127 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package registries - -import ( - "github.com/emicklei/go-restful" - "net/http" - - "kubesphere.io/kubesphere/pkg/models/registries" - "kubesphere.io/kubesphere/pkg/server/errors" - - k8serror "k8s.io/apimachinery/pkg/api/errors" - log "k8s.io/klog" -) - -func RegistryVerify(request *restful.Request, response *restful.Response) { - - authInfo := registries.AuthInfo{} - - err := request.ReadEntity(&authInfo) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - err = registries.RegistryVerify(authInfo) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(errors.None) -} - -func RegistryImageBlob(request *restful.Request, response *restful.Response) { - imageName := request.QueryParameter("image") - namespace := request.QueryParameter("namespace") - secretName := request.QueryParameter("secret") - - // get entry - entry, err := registries.GetEntryBySecret(namespace, secretName) - if err != nil { - log.Errorf("%+v", err) - if k8serror.IsNotFound(err) { - log.Errorf("%+v", err) - errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response) - return - } - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()}) - return - } - - // parse image - image, err := registries.ParseImage(imageName) - if err != nil { - log.Errorf("%+v", err) - errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response) - return - } - - // Create the registry client. - r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain) - if err != nil { - log.Errorf("%+v", err) - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()}) - return - } - - digestUrl := r.GetDigestUrl(image) - - // Get token. - token, err := r.Token(digestUrl) - if err != nil { - log.Errorf("%+v", err) - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()}) - return - } - - // Get digest. - imageManifest, err := r.ImageManifest(image, token) - if err != nil { - if serviceError, ok := err.(restful.ServiceError); ok { - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: serviceError.Message}) - return - } - log.Errorf("%+v", err) - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()}) - return - } - image.Digest = imageManifest.ManifestConfig.Digest - - // Get blob. - imageBlob, err := r.ImageBlob(image, token) - if err != nil { - log.Errorf("%+v", err) - response.WriteAsJson(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()}) - return - } - - imageDetails := ®istries.ImageDetails{ - Status: registries.StatusSuccess, - ImageManifest: imageManifest, - ImageBlob: imageBlob, - ImageTag: image.Tag, - Registry: image.Domain, - } - - response.WriteAsJson(imageDetails) -} diff --git a/pkg/apiserver/resources/resources.go b/pkg/apiserver/resources/resources.go deleted file mode 100644 index 484c6c5cc..000000000 --- a/pkg/apiserver/resources/resources.go +++ /dev/null @@ -1,54 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package resources - -import ( - "github.com/emicklei/go-restful" - "kubesphere.io/kubesphere/pkg/models/resources" - "net/http" - - "kubesphere.io/kubesphere/pkg/server/errors" - "kubesphere.io/kubesphere/pkg/server/params" -) - -func ListNamespacedResources(req *restful.Request, resp *restful.Response) { - ListResources(req, resp) -} - -func ListResources(req *restful.Request, resp *restful.Response) { - namespace := req.PathParameter("namespace") - resourceName := req.PathParameter("resources") - conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam)) - orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime) - limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam)) - reverse := params.ParseReverse(req) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) - return - } - - result, err := resources.ListResources(namespace, resourceName, conditions, orderBy, reverse, limit, offset) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(result) -} diff --git a/pkg/apiserver/resources/storage.go b/pkg/apiserver/resources/storage.go deleted file mode 100644 index 330aa3668..000000000 --- a/pkg/apiserver/resources/storage.go +++ /dev/null @@ -1,71 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package resources - -import ( - "github.com/emicklei/go-restful" - "k8s.io/api/core/v1" - "net/http" - - "kubesphere.io/kubesphere/pkg/models/storage" - "kubesphere.io/kubesphere/pkg/server/errors" -) - -type pvcList struct { - Name string `json:"name"` - Items []*v1.PersistentVolumeClaim `json:"items"` -} - -type podListByPvc struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Pods []*v1.Pod `json:"pods"` -} - -// List all pods of a specific PVC -// Extended API URL: "GET /api/v1alpha2/namespaces/{namespace}/persistentvolumeclaims/{name}/pods" -func GetPodListByPvc(request *restful.Request, response *restful.Response) { - - pvcName := request.PathParameter("pvc") - nsName := request.PathParameter("namespace") - pods, err := storage.GetPodListByPvc(pvcName, nsName) - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - result := podListByPvc{Name: pvcName, Namespace: nsName, Pods: pods} - response.WriteAsJson(result) -} - -// List all PersistentVolumeClaims of a specific StorageClass -// Extended API URL: "GET /api/v1alpha2/storageclasses/{storageclass}/persistentvolumeclaims" -func GetPvcListBySc(request *restful.Request, response *restful.Response) { - scName := request.PathParameter("storageclass") - claims, err := storage.GetPvcListBySc(scName) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - result := pvcList{ - Name: scName, Items: claims, - } - - response.WriteAsJson(result) -} diff --git a/pkg/apiserver/revisions/revisions.go b/pkg/apiserver/revisions/revisions.go deleted file mode 100644 index 895c6f5ea..000000000 --- a/pkg/apiserver/revisions/revisions.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package revisions - -import ( - "net/http" - "strconv" - - "github.com/emicklei/go-restful" - "kubesphere.io/kubesphere/pkg/models/revisions" - "kubesphere.io/kubesphere/pkg/server/errors" -) - -func GetDaemonSetRevision(req *restful.Request, resp *restful.Response) { - daemonset := req.PathParameter("daemonset") - namespace := req.PathParameter("namespace") - revision, err := strconv.Atoi(req.PathParameter("revision")) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) - return - } - - result, err := revisions.GetDaemonSetRevision(namespace, daemonset, revision) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(result) -} - -func GetDeployRevision(req *restful.Request, resp *restful.Response) { - deploy := req.PathParameter("deployment") - namespace := req.PathParameter("namespace") - revision := req.PathParameter("revision") - - result, err := revisions.GetDeployRevision(namespace, deploy, revision) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(result) -} - -func GetStatefulSetRevision(req *restful.Request, resp *restful.Response) { - statefulset := req.PathParameter("statefulset") - namespace := req.PathParameter("namespace") - revision, err := strconv.Atoi(req.PathParameter("revision")) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) - return - } - - result, err := revisions.GetStatefulSetRevision(namespace, statefulset, revision) - - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - resp.WriteAsJson(result) -} diff --git a/pkg/apiserver/routers/routers.go b/pkg/apiserver/routers/routers.go deleted file mode 100644 index 992f02441..000000000 --- a/pkg/apiserver/routers/routers.go +++ /dev/null @@ -1,151 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package routers - -import ( - "fmt" - "github.com/emicklei/go-restful" - k8serr "k8s.io/apimachinery/pkg/api/errors" - "net/http" - - "kubesphere.io/kubesphere/pkg/server/errors" - - "strings" - - "k8s.io/api/core/v1" - - "kubesphere.io/kubesphere/pkg/models/routers" -) - -type Router struct { - RouterType string `json:"type"` - Annotations map[string]string `json:"annotations"` -} - -// Get all namespace ingress controller services -func GetAllRouters(request *restful.Request, response *restful.Response) { - - routers, err := routers.GetAllRouters() - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(routers) -} - -// Get ingress controller service for specified namespace -func GetRouter(request *restful.Request, response *restful.Response) { - - namespace := request.PathParameter("namespace") - router, err := routers.GetRouter(namespace) - - if err != nil { - if k8serr.IsNotFound(err) { - response.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err)) - } else { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - } - return - } - - response.WriteAsJson(router) -} - -// Create ingress controller and related services -func CreateRouter(request *restful.Request, response *restful.Response) { - - namespace := request.PathParameter("namespace") - - newRouter := Router{} - err := request.ReadEntity(&newRouter) - - if err != nil { - response.WriteAsJson(err) - return - } - - var router *v1.Service - - serviceType, annotationMap, err := parseParameter(newRouter) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("wrong annotations, missing key or value"))) - return - } - - router, err = routers.CreateRouter(namespace, serviceType, annotationMap) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(router) -} - -// Delete ingress controller and services -func DeleteRouter(request *restful.Request, response *restful.Response) { - namespace := request.PathParameter("namespace") - - router, err := routers.DeleteRouter(namespace) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(router) -} - -func UpdateRouter(request *restful.Request, response *restful.Response) { - - namespace := request.PathParameter("namespace") - - newRouter := Router{} - err := request.ReadEntity(&newRouter) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) - return - } - - serviceType, annotationMap, err := parseParameter(newRouter) - - router, err := routers.UpdateRouter(namespace, serviceType, annotationMap) - - if err != nil { - response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - - response.WriteAsJson(router) -} - -func parseParameter(router Router) (routerType v1.ServiceType, annotationMap map[string]string, err error) { - - routerType = v1.ServiceTypeNodePort - - if strings.Compare(strings.ToLower(router.RouterType), "loadbalancer") == 0 { - routerType = v1.ServiceTypeLoadBalancer - } - - return routerType, router.Annotations, nil -} diff --git a/pkg/apiserver/tenant/tenant.go b/pkg/apiserver/tenant/tenant.go index d0f6a35b2..759bd62a1 100644 --- a/pkg/apiserver/tenant/tenant.go +++ b/pkg/apiserver/tenant/tenant.go @@ -31,7 +31,7 @@ import ( "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models/iam" "kubesphere.io/kubesphere/pkg/models/metrics" - "kubesphere.io/kubesphere/pkg/models/resources" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/models/tenant" "kubesphere.io/kubesphere/pkg/models/workspaces" "kubesphere.io/kubesphere/pkg/server/errors" @@ -64,7 +64,7 @@ func ListWorkspaces(req *restful.Request, resp *restful.Response) { reverse := params.ParseReverse(req) if orderBy == "" { - orderBy = resources.CreateTime + orderBy = v1alpha2.CreateTime reverse = true } diff --git a/pkg/apiserver/workloadstatuses/workloadstatuses.go b/pkg/apiserver/workloadstatuses/workloadstatuses.go deleted file mode 100644 index fe5ebfd26..000000000 --- a/pkg/apiserver/workloadstatuses/workloadstatuses.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -package workloadstatuses - -import ( - "github.com/emicklei/go-restful" - "net/http" - - "kubesphere.io/kubesphere/pkg/models/status" - "kubesphere.io/kubesphere/pkg/server/errors" -) - -func GetClusterAbnormalWorkloads(req *restful.Request, resp *restful.Response) { - res, err := status.GetClusterResourceStatus() - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - resp.WriteAsJson(res) -} - -func GetNamespacedAbnormalWorkloads(req *restful.Request, resp *restful.Response) { - res, err := status.GetNamespacesResourceStatus(req.PathParameter("namespace")) - if err != nil { - resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) - return - } - resp.WriteAsJson(res) -} diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index cdf28675e..73b17c3ac 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -25,6 +25,7 @@ import ( rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" + loggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2" networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/tenant/v1alpha1" @@ -33,6 +34,7 @@ import ( type Interface interface { Discovery() discovery.DiscoveryInterface DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface + LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface TenantV1alpha1() tenantv1alpha1.TenantV1alpha1Interface @@ -43,6 +45,7 @@ type Interface interface { type Clientset struct { *discovery.DiscoveryClient devopsV1alpha1 *devopsv1alpha1.DevopsV1alpha1Client + loggingV1alpha2 *loggingv1alpha2.LoggingV1alpha2Client networkV1alpha1 *networkv1alpha1.NetworkV1alpha1Client servicemeshV1alpha2 *servicemeshv1alpha2.ServicemeshV1alpha2Client tenantV1alpha1 *tenantv1alpha1.TenantV1alpha1Client @@ -53,6 +56,11 @@ func (c *Clientset) DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface { return c.devopsV1alpha1 } +// LoggingV1alpha2 retrieves the LoggingV1alpha2Client +func (c *Clientset) LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface { + return c.loggingV1alpha2 +} + // NetworkV1alpha1 retrieves the NetworkV1alpha1Client func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { return c.networkV1alpha1 @@ -93,6 +101,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.loggingV1alpha2, err = loggingv1alpha2.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.networkV1alpha1, err = networkv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -118,6 +130,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.devopsV1alpha1 = devopsv1alpha1.NewForConfigOrDie(c) + cs.loggingV1alpha2 = loggingv1alpha2.NewForConfigOrDie(c) cs.networkV1alpha1 = networkv1alpha1.NewForConfigOrDie(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.NewForConfigOrDie(c) cs.tenantV1alpha1 = tenantv1alpha1.NewForConfigOrDie(c) @@ -130,6 +143,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { func New(c rest.Interface) *Clientset { var cs Clientset cs.devopsV1alpha1 = devopsv1alpha1.New(c) + cs.loggingV1alpha2 = loggingv1alpha2.New(c) cs.networkV1alpha1 = networkv1alpha1.New(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.New(c) cs.tenantV1alpha1 = tenantv1alpha1.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 2eb0a0a07..5077dd3ae 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -27,6 +27,8 @@ import ( clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" fakedevopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1/fake" + loggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2" + fakeloggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake" networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" fakenetworkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1/fake" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" @@ -87,6 +89,11 @@ func (c *Clientset) DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface { return &fakedevopsv1alpha1.FakeDevopsV1alpha1{Fake: &c.Fake} } +// LoggingV1alpha2 retrieves the LoggingV1alpha2Client +func (c *Clientset) LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface { + return &fakeloggingv1alpha2.FakeLoggingV1alpha2{Fake: &c.Fake} +} + // NetworkV1alpha1 retrieves the NetworkV1alpha1Client func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { return &fakenetworkv1alpha1.FakeNetworkV1alpha1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 36f2e736e..028831216 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -25,6 +25,7 @@ import ( serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" + loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" @@ -35,6 +36,7 @@ var codecs = serializer.NewCodecFactory(scheme) var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ devopsv1alpha1.AddToScheme, + loggingv1alpha2.AddToScheme, networkv1alpha1.AddToScheme, servicemeshv1alpha2.AddToScheme, tenantv1alpha1.AddToScheme, diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 30434c545..7e293b490 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -25,6 +25,7 @@ import ( serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" + loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" @@ -35,6 +36,7 @@ var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ devopsv1alpha1.AddToScheme, + loggingv1alpha2.AddToScheme, networkv1alpha1.AddToScheme, servicemeshv1alpha2.AddToScheme, tenantv1alpha1.AddToScheme, diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go new file mode 100644 index 000000000..02d20203a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha2 diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/doc.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/doc.go new file mode 100644 index 000000000..329c98fb5 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_fluentbit.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_fluentbit.go new file mode 100644 index 000000000..8f27f3959 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_fluentbit.go @@ -0,0 +1,140 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" +) + +// FakeFluentBits implements FluentBitInterface +type FakeFluentBits struct { + Fake *FakeLoggingV1alpha2 + ns string +} + +var fluentbitsResource = schema.GroupVersionResource{Group: "logging.kubesphere.io", Version: "v1alpha2", Resource: "fluentbits"} + +var fluentbitsKind = schema.GroupVersionKind{Group: "logging.kubesphere.io", Version: "v1alpha2", Kind: "FluentBit"} + +// Get takes name of the fluentBit, and returns the corresponding fluentBit object, and an error if there is any. +func (c *FakeFluentBits) Get(name string, options v1.GetOptions) (result *v1alpha2.FluentBit, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(fluentbitsResource, c.ns, name), &v1alpha2.FluentBit{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.FluentBit), err +} + +// List takes label and field selectors, and returns the list of FluentBits that match those selectors. +func (c *FakeFluentBits) List(opts v1.ListOptions) (result *v1alpha2.FluentBitList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(fluentbitsResource, fluentbitsKind, c.ns, opts), &v1alpha2.FluentBitList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha2.FluentBitList{ListMeta: obj.(*v1alpha2.FluentBitList).ListMeta} + for _, item := range obj.(*v1alpha2.FluentBitList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested fluentBits. +func (c *FakeFluentBits) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(fluentbitsResource, c.ns, opts)) + +} + +// Create takes the representation of a fluentBit and creates it. Returns the server's representation of the fluentBit, and an error, if there is any. +func (c *FakeFluentBits) Create(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(fluentbitsResource, c.ns, fluentBit), &v1alpha2.FluentBit{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.FluentBit), err +} + +// Update takes the representation of a fluentBit and updates it. Returns the server's representation of the fluentBit, and an error, if there is any. +func (c *FakeFluentBits) Update(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(fluentbitsResource, c.ns, fluentBit), &v1alpha2.FluentBit{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.FluentBit), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeFluentBits) UpdateStatus(fluentBit *v1alpha2.FluentBit) (*v1alpha2.FluentBit, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(fluentbitsResource, "status", c.ns, fluentBit), &v1alpha2.FluentBit{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.FluentBit), err +} + +// Delete takes name of the fluentBit and deletes it. Returns an error if one occurs. +func (c *FakeFluentBits) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(fluentbitsResource, c.ns, name), &v1alpha2.FluentBit{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeFluentBits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(fluentbitsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha2.FluentBitList{}) + return err +} + +// Patch applies the patch and returns the patched fluentBit. +func (c *FakeFluentBits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(fluentbitsResource, c.ns, name, pt, data, subresources...), &v1alpha2.FluentBit{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha2.FluentBit), err +} diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_logging_client.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_logging_client.go new file mode 100644 index 000000000..f627a40f0 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake/fake_logging_client.go @@ -0,0 +1,40 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2" +) + +type FakeLoggingV1alpha2 struct { + *testing.Fake +} + +func (c *FakeLoggingV1alpha2) FluentBits(namespace string) v1alpha2.FluentBitInterface { + return &FakeFluentBits{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeLoggingV1alpha2) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/fluentbit.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fluentbit.go new file mode 100644 index 000000000..8bd3743c2 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/fluentbit.go @@ -0,0 +1,191 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" + scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +// FluentBitsGetter has a method to return a FluentBitInterface. +// A group's client should implement this interface. +type FluentBitsGetter interface { + FluentBits(namespace string) FluentBitInterface +} + +// FluentBitInterface has methods to work with FluentBit resources. +type FluentBitInterface interface { + Create(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error) + Update(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error) + UpdateStatus(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha2.FluentBit, error) + List(opts v1.ListOptions) (*v1alpha2.FluentBitList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error) + FluentBitExpansion +} + +// fluentBits implements FluentBitInterface +type fluentBits struct { + client rest.Interface + ns string +} + +// newFluentBits returns a FluentBits +func newFluentBits(c *LoggingV1alpha2Client, namespace string) *fluentBits { + return &fluentBits{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the fluentBit, and returns the corresponding fluentBit object, and an error if there is any. +func (c *fluentBits) Get(name string, options v1.GetOptions) (result *v1alpha2.FluentBit, err error) { + result = &v1alpha2.FluentBit{} + err = c.client.Get(). + Namespace(c.ns). + Resource("fluentbits"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of FluentBits that match those selectors. +func (c *fluentBits) List(opts v1.ListOptions) (result *v1alpha2.FluentBitList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha2.FluentBitList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("fluentbits"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested fluentBits. +func (c *fluentBits) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("fluentbits"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a fluentBit and creates it. Returns the server's representation of the fluentBit, and an error, if there is any. +func (c *fluentBits) Create(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) { + result = &v1alpha2.FluentBit{} + err = c.client.Post(). + Namespace(c.ns). + Resource("fluentbits"). + Body(fluentBit). + Do(). + Into(result) + return +} + +// Update takes the representation of a fluentBit and updates it. Returns the server's representation of the fluentBit, and an error, if there is any. +func (c *fluentBits) Update(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) { + result = &v1alpha2.FluentBit{} + err = c.client.Put(). + Namespace(c.ns). + Resource("fluentbits"). + Name(fluentBit.Name). + Body(fluentBit). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *fluentBits) UpdateStatus(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) { + result = &v1alpha2.FluentBit{} + err = c.client.Put(). + Namespace(c.ns). + Resource("fluentbits"). + Name(fluentBit.Name). + SubResource("status"). + Body(fluentBit). + Do(). + Into(result) + return +} + +// Delete takes name of the fluentBit and deletes it. Returns an error if one occurs. +func (c *fluentBits) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("fluentbits"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *fluentBits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("fluentbits"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched fluentBit. +func (c *fluentBits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error) { + result = &v1alpha2.FluentBit{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("fluentbits"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/generated_expansion.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/generated_expansion.go new file mode 100644 index 000000000..55947701a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +type FluentBitExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/logging/v1alpha2/logging_client.go b/pkg/client/clientset/versioned/typed/logging/v1alpha2/logging_client.go new file mode 100644 index 000000000..db526dcd1 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/logging/v1alpha2/logging_client.go @@ -0,0 +1,89 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + rest "k8s.io/client-go/rest" + v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme" +) + +type LoggingV1alpha2Interface interface { + RESTClient() rest.Interface + FluentBitsGetter +} + +// LoggingV1alpha2Client is used to interact with features provided by the logging.kubesphere.io group. +type LoggingV1alpha2Client struct { + restClient rest.Interface +} + +func (c *LoggingV1alpha2Client) FluentBits(namespace string) FluentBitInterface { + return newFluentBits(c, namespace) +} + +// NewForConfig creates a new LoggingV1alpha2Client for the given config. +func NewForConfig(c *rest.Config) (*LoggingV1alpha2Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &LoggingV1alpha2Client{client}, nil +} + +// NewForConfigOrDie creates a new LoggingV1alpha2Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *LoggingV1alpha2Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new LoggingV1alpha2Client for the given RESTClient. +func New(c rest.Interface) *LoggingV1alpha2Client { + return &LoggingV1alpha2Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha2.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *LoggingV1alpha2Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 8134dd6ef..30cabc2c4 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -30,6 +30,7 @@ import ( versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" devops "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops" internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + logging "kubesphere.io/kubesphere/pkg/client/informers/externalversions/logging" network "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network" servicemesh "kubesphere.io/kubesphere/pkg/client/informers/externalversions/servicemesh" tenant "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant" @@ -176,6 +177,7 @@ type SharedInformerFactory interface { WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool Devops() devops.Interface + Logging() logging.Interface Network() network.Interface Servicemesh() servicemesh.Interface Tenant() tenant.Interface @@ -185,6 +187,10 @@ func (f *sharedInformerFactory) Devops() devops.Interface { return devops.New(f, f.namespace, f.tweakListOptions) } +func (f *sharedInformerFactory) Logging() logging.Interface { + return logging.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Network() network.Interface { return network.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 47f806269..b1e7ce43b 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -24,8 +24,9 @@ import ( schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" + v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" - v1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" + servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" ) @@ -59,6 +60,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case v1alpha1.SchemeGroupVersion.WithResource("s2ibinaries"): return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBinaries().Informer()}, nil + // Group=logging.kubesphere.io, Version=v1alpha2 + case v1alpha2.SchemeGroupVersion.WithResource("fluentbits"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Logging().V1alpha2().FluentBits().Informer()}, nil + // Group=network.kubesphere.io, Version=v1alpha1 case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().NamespaceNetworkPolicies().Informer()}, nil @@ -66,9 +71,9 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().WorkspaceNetworkPolicies().Informer()}, nil // Group=servicemesh.kubesphere.io, Version=v1alpha2 - case v1alpha2.SchemeGroupVersion.WithResource("servicepolicies"): + case servicemeshv1alpha2.SchemeGroupVersion.WithResource("servicepolicies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().ServicePolicies().Informer()}, nil - case v1alpha2.SchemeGroupVersion.WithResource("strategies"): + case servicemeshv1alpha2.SchemeGroupVersion.WithResource("strategies"): return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().Strategies().Informer()}, nil // Group=tenant.kubesphere.io, Version=v1alpha1 diff --git a/pkg/client/informers/externalversions/logging/interface.go b/pkg/client/informers/externalversions/logging/interface.go new file mode 100644 index 000000000..e170ad4c8 --- /dev/null +++ b/pkg/client/informers/externalversions/logging/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package logging + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha2 "kubesphere.io/kubesphere/pkg/client/informers/externalversions/logging/v1alpha2" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha2 provides access to shared informers for resources in V1alpha2. + V1alpha2() v1alpha2.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha2 returns a new v1alpha2.Interface. +func (g *group) V1alpha2() v1alpha2.Interface { + return v1alpha2.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/logging/v1alpha2/fluentbit.go b/pkg/client/informers/externalversions/logging/v1alpha2/fluentbit.go new file mode 100644 index 000000000..75bba343e --- /dev/null +++ b/pkg/client/informers/externalversions/logging/v1alpha2/fluentbit.go @@ -0,0 +1,89 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" + versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" + v1alpha2 "kubesphere.io/kubesphere/pkg/client/listers/logging/v1alpha2" +) + +// FluentBitInformer provides access to a shared informer and lister for +// FluentBits. +type FluentBitInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha2.FluentBitLister +} + +type fluentBitInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewFluentBitInformer constructs a new informer for FluentBit type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFluentBitInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredFluentBitInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredFluentBitInformer constructs a new informer for FluentBit type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredFluentBitInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.LoggingV1alpha2().FluentBits(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.LoggingV1alpha2().FluentBits(namespace).Watch(options) + }, + }, + &loggingv1alpha2.FluentBit{}, + resyncPeriod, + indexers, + ) +} + +func (f *fluentBitInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredFluentBitInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *fluentBitInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&loggingv1alpha2.FluentBit{}, f.defaultInformer) +} + +func (f *fluentBitInformer) Lister() v1alpha2.FluentBitLister { + return v1alpha2.NewFluentBitLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/logging/v1alpha2/interface.go b/pkg/client/informers/externalversions/logging/v1alpha2/interface.go new file mode 100644 index 000000000..b298e36b4 --- /dev/null +++ b/pkg/client/informers/externalversions/logging/v1alpha2/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // FluentBits returns a FluentBitInformer. + FluentBits() FluentBitInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// FluentBits returns a FluentBitInformer. +func (v *version) FluentBits() FluentBitInformer { + return &fluentBitInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/listers/logging/v1alpha2/expansion_generated.go b/pkg/client/listers/logging/v1alpha2/expansion_generated.go new file mode 100644 index 000000000..984170034 --- /dev/null +++ b/pkg/client/listers/logging/v1alpha2/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha2 + +// FluentBitListerExpansion allows custom methods to be added to +// FluentBitLister. +type FluentBitListerExpansion interface{} + +// FluentBitNamespaceListerExpansion allows custom methods to be added to +// FluentBitNamespaceLister. +type FluentBitNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/logging/v1alpha2/fluentbit.go b/pkg/client/listers/logging/v1alpha2/fluentbit.go new file mode 100644 index 000000000..adabfafac --- /dev/null +++ b/pkg/client/listers/logging/v1alpha2/fluentbit.go @@ -0,0 +1,94 @@ +/* +Copyright 2019 The KubeSphere authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2" +) + +// FluentBitLister helps list FluentBits. +type FluentBitLister interface { + // List lists all FluentBits in the indexer. + List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) + // FluentBits returns an object that can list and get FluentBits. + FluentBits(namespace string) FluentBitNamespaceLister + FluentBitListerExpansion +} + +// fluentBitLister implements the FluentBitLister interface. +type fluentBitLister struct { + indexer cache.Indexer +} + +// NewFluentBitLister returns a new FluentBitLister. +func NewFluentBitLister(indexer cache.Indexer) FluentBitLister { + return &fluentBitLister{indexer: indexer} +} + +// List lists all FluentBits in the indexer. +func (s *fluentBitLister) List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.FluentBit)) + }) + return ret, err +} + +// FluentBits returns an object that can list and get FluentBits. +func (s *fluentBitLister) FluentBits(namespace string) FluentBitNamespaceLister { + return fluentBitNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// FluentBitNamespaceLister helps list and get FluentBits. +type FluentBitNamespaceLister interface { + // List lists all FluentBits in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) + // Get retrieves the FluentBit from the indexer for a given namespace and name. + Get(name string) (*v1alpha2.FluentBit, error) + FluentBitNamespaceListerExpansion +} + +// fluentBitNamespaceLister implements the FluentBitNamespaceLister +// interface. +type fluentBitNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all FluentBits in the indexer for a given namespace. +func (s fluentBitNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha2.FluentBit)) + }) + return ret, err +} + +// Get retrieves the FluentBit from the indexer for a given namespace and name. +func (s fluentBitNamespaceLister) Get(name string) (*v1alpha2.FluentBit, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha2.Resource("fluentbit"), name) + } + return obj.(*v1alpha2.FluentBit), nil +} diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index a3a4482d3..70d5bc1ba 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -31,8 +31,6 @@ const ( PorterNamespace = "porter-system" IngressControllerNamespace = KubeSphereControlNamespace AdminUserName = "admin" - DataHome = "/etc/kubesphere" - IngressControllerFolder = DataHome + "/ingress-controller" IngressControllerPrefix = "kubesphere-router-" WorkspaceLabelKey = "kubesphere.io/workspace" diff --git a/pkg/controller/namespace/namespace_controller.go b/pkg/controller/namespace/namespace_controller.go index 0f23c88e8..e7a7020e8 100644 --- a/pkg/controller/namespace/namespace_controller.go +++ b/pkg/controller/namespace/namespace_controller.go @@ -32,7 +32,6 @@ import ( "k8s.io/klog" "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" "kubesphere.io/kubesphere/pkg/constants" - cs "kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil" @@ -101,7 +100,8 @@ var _ reconcile.Reconciler = &ReconcileNamespace{} // ReconcileNamespace reconciles a Namespace object type ReconcileNamespace struct { client.Client - scheme *runtime.Scheme + openpitrixClient *openpitrix.Client + scheme *runtime.Scheme } // Reconcile reads that state of the cluster for a Namespace object and makes changes based on the state read @@ -359,18 +359,9 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace) return nil } - openPitrixClient, err := cs.ClientSets().OpenPitrix() - - if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled { - return nil - } else if err != nil { - klog.Error(fmt.Sprintf("create runtime, namespace: %s, error: %s", namespace.Name, err)) - return err - } - adminKubeConfigName := fmt.Sprintf("kubeconfig-%s", constants.AdminUserName) - runtimeCredentials, err := openPitrixClient.Runtime().DescribeRuntimeCredentials(openpitrix.SystemContext(), &pb.DescribeRuntimeCredentialsRequest{SearchWord: &wrappers.StringValue{Value: adminKubeConfigName}, Limit: 1}) + runtimeCredentials, err := r.openpitrixClient.Runtime().DescribeRuntimeCredentials(openpitrix.SystemContext(), &pb.DescribeRuntimeCredentialsRequest{SearchWord: &wrappers.StringValue{Value: adminKubeConfigName}, Limit: 1}) if err != nil { klog.Error(fmt.Sprintf("create runtime, namespace: %s, error: %s", namespace.Name, err)) @@ -391,7 +382,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace) return err } - resp, err := openPitrixClient.Runtime().CreateRuntimeCredential(openpitrix.SystemContext(), &pb.CreateRuntimeCredentialRequest{ + resp, err := r.openpitrixClient.Runtime().CreateRuntimeCredential(openpitrix.SystemContext(), &pb.CreateRuntimeCredentialRequest{ Name: &wrappers.StringValue{Value: adminKubeConfigName}, Provider: &wrappers.StringValue{Value: "kubernetes"}, Description: &wrappers.StringValue{Value: "kubeconfig"}, @@ -408,7 +399,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace) } // TODO runtime id is invalid when recreate runtime - runtimeId, err := openPitrixClient.Runtime().CreateRuntime(openpitrix.SystemContext(), &pb.CreateRuntimeRequest{ + runtimeId, err := r.openpitrixClient.Runtime().CreateRuntime(openpitrix.SystemContext(), &pb.CreateRuntimeRequest{ Name: &wrappers.StringValue{Value: namespace.Name}, RuntimeCredentialId: &wrappers.StringValue{Value: kubesphereRuntimeCredentialId}, Provider: &wrappers.StringValue{Value: openpitrix.KubernetesProvider}, @@ -429,17 +420,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace) func (r *ReconcileNamespace) deleteRuntime(namespace *corev1.Namespace) error { if runtimeId := namespace.Annotations[constants.OpenPitrixRuntimeAnnotationKey]; runtimeId != "" { - - openPitrixClient, err := cs.ClientSets().OpenPitrix() - - if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled { - return nil - } else if err != nil { - klog.Errorf("delete openpitrix runtime: %s, error: %s", runtimeId, err) - return err - } - - _, err = openPitrixClient.Runtime().DeleteRuntimes(openpitrix.SystemContext(), &pb.DeleteRuntimesRequest{RuntimeId: []string{runtimeId}, Force: &wrappers.BoolValue{Value: true}}) + _, err := r.openpitrixClient.Runtime().DeleteRuntimes(openpitrix.SystemContext(), &pb.DeleteRuntimesRequest{RuntimeId: []string{runtimeId}, Force: &wrappers.BoolValue{Value: true}}) if err == nil || openpitrix.IsNotFound(err) || openpitrix.IsDeleted(err) { return nil diff --git a/pkg/controller/s2ibinary/s2ibinary_controller.go b/pkg/controller/s2ibinary/s2ibinary_controller.go index ea2f10a3f..d0bd4e7df 100644 --- a/pkg/controller/s2ibinary/s2ibinary_controller.go +++ b/pkg/controller/s2ibinary/s2ibinary_controller.go @@ -2,9 +2,6 @@ package s2ibinary import ( "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/s3" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -16,7 +13,7 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/simple/client" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "time" @@ -39,6 +36,8 @@ type S2iBinaryController struct { workqueue workqueue.RateLimitingInterface workerLoopPeriod time.Duration + + s3Client s3.Interface } func NewController(devopsclientset devopsclient.Interface, @@ -205,29 +204,12 @@ func (c *S2iBinaryController) syncHandler(key string) error { } func (c *S2iBinaryController) deleteBinaryInS3(s2ibin *devopsv1alpha1.S2iBinary) error { - s3Client, err := client.ClientSets().S3() + + key := fmt.Sprintf("%s-%s", s2ibin.Namespace, s2ibin.Name) + err := c.s3Client.Delete(key) if err != nil { - return err + klog.Errorf("error happened while deleting %s, %v", key, err) } - input := &s3.DeleteObjectInput{ - Bucket: s3Client.Bucket(), - Key: aws.String(fmt.Sprintf("%s-%s", s2ibin.Namespace, s2ibin.Name)), - } - _, err = s3Client.Client().DeleteObject(input) - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchKey: - return nil - default: - klog.Error(err, fmt.Sprintf("failed to delete s2ibin %s/%s in s3", s2ibin.Namespace, s2ibin.Name)) - return err - } - } else { - klog.Error(err, fmt.Sprintf("failed to delete s2ibin %s/%s in s3", s2ibin.Namespace, s2ibin.Name)) - return err - } - } return nil } diff --git a/pkg/controller/workspace/workspace_controller.go b/pkg/controller/workspace/workspace_controller.go index 620197c38..1a9ac92af 100644 --- a/pkg/controller/workspace/workspace_controller.go +++ b/pkg/controller/workspace/workspace_controller.go @@ -324,15 +324,6 @@ func (r *ReconcileWorkspace) deleteGroup(instance *tenantv1alpha1.Workspace) err } func (r *ReconcileWorkspace) deleteDevOpsProjects(instance *tenantv1alpha1.Workspace) error { - if _, err := cs.ClientSets().Devops(); err != nil { - // skip if devops is not enabled - if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled { - return nil - } else { - log.Error(err, "") - return err - } - } var wg sync.WaitGroup log.Info("Delete DevOps Projects") diff --git a/pkg/informers/informers.go b/pkg/informers/informers.go index f8db835b1..9df473daf 100644 --- a/pkg/informers/informers.go +++ b/pkg/informers/informers.go @@ -18,56 +18,67 @@ package informers import ( + applicationclient "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned" applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions" + s2i "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned" s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions" k8sinformers "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" - "kubesphere.io/kubesphere/pkg/simple/client" - "sync" "time" ) const defaultResync = 600 * time.Second -var ( - k8sOnce sync.Once - s2iOnce sync.Once - ksOnce sync.Once - appOnce sync.Once +type InformerFactory interface { + KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory + S2iSharedInformerFactory() s2iinformers.SharedInformerFactory + KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory + ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory +} + +type informerFactories struct { informerFactory k8sinformers.SharedInformerFactory s2iInformerFactory s2iinformers.SharedInformerFactory ksInformerFactory ksinformers.SharedInformerFactory appInformerFactory applicationinformers.SharedInformerFactory -) - -func SharedInformerFactory() k8sinformers.SharedInformerFactory { - k8sOnce.Do(func() { - k8sClient := client.ClientSets().K8s().Kubernetes() - informerFactory = k8sinformers.NewSharedInformerFactory(k8sClient, defaultResync) - }) - return informerFactory } -func S2iSharedInformerFactory() s2iinformers.SharedInformerFactory { - s2iOnce.Do(func() { - k8sClient := client.ClientSets().K8s().S2i() - s2iInformerFactory = s2iinformers.NewSharedInformerFactory(k8sClient, defaultResync) - }) - return s2iInformerFactory +func NewInformerFactories(client kubernetes.Interface, ksClient versioned.Interface, s2iClient s2i.Interface, appClient applicationclient.Interface) InformerFactory { + factory := &informerFactories{} + + if client != nil { + factory.informerFactory = k8sinformers.NewSharedInformerFactory(client, defaultResync) + } + + if ksClient != nil { + factory.ksInformerFactory = ksinformers.NewSharedInformerFactory(ksClient, defaultResync) + } + + if s2iClient != nil { + factory.s2iInformerFactory = s2iinformers.NewSharedInformerFactory(s2iClient, defaultResync) + } + + if appClient != nil { + factory.appInformerFactory = applicationinformers.NewSharedInformerFactory(appClient, defaultResync) + } + + return factory } -func KsSharedInformerFactory() ksinformers.SharedInformerFactory { - ksOnce.Do(func() { - k8sClient := client.ClientSets().K8s().KubeSphere() - ksInformerFactory = ksinformers.NewSharedInformerFactory(k8sClient, defaultResync) - }) - return ksInformerFactory +func (f *informerFactories) KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory { + return f.informerFactory } -func AppSharedInformerFactory() applicationinformers.SharedInformerFactory { - appOnce.Do(func() { - appClient := client.ClientSets().K8s().Application() - appInformerFactory = applicationinformers.NewSharedInformerFactory(appClient, defaultResync) - }) - return appInformerFactory +func (f *informerFactories) S2iSharedInformerFactory() s2iinformers.SharedInformerFactory { + return f.s2iInformerFactory +} + +func (f *informerFactories) KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory { + return f.ksInformerFactory +} + +func (f *informerFactories) ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory { + return f.appInformerFactory } diff --git a/pkg/kapis/kapis.go b/pkg/kapis/kapis.go index 1e8d81ca5..8a36366cd 100644 --- a/pkg/kapis/kapis.go +++ b/pkg/kapis/kapis.go @@ -13,16 +13,17 @@ import ( servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2" tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2" terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" ) -func InstallAPIs(container *restful.Container) { +func InstallAPIs(container *restful.Container, client k8s.Client) { urlruntime.Must(servicemeshv1alpha2.AddToContainer(container)) urlruntime.Must(devopsv1alpha2.AddToContainer(container)) urlruntime.Must(loggingv1alpha2.AddToContainer(container)) urlruntime.Must(monitoringv1alpha2.AddToContainer(container)) urlruntime.Must(openpitrixv1.AddToContainer(container)) - urlruntime.Must(operationsv1alpha2.AddToContainer(container)) - urlruntime.Must(resourcesv1alpha2.AddToContainer(container)) + urlruntime.Must(operationsv1alpha2.AddToContainer(container, client)) + urlruntime.Must(resourcesv1alpha2.AddToContainer(container, client)) urlruntime.Must(tenantv1alpha2.AddToContainer(container)) urlruntime.Must(terminalv1alpha2.AddToContainer(container)) } diff --git a/pkg/kapis/logging/v1alpha2/register.go b/pkg/kapis/logging/v1alpha2/register.go index fa4b59d84..63aa5ba4a 100644 --- a/pkg/kapis/logging/v1alpha2/register.go +++ b/pkg/kapis/logging/v1alpha2/register.go @@ -26,7 +26,6 @@ import ( "kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models/log" - fluentbitclient "kubesphere.io/kubesphere/pkg/simple/client/fluentbit" "net/http" ) diff --git a/pkg/kapis/openpitrix/v1/handler.go b/pkg/kapis/openpitrix/v1/handler.go new file mode 100644 index 000000000..13b38ab48 --- /dev/null +++ b/pkg/kapis/openpitrix/v1/handler.go @@ -0,0 +1,14 @@ +package v1 + +import "github.com/emicklei/go-restful" + +type openpitrixHandler struct { +} + +func newOpenpitrixHandler() *openpitrixHandler { + return &openpitrixHandler{} +} + +func (h *openpitrixHandler) handleListApplications(request *restful.Request, response *restful.Response) { + +} diff --git a/pkg/kapis/operations/install/install.go b/pkg/kapis/operations/install/install.go index ca8bcfde4..c2091aa5b 100644 --- a/pkg/kapis/operations/install/install.go +++ b/pkg/kapis/operations/install/install.go @@ -29,5 +29,5 @@ func init() { } func Install(container *restful.Container) { - urlruntime.Must(v1alpha2.AddToContainer(container)) + urlruntime.Must(v1alpha2.AddToContainer(container, nil)) } diff --git a/pkg/kapis/operations/v1alpha2/handler.go b/pkg/kapis/operations/v1alpha2/handler.go new file mode 100644 index 000000000..59d362538 --- /dev/null +++ b/pkg/kapis/operations/v1alpha2/handler.go @@ -0,0 +1,48 @@ +package v1alpha2 + +import ( + "fmt" + "github.com/emicklei/go-restful" + k8serr "k8s.io/apimachinery/pkg/api/errors" + "kubesphere.io/kubesphere/pkg/models/workloads" + "kubesphere.io/kubesphere/pkg/server/errors" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "net/http" +) + +type operationHandler struct { + jobRunner workloads.JobRunner +} + +func newOperationHandler(client k8s.Client) *operationHandler { + return &operationHandler{ + jobRunner: workloads.NewJobRunner(client.Kubernetes()), + } +} + +func (r *operationHandler) handleJobReRun(request *restful.Request, response *restful.Response) { + var err error + + job := request.PathParameter("job") + namespace := request.PathParameter("namespace") + action := request.QueryParameter("action") + resourceVersion := request.QueryParameter("resourceVersion") + + switch action { + case "rerun": + err = r.jobRunner.JobReRun(namespace, job, resourceVersion) + default: + response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("invalid operation %s", action))) + return + } + if err != nil { + if k8serr.IsConflict(err) { + response.WriteHeaderAndEntity(http.StatusConflict, errors.Wrap(err)) + return + } + response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) + return + } + + response.WriteAsJson(errors.None) +} diff --git a/pkg/kapis/operations/v1alpha2/register.go b/pkg/kapis/operations/v1alpha2/register.go index c4240d908..fdcbc4b4b 100644 --- a/pkg/kapis/operations/v1alpha2/register.go +++ b/pkg/kapis/operations/v1alpha2/register.go @@ -20,9 +20,9 @@ package v1alpha2 import ( "github.com/emicklei/go-restful" "k8s.io/apimachinery/pkg/runtime/schema" - "kubesphere.io/kubesphere/pkg/apiserver/operations" "kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/server/errors" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" "net/http" ) @@ -30,25 +30,15 @@ const GroupName = "operations.kubesphere.io" var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} -var ( - WebServiceBuilder = runtime.NewContainerBuilder(addWebService) - AddToContainer = WebServiceBuilder.AddToContainer -) - -func addWebService(c *restful.Container) error { +func AddToContainer(c *restful.Container, client k8s.Client) error { ok := "ok" webservice := runtime.NewWebService(GroupVersion) - webservice.Route(webservice.POST("/nodes/{node}/drainage"). - To(operations.DrainNode). - Deprecate(). - Doc("remove a node from service, safely evict all of your pods from a node and you can power down the node. More info: https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"). - Param(webservice.PathParameter("node", "node name")). - Returns(http.StatusOK, ok, errors.Error{})) + handler := newOperationHandler(client) webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}"). - To(operations.RerunJob). + To(handler.handleJobReRun). Doc("Rerun job whether the job is complete or not"). Deprecate(). Param(webservice.PathParameter("job", "job name")). diff --git a/pkg/kapis/resources/install/install.go b/pkg/kapis/resources/install/install.go deleted file mode 100644 index 85400efb9..000000000 --- a/pkg/kapis/resources/install/install.go +++ /dev/null @@ -1,33 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package install - -import ( - "github.com/emicklei/go-restful" - urlruntime "k8s.io/apimachinery/pkg/util/runtime" - "kubesphere.io/kubesphere/pkg/apiserver/runtime" - "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2" -) - -func init() { - Install(runtime.Container) -} - -func Install(c *restful.Container) { - urlruntime.Must(v1alpha2.AddToContainer(c)) -} diff --git a/pkg/kapis/resources/v1alpha2/handler.go b/pkg/kapis/resources/v1alpha2/handler.go new file mode 100644 index 000000000..c8ec18080 --- /dev/null +++ b/pkg/kapis/resources/v1alpha2/handler.go @@ -0,0 +1,345 @@ +package v1alpha2 + +import ( + "fmt" + "github.com/emicklei/go-restful" + v1 "k8s.io/api/core/v1" + k8serr "k8s.io/apimachinery/pkg/api/errors" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/components" + "kubesphere.io/kubesphere/pkg/models/git" + "kubesphere.io/kubesphere/pkg/models/quotas" + "kubesphere.io/kubesphere/pkg/models/registries" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource" + "kubesphere.io/kubesphere/pkg/models/revisions" + "kubesphere.io/kubesphere/pkg/models/routers" + "kubesphere.io/kubesphere/pkg/server/errors" + "kubesphere.io/kubesphere/pkg/server/params" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "net/http" + "strconv" + "strings" +) + +type resourceHandler struct { + resourcesGetter *resource.ResourceGetter + componentsGetter components.ComponentsGetter + resourceQuotaGetter quotas.ResourceQuotaGetter + revisionGetter revisions.RevisionGetter + routerOperator routers.RouterOperator + gitVerifier git.GitVerifier + registryGetter registries.RegistryGetter +} + +func newResourceHandler(client k8s.Client) *resourceHandler { + + factory := informers.NewInformerFactories(client.Kubernetes(), client.KubeSphere(), client.S2i(), client.Application()) + + return &resourceHandler{ + resourcesGetter: resource.NewResourceGetter(factory), + componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()), + resourceQuotaGetter: quotas.NewResourceQuotaGetter(factory.KubernetesSharedInformerFactory()), + revisionGetter: revisions.NewRevisionGetter(factory.KubernetesSharedInformerFactory()), + routerOperator: routers.NewRouterOperator(client.Kubernetes(), factory.KubernetesSharedInformerFactory()), + gitVerifier: git.NewGitVerifier(factory.KubernetesSharedInformerFactory()), + registryGetter: registries.NewRegistryGetter(factory.KubernetesSharedInformerFactory()), + } +} + +func (r *resourceHandler) handleGetNamespacedResources(request *restful.Request, response *restful.Response) { + r.handleListNamespaceResources(request, response) +} + +func (r *resourceHandler) handleListNamespaceResources(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + resourceName := request.PathParameter("resources") + conditions, err := params.ParseConditions(request.QueryParameter(params.ConditionsParam)) + orderBy := params.GetStringValueWithDefault(request, params.OrderByParam, v1alpha2.CreateTime) + limit, offset := params.ParsePaging(request.QueryParameter(params.PagingParam)) + reverse := params.ParseReverse(request) + + if err != nil { + response.WriteHeaderAndEntity(http.StatusBadRequest, err) + return + } + + result, err := r.resourcesGetter.ListResources(namespace, resourceName, conditions, orderBy, reverse, limit, offset) + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, response *restful.Response) { + result, err := r.componentsGetter.GetSystemHealthStatus() + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetComponentStatus(request *restful.Request, response *restful.Response) { + component := request.PathParameter("component") + result, err := r.componentsGetter.GetComponentStatus(component) + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetComponents(_ *restful.Request, response *restful.Response) { + result, err := r.componentsGetter.GetAllComponentsStatus() + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetClusterQuotas(_ *restful.Request, response *restful.Response) { + result, err := r.resourceQuotaGetter.GetClusterQuota() + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetNamespaceQuotas(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + quota, err := r.resourceQuotaGetter.GetNamespaceQuota(namespace) + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(quota) +} + +func (r *resourceHandler) handleGetDaemonSetRevision(request *restful.Request, response *restful.Response) { + daemonset := request.PathParameter("daemonset") + namespace := request.PathParameter("namespace") + revision, err := strconv.Atoi(request.PathParameter("revision")) + + if err != nil { + response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) + return + } + + result, err := r.revisionGetter.GetDaemonSetRevision(namespace, daemonset, revision) + + if err != nil { + response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetDeploymentRevision(request *restful.Request, response *restful.Response) { + deploy := request.PathParameter("deployment") + namespace := request.PathParameter("namespace") + revision := request.PathParameter("revision") + + result, err := r.revisionGetter.GetDeploymentRevision(namespace, deploy, revision) + + if err != nil { + response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err)) + return + } + + response.WriteAsJson(result) +} + +func (r *resourceHandler) handleGetStatefulSetRevision(request *restful.Request, response *restful.Response) { + statefulset := request.PathParameter("statefulset") + namespace := request.PathParameter("namespace") + revision, err := strconv.Atoi(request.PathParameter("revision")) + if err != nil { + response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) + return + } + + result, err := r.revisionGetter.GetStatefulSetRevision(namespace, statefulset, revision) + if err != nil { + api.HandleInternalError(response, err) + return + } + response.WriteAsJson(result) +} + +// Get ingress controller service for specified namespace +func (r *resourceHandler) handleGetRouter(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + router, err := r.routerOperator.GetRouter(namespace) + if err != nil { + if k8serr.IsNotFound(err) { + response.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err)) + } else { + api.HandleInternalError(response, err) + } + return + } + + response.WriteAsJson(router) +} + +// Create ingress controller and related services +func (r *resourceHandler) handleCreateRouter(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + newRouter := api.Router{} + err := request.ReadEntity(&newRouter) + if err != nil { + response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("wrong annotations, missing key or value"))) + return + } + + routerType := v1.ServiceTypeNodePort + if strings.Compare(strings.ToLower(newRouter.RouterType), "loadbalancer") == 0 { + routerType = v1.ServiceTypeLoadBalancer + } + + router, err := r.routerOperator.CreateRouter(namespace, routerType, newRouter.Annotations) + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(router) +} + +// Delete ingress controller and services +func (r *resourceHandler) handleDeleteRouter(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + + router, err := r.routerOperator.DeleteRouter(namespace) + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(router) +} + +func (r *resourceHandler) handleUpdateRouter(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + newRouter := api.Router{} + err := request.ReadEntity(&newRouter) + if err != nil { + response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) + return + } + + var routerType = v1.ServiceTypeNodePort + if strings.Compare(strings.ToLower(newRouter.RouterType), "loadbalancer") == 0 { + routerType = v1.ServiceTypeLoadBalancer + } + router, err := r.routerOperator.UpdateRouter(namespace, routerType, newRouter.Annotations) + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteAsJson(router) +} + +func (r *resourceHandler) handleVerifyGitCredential(request *restful.Request, response *restful.Response) { + + var credential api.GitCredential + err := request.ReadEntity(&credential) + if err != nil { + api.HandleBadRequest(response, err) + return + } + + err = r.gitVerifier.VerifyGitCredential(credential.RemoteUrl, credential.SecretRef.Namespace, credential.SecretRef.Name) + if err != nil { + api.HandleBadRequest(response, err) + return + } + + response.WriteHeader(http.StatusOK) +} + +func (r *resourceHandler) handleVerifyRegistryCredential(request *restful.Request, response *restful.Response) { + var credential api.RegistryCredential + err := request.ReadEntity(&credential) + if err != nil { + api.HandleBadRequest(response, err) + return + } + + err = r.registryGetter.VerifyRegistryCredential(credential) + if err != nil { + api.HandleBadRequest(response, err) + return + } + + response.WriteHeader(http.StatusOK) +} + +func (r *resourceHandler) handleGetRegistryEntry(request *restful.Request, response *restful.Response) { + imageName := request.QueryParameter("image") + namespace := request.QueryParameter("namespace") + secretName := request.QueryParameter("secret") + + detail, err := r.registryGetter.GetEntry(namespace, secretName, imageName) + if err != nil { + api.HandleBadRequest(response, err) + return + } + + response.WriteAsJson(detail) +} + +func (r *resourceHandler) handleGetNamespacedAbnormalWorkloads(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + + result := api.Workloads{ + Namespace: namespace, + Count: make(map[string]int), + } + + for _, workloadType := range []string{api.ResourceKindDeployment, api.ResourceKindStatefulSet, api.ResourceKindDaemonSet, api.ResourceKindJob, api.ResourceKindPersistentVolumeClaim} { + var notReadyStatus string + + switch workloadType { + case api.ResourceKindPersistentVolumeClaim: + notReadyStatus = strings.Join([]string{v1alpha2.StatusPending, v1alpha2.StatusLost}, "|") + case api.ResourceKindJob: + notReadyStatus = v1alpha2.StatusFailed + default: + notReadyStatus = v1alpha2.StatusUpdating + } + + res, err := r.resourcesGetter.ListResources(namespace, workloadType, ¶ms.Conditions{Match: map[string]string{v1alpha2.Status: notReadyStatus}}, "", false, -1, 0) + if err != nil { + api.HandleInternalError(response, err) + } + + result.Count[workloadType] = len(res.Items) + } + + response.WriteAsJson(result) + +} + +func (r *resourceHandler) handleGetAbnormalWorkloads(request *restful.Request, response *restful.Response) { + r.handleGetNamespacedAbnormalWorkloads(request, response) +} diff --git a/pkg/kapis/resources/v1alpha2/register.go b/pkg/kapis/resources/v1alpha2/register.go index 5568aa02a..30ea37fa9 100644 --- a/pkg/kapis/resources/v1alpha2/register.go +++ b/pkg/kapis/resources/v1alpha2/register.go @@ -23,43 +23,32 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "kubesphere.io/kubesphere/pkg/apiserver/components" - "kubesphere.io/kubesphere/pkg/apiserver/git" - "kubesphere.io/kubesphere/pkg/apiserver/operations" - "kubesphere.io/kubesphere/pkg/apiserver/quotas" - "kubesphere.io/kubesphere/pkg/apiserver/registries" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/api/resource/v1alpha2" "kubesphere.io/kubesphere/pkg/apiserver/resources" - "kubesphere.io/kubesphere/pkg/apiserver/revisions" - "kubesphere.io/kubesphere/pkg/apiserver/routers" "kubesphere.io/kubesphere/pkg/apiserver/runtime" - "kubesphere.io/kubesphere/pkg/apiserver/workloadstatuses" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models" gitmodel "kubesphere.io/kubesphere/pkg/models/git" registriesmodel "kubesphere.io/kubesphere/pkg/models/registries" - "kubesphere.io/kubesphere/pkg/models/status" "kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/params" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" "net/http" ) -const GroupName = "resources.kubesphere.io" +const ( + GroupName = "resources.kubesphere.io" +) var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} -var ( - WebServiceBuilder = runtime.NewContainerBuilder(addWebService) - AddToContainer = WebServiceBuilder.AddToContainer -) - -func addWebService(c *restful.Container) error { - +func AddToContainer(c *restful.Container, client k8s.Client) error { webservice := runtime.NewWebService(GroupVersion) - - ok := "ok" + handler := newResourceHandler(client) webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}"). - To(resources.ListNamespacedResources). + To(handler.handleListNamespaceResources). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Doc("Namespace level resource query"). Param(webservice.PathParameter("namespace", "the name of the project")). @@ -73,21 +62,11 @@ func addWebService(c *restful.Container) error { DefaultValue("limit=10,page=1")). Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")). Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime")). - Returns(http.StatusOK, ok, models.PageableResponse{})) - - webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}"). - To(operations.RerunJob). - Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Doc("Rerun job whether the job is complete or not"). - Param(webservice.PathParameter("job", "job name")). - Param(webservice.PathParameter("namespace", "the name of the namespace where the job runs in")). - Param(webservice.QueryParameter("action", "action must be \"rerun\"")). - Param(webservice.QueryParameter("resourceVersion", "version of job, rerun when the version matches")). - Returns(http.StatusOK, ok, errors.Error{})) + Returns(http.StatusOK, api.StatusOK, models.PageableResponse{})) webservice.Route(webservice.GET("/{resources}"). - To(resources.ListResources). - Returns(http.StatusOK, ok, models.PageableResponse{}). + To(handler.handleListNamespaceResources). + Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). Doc("Cluster level resource query"). Param(webservice.PathParameter("resources", "cluster level resource type, e.g. nodes,workspaces,storageclasses,clusterroles.")). @@ -102,67 +81,60 @@ func addWebService(c *restful.Container) error { Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")). Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime"))) - webservice.Route(webservice.POST("/nodes/{node}/drainage"). - To(operations.DrainNode). - Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). - Doc("remove a node from service, safely evict all of your pods from a node and you can power down the node. More info: https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"). - Param(webservice.PathParameter("node", "node name")). - Returns(http.StatusOK, ok, errors.Error{})) - webservice.Route(webservice.GET("/users/{user}/kubectl"). To(resources.GetKubectl). Doc("get user's kubectl pod"). Param(webservice.PathParameter("user", "username")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag}). - Returns(http.StatusOK, ok, models.PodInfo{})) + Returns(http.StatusOK, api.StatusOK, models.PodInfo{})) webservice.Route(webservice.GET("/users/{user}/kubeconfig"). Produces("text/plain", restful.MIME_JSON). To(resources.GetKubeconfig). Doc("get users' kubeconfig"). Param(webservice.PathParameter("user", "username")). - Returns(http.StatusOK, ok, ""). + Returns(http.StatusOK, api.StatusOK, ""). Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag})) webservice.Route(webservice.GET("/components"). - To(components.GetComponents). + To(handler.handleGetComponents). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Doc("List the system components."). - Returns(http.StatusOK, ok, []models.ComponentStatus{})) + Returns(http.StatusOK, api.StatusOK, []v1alpha2.ComponentStatus{})) + webservice.Route(webservice.GET("/components/{component}"). - To(components.GetComponentStatus). + To(handler.handleGetComponentStatus). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Doc("Describe the specified system component."). Param(webservice.PathParameter("component", "component name")). - Returns(http.StatusOK, ok, models.ComponentStatus{})) + Returns(http.StatusOK, api.StatusOK, v1alpha2.ComponentStatus{})) webservice.Route(webservice.GET("/componenthealth"). - To(components.GetSystemHealthStatus). + To(handler.handleGetSystemHealthStatus). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Doc("Get the health status of system components."). - Returns(http.StatusOK, ok, models.HealthStatus{})) + Returns(http.StatusOK, api.StatusOK, v1alpha2.HealthStatus{})) webservice.Route(webservice.GET("/quotas"). - To(quotas.GetClusterQuotas). + To(handler.handleGetClusterQuotas). Doc("get whole cluster's resource usage"). - Returns(http.StatusOK, ok, models.ResourceQuota{}). + Returns(http.StatusOK, api.StatusOK, api.ResourceQuota{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag})) webservice.Route(webservice.GET("/namespaces/{namespace}/quotas"). Doc("get specified namespace's resource quota and usage"). Param(webservice.PathParameter("namespace", "the name of the project")). - Returns(http.StatusOK, ok, models.ResourceQuota{}). + Returns(http.StatusOK, api.StatusOK, api.ResourceQuota{}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - To(quotas.GetNamespaceQuotas)) + To(handler.handleGetNamespaceQuotas)) webservice.Route(webservice.POST("registry/verify"). - To(registries.RegistryVerify). + To(handler.handleVerifyRegistryCredential). Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}). Doc("verify if a user has access to the docker registry"). - Reads(registriesmodel.AuthInfo{}). - Returns(http.StatusOK, ok, errors.Error{})) - + Reads(api.RegistryCredential{}). + Returns(http.StatusOK, api.StatusOK, errors.Error{})) webservice.Route(webservice.GET("/registry/blob"). - To(registries.RegistryImageBlob). + To(handler.handleGetRegistryEntry). Param(webservice.QueryParameter("image", "query image, condition for filtering."). Required(true). DataFormat("image=%s")). @@ -175,87 +147,80 @@ func addWebService(c *restful.Container) error { Metadata(restfulspec.KeyOpenAPITags, []string{constants.RegistryTag}). Doc("Retrieve the blob from the registry identified"). Writes(registriesmodel.ImageDetails{}). - Returns(http.StatusOK, ok, registriesmodel.ImageDetails{}), + Returns(http.StatusOK, api.StatusOK, registriesmodel.ImageDetails{}), ) - webservice.Route(webservice.POST("git/verify"). - To(git.GitReadVerify). + To(handler.handleVerifyGitCredential). Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}). Doc("Verify if the kubernetes secret has read access to the git repository"). Reads(gitmodel.AuthInfo{}). - Returns(http.StatusOK, ok, errors.Error{}), + Returns(http.StatusOK, api.StatusOK, errors.Error{}), ) webservice.Route(webservice.GET("/namespaces/{namespace}/daemonsets/{daemonset}/revisions/{revision}"). - To(revisions.GetDaemonSetRevision). + To(handler.handleGetDaemonSetRevision). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Doc("Get the specified daemonset revision"). Param(webservice.PathParameter("daemonset", "the name of the daemonset")). Param(webservice.PathParameter("namespace", "the namespace of the daemonset")). Param(webservice.PathParameter("revision", "the revision of the daemonset")). - Returns(http.StatusOK, ok, appsv1.DaemonSet{})) + Returns(http.StatusOK, api.StatusOK, appsv1.DaemonSet{})) webservice.Route(webservice.GET("/namespaces/{namespace}/deployments/{deployment}/revisions/{revision}"). - To(revisions.GetDeployRevision). + To(handler.handleGetDeploymentRevision). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Doc("Get the specified deployment revision"). Param(webservice.PathParameter("deployment", "the name of deployment")). Param(webservice.PathParameter("namespace", "the namespace of the deployment")). Param(webservice.PathParameter("revision", "the revision of the deployment")). - Returns(http.StatusOK, ok, appsv1.ReplicaSet{})) + Returns(http.StatusOK, api.StatusOK, appsv1.ReplicaSet{})) webservice.Route(webservice.GET("/namespaces/{namespace}/statefulsets/{statefulset}/revisions/{revision}"). - To(revisions.GetStatefulSetRevision). + To(handler.handleGetStatefulSetRevision). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Doc("Get the specified statefulset revision"). Param(webservice.PathParameter("statefulset", "the name of the statefulset")). Param(webservice.PathParameter("namespace", "the namespace of the statefulset")). Param(webservice.PathParameter("revision", "the revision of the statefulset")). - Returns(http.StatusOK, ok, appsv1.StatefulSet{})) - - webservice.Route(webservice.GET("/routers"). - To(routers.GetAllRouters). - Doc("List all routers of all projects"). - Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). - Returns(http.StatusOK, ok, corev1.ServiceList{})) + Returns(http.StatusOK, api.StatusOK, appsv1.StatefulSet{})) webservice.Route(webservice.GET("/namespaces/{namespace}/router"). - To(routers.GetRouter). + To(handler.handleGetRouter). Doc("List router of a specified project"). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Returns(http.StatusOK, ok, corev1.Service{}). + Returns(http.StatusOK, api.StatusOK, corev1.Service{}). Param(webservice.PathParameter("namespace", "the name of the project"))) webservice.Route(webservice.DELETE("/namespaces/{namespace}/router"). - To(routers.DeleteRouter). + To(handler.handleDeleteRouter). Doc("List router of a specified project"). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Returns(http.StatusOK, ok, corev1.Service{}). + Returns(http.StatusOK, api.StatusOK, corev1.Service{}). Param(webservice.PathParameter("namespace", "the name of the project"))) webservice.Route(webservice.POST("/namespaces/{namespace}/router"). - To(routers.CreateRouter). + To(handler.handleCreateRouter). Doc("Create a router for a specified project"). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Returns(http.StatusOK, ok, corev1.Service{}). + Returns(http.StatusOK, api.StatusOK, corev1.Service{}). Param(webservice.PathParameter("namespace", "the name of the project"))) webservice.Route(webservice.PUT("/namespaces/{namespace}/router"). - To(routers.UpdateRouter). + To(handler.handleUpdateRouter). Doc("Update a router for a specified project"). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Returns(http.StatusOK, ok, corev1.Service{}). + Returns(http.StatusOK, api.StatusOK, corev1.Service{}). Param(webservice.PathParameter("namespace", "the name of the project"))) webservice.Route(webservice.GET("/abnormalworkloads"). Doc("get abnormal workloads' count of whole cluster"). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). - Returns(http.StatusOK, ok, status.WorkLoadStatus{}). - To(workloadstatuses.GetClusterAbnormalWorkloads)) + Returns(http.StatusOK, api.StatusOK, api.Workloads{}). + To(handler.handleGetAbnormalWorkloads)) webservice.Route(webservice.GET("/namespaces/{namespace}/abnormalworkloads"). Doc("get abnormal workloads' count of specified namespace"). Param(webservice.PathParameter("namespace", "the name of the project")). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). - Returns(http.StatusOK, ok, status.WorkLoadStatus{}). - To(workloadstatuses.GetNamespacedAbnormalWorkloads)) + Returns(http.StatusOK, api.StatusOK, api.Workloads{}). + To(handler.handleGetNamespacedAbnormalWorkloads)) c.Add(webservice) diff --git a/pkg/kapis/resources/v1alpha3/handler.go b/pkg/kapis/resources/v1alpha3/handler.go new file mode 100644 index 000000000..bb815e38c --- /dev/null +++ b/pkg/kapis/resources/v1alpha3/handler.go @@ -0,0 +1,91 @@ +package v1alpha3 + +import ( + "github.com/emicklei/go-restful" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/components" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "net/http" +) + +type Handler struct { + namespacedResourceGetter *resource.NamespacedResourceGetter + componentsGetter components.ComponentsGetter +} + +func New(client k8s.Client) *Handler { + factory := informers.NewInformerFactories(client.Kubernetes(), nil, nil, nil) + + return &Handler{ + namespacedResourceGetter: resource.New(factory.KubernetesSharedInformerFactory()), + componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()), + } +} + +func (h Handler) handleGetNamespacedResource(request *restful.Request, response *restful.Response) { + resource := request.PathParameter("resources") + namespace := request.PathParameter("namespace") + name := request.PathParameter("name") + + result, err := h.namespacedResourceGetter.Get(resource, namespace, name) + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +// handleListNamedResource retrieves namespaced scope resources +func (h Handler) handleListNamespacedResource(request *restful.Request, response *restful.Response) { + query := query.ParseQueryParameter(request) + resource := request.PathParameter("resources") + namespace := request.PathParameter("namespace") + + result, err := h.namespacedResourceGetter.List(resource, namespace, query) + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (h Handler) handleGetComponentStatus(request *restful.Request, response *restful.Response) { + component := request.PathParameter("component") + result, err := h.componentsGetter.GetComponentStatus(component) + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +func (h Handler) handleGetSystemHealthStatus(request *restful.Request, response *restful.Response) { + result, err := h.componentsGetter.GetSystemHealthStatus() + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteHeaderAndEntity(http.StatusOK, result) +} + +// get all componentsHandler +func (h Handler) handleGetComponents(request *restful.Request, response *restful.Response) { + + result, err := h.componentsGetter.GetAllComponentsStatus() + + if err != nil { + api.HandleInternalError(response, err) + return + } + + response.WriteHeaderAndEntity(http.StatusOK, result) +} diff --git a/pkg/kapis/resources/v1alpha3/handler_test.go b/pkg/kapis/resources/v1alpha3/handler_test.go new file mode 100644 index 000000000..6ef3f09c5 --- /dev/null +++ b/pkg/kapis/resources/v1alpha3/handler_test.go @@ -0,0 +1,7 @@ +package v1alpha3 + +import "testing" + +func TestComponentHandler(t *testing.T) { + +} diff --git a/pkg/kapis/resources/v1alpha3/register.go b/pkg/kapis/resources/v1alpha3/register.go new file mode 100644 index 000000000..e671692be --- /dev/null +++ b/pkg/kapis/resources/v1alpha3/register.go @@ -0,0 +1,81 @@ +/* + + Copyright 2019 The KubeSphere Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package v1alpha3 + +import ( + "github.com/emicklei/go-restful" + "github.com/emicklei/go-restful-openapi" + "k8s.io/apimachinery/pkg/runtime/schema" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/api/resource/v1alpha2" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/apiserver/runtime" + "kubesphere.io/kubesphere/pkg/simple/client/k8s" + "net/http" +) + +const ( + GroupName = "resources.kubesphere.io" + + tagComponentStatus = "Component Status" + tagNamespacedResource = "Namespaced Resource" + + ok = "OK" +) + +var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} + +func AddWebService(c *restful.Container, client k8s.Client) error { + + webservice := runtime.NewWebService(GroupVersion) + handler := New(client) + + webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}"). + To(handler.handleGetNamespacedResource). + Metadata(restfulspec.KeyOpenAPITags, []string{tagNamespacedResource}). + Doc("Namespace level resource query"). + Param(webservice.PathParameter("namespace", "the name of the project")). + Param(webservice.PathParameter("resources", "namespace level resource type, e.g. pods,jobs,configmaps,services.")). + Param(webservice.QueryParameter(query.ParameterName, "name used to do filtering").Required(false)). + Param(webservice.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=0")). + Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)). + Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")). + Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")). + Returns(http.StatusOK, ok, api.ListResult{})) + + webservice.Route(webservice.GET("/components"). + To(handler.handleGetComponents). + Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}). + Doc("List the system components."). + Returns(http.StatusOK, ok, []v1alpha2.ComponentStatus{})) + webservice.Route(webservice.GET("/components/{component}"). + To(handler.handleGetComponentStatus). + Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}). + Doc("Describe the specified system component."). + Param(webservice.PathParameter("component", "component name")). + Returns(http.StatusOK, ok, v1alpha2.ComponentStatus{})) + webservice.Route(webservice.GET("/componenthealth"). + To(handler.handleGetSystemHealthStatus). + Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}). + Doc("Get the health status of system components."). + Returns(http.StatusOK, ok, v1alpha2.HealthStatus{})) + + c.Add(webservice) + + return nil +} diff --git a/pkg/models/components/components.go b/pkg/models/components/components.go index f24f670c5..bd27a6f20 100644 --- a/pkg/models/components/components.go +++ b/pkg/models/components/components.go @@ -19,47 +19,56 @@ package components import ( "fmt" - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/informers" - "kubesphere.io/kubesphere/pkg/models" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/informers" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/api/resource/v1alpha2" "kubesphere.io/kubesphere/pkg/constants" ) -func GetComponentStatus(name string) (interface{}, error) { +type ComponentsGetter interface { + GetComponentStatus(name string) (v1alpha2.ComponentStatus, error) + GetSystemHealthStatus() (v1alpha2.HealthStatus, error) + GetAllComponentsStatus() ([]v1alpha2.ComponentStatus, error) +} + +type componentsGetter struct { + informers informers.SharedInformerFactory +} + +func NewComponentsGetter(informers informers.SharedInformerFactory) ComponentsGetter { + return &componentsGetter{informers: informers} +} + +func (c *componentsGetter) GetComponentStatus(name string) (v1alpha2.ComponentStatus, error) { var service *corev1.Service var err error - serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister() - for _, ns := range constants.SystemNamespaces { - service, err = serviceLister.Services(ns).Get(name) + service, err = c.informers.Core().V1().Services().Lister().Services(ns).Get(name) if err == nil { break } } if err != nil { - return nil, err + return v1alpha2.ComponentStatus{}, err } if len(service.Spec.Selector) == 0 { - return nil, fmt.Errorf("component %s has no selector", name) + return v1alpha2.ComponentStatus{}, fmt.Errorf("component %s has no selector", name) } - podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister() - - pods, err := podLister.Pods(service.Namespace).List(labels.SelectorFromValidatedSet(service.Spec.Selector)) + pods, err := c.informers.Core().V1().Pods().Lister().Pods(service.Namespace).List(labels.SelectorFromValidatedSet(service.Spec.Selector)) if err != nil { - return nil, err + return v1alpha2.ComponentStatus{}, err } - component := models.ComponentStatus{ + component := v1alpha2.ComponentStatus{ Name: service.Name, Namespace: service.Namespace, SelfLink: service.SelfLink, @@ -86,21 +95,20 @@ func isAllContainersReady(pod *corev1.Pod) bool { return true } -func GetSystemHealthStatus() (*models.HealthStatus, error) { +func (c *componentsGetter) GetSystemHealthStatus() (v1alpha2.HealthStatus, error) { - status := &models.HealthStatus{} + status := v1alpha2.HealthStatus{} // get kubesphere-system components - components, err := GetAllComponentsStatus() + components, err := c.GetAllComponentsStatus() if err != nil { klog.Errorln(err) } status.KubeSphereComponents = components - nodeLister := informers.SharedInformerFactory().Core().V1().Nodes().Lister() // get node status - nodes, err := nodeLister.List(labels.Everything()) + nodes, err := c.informers.Core().V1().Nodes().Lister().List(labels.Everything()) if err != nil { klog.Errorln(err) return status, nil @@ -116,7 +124,7 @@ func GetSystemHealthStatus() (*models.HealthStatus, error) { } } } - nodeStatus := models.NodeStatus{TotalNodes: totalNodes, HealthyNodes: healthyNodes} + nodeStatus := v1alpha2.NodeStatus{TotalNodes: totalNodes, HealthyNodes: healthyNodes} status.NodeStatus = nodeStatus @@ -124,16 +132,14 @@ func GetSystemHealthStatus() (*models.HealthStatus, error) { } -func GetAllComponentsStatus() ([]models.ComponentStatus, error) { - serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister() - podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister() +func (c *componentsGetter) GetAllComponentsStatus() ([]v1alpha2.ComponentStatus, error) { - components := make([]models.ComponentStatus, 0) + components := make([]v1alpha2.ComponentStatus, 0) var err error for _, ns := range constants.SystemNamespaces { - services, err := serviceLister.Services(ns).List(labels.Everything()) + services, err := c.informers.Core().V1().Services().Lister().Services(ns).List(labels.Everything()) if err != nil { klog.Error(err) @@ -147,7 +153,7 @@ func GetAllComponentsStatus() ([]models.ComponentStatus, error) { continue } - component := models.ComponentStatus{ + component := v1alpha2.ComponentStatus{ Name: service.Name, Namespace: service.Namespace, SelfLink: service.SelfLink, @@ -157,7 +163,7 @@ func GetAllComponentsStatus() ([]models.ComponentStatus, error) { TotalBackends: 0, } - pods, err := podLister.Pods(ns).List(labels.SelectorFromValidatedSet(service.Spec.Selector)) + pods, err := c.informers.Core().V1().Pods().Lister().Pods(ns).List(labels.SelectorFromValidatedSet(service.Spec.Selector)) if err != nil { klog.Errorln(err) diff --git a/pkg/models/components/components_test.go b/pkg/models/components/components_test.go new file mode 100644 index 000000000..95d66076e --- /dev/null +++ b/pkg/models/components/components_test.go @@ -0,0 +1,356 @@ +package components + +import ( + "fmt" + "github.com/google/go-cmp/cmp" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + "kubesphere.io/kubesphere/pkg/api/resource/v1alpha2" + "testing" + "time" +) + +func service(name, namespace string, selector map[string]string) runtime.Object { + return &v1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: v1.ServiceSpec{ + Selector: selector, + }, + } +} + +func pods(name, namespace string, labels map[string]string, healthPods, totalPods int) []runtime.Object { + var ps []runtime.Object + + for index := 0; index < totalPods; index++ { + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%d", name, index), + Namespace: namespace, + Labels: labels, + }, + Status: v1.PodStatus{ + Phase: v1.PodRunning, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: fmt.Sprintf("%s-%d", name, index), + Ready: true, + }, + }, + }, + } + + if index >= healthPods { + pod.Status.Phase = v1.PodPending + pod.Status.ContainerStatuses[0].Ready = false + } + + ps = append(ps, pod) + } + + return ps +} + +func nodes(name string, healthNodes, totalNodes int) []runtime.Object { + var ns []runtime.Object + + for index := 0; index < totalNodes; index++ { + node := &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%d", name, index), + }, + Status: v1.NodeStatus{ + Phase: v1.NodeRunning, + Conditions: []v1.NodeCondition{ + { + Type: v1.NodeReady, + Status: v1.ConditionTrue, + }, + }, + }, + } + + if index >= healthNodes { + node.Status.Phase = v1.NodePending + node.Status.Conditions[0].Status = v1.ConditionFalse + } + + ns = append(ns, node) + } + + return ns +} + +func TestGetSystemHealthStatus(t *testing.T) { + var tests = []struct { + description string + labels map[string]string + namespace string + name string + healthPods int + totalPods int + healthNodes int + totalNodes int + expected v1alpha2.HealthStatus + }{ + { + "no backends", + map[string]string{"app": "foo"}, + "kube-system", + "", + 0, + 0, + 0, + 0, + v1alpha2.HealthStatus{ + KubeSphereComponents: []v1alpha2.ComponentStatus{ + { + Namespace: "kube-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 0, + HealthyBackends: 0, + }, + }, + NodeStatus: v1alpha2.NodeStatus{}, + }, + }, + { + "all healthy", + map[string]string{"app": "foo"}, + "kubesphere-system", + "ks-apiserver", + 2, + 2, + 2, + 2, + v1alpha2.HealthStatus{ + KubeSphereComponents: []v1alpha2.ComponentStatus{ + { + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 2, + HealthyBackends: 2, + }, + }, + NodeStatus: v1alpha2.NodeStatus{ + TotalNodes: 2, + HealthyNodes: 2, + }, + }, + }, + { + "all unhealthy", + map[string]string{"app": "foo"}, + "kubesphere-system", + "ks-apiserver", + 0, + 2, + 0, + 2, + v1alpha2.HealthStatus{ + KubeSphereComponents: []v1alpha2.ComponentStatus{ + { + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 2, + HealthyBackends: 0, + }, + }, + NodeStatus: v1alpha2.NodeStatus{ + TotalNodes: 2, + HealthyNodes: 0, + }, + }, + }, + { + "half healthy", + map[string]string{"app": "foo"}, + "kubesphere-system", + "ks-apiserver", + 2, + 4, + 2, + 4, + v1alpha2.HealthStatus{ + KubeSphereComponents: []v1alpha2.ComponentStatus{ + { + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 4, + HealthyBackends: 2, + }, + }, + NodeStatus: v1alpha2.NodeStatus{ + TotalNodes: 4, + HealthyNodes: 2, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods) + svc := service(test.name, test.namespace, test.labels) + ns := nodes(test.name, test.healthNodes, test.totalNodes) + + var objs []runtime.Object + objs = append(objs, ps...) + objs = append(objs, svc) + objs = append(objs, ns...) + + client := fake.NewSimpleClientset(objs...) + + informer := informers.NewSharedInformerFactory(client, time.Minute*10) + + informer.Core().V1().Services().Informer().GetIndexer().Add(svc) + + for _, obj := range ps { + informer.Core().V1().Pods().Informer().GetIndexer().Add(obj) + } + + for _, obj := range ns { + informer.Core().V1().Nodes().Informer().GetIndexer().Add(obj) + } + + c := NewComponentsGetter(informer) + healthStatus, err := c.GetSystemHealthStatus() + if err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(healthStatus, test.expected); diff != "" { + t.Errorf("%T differ (-got, +want): %s", test.expected, diff) + return + } + }) + } + +} + +func TestGetComponentStatus(t *testing.T) { + var tests = []struct { + description string + name string + namespace string + labels map[string]string + healthPods int + totalPods int + expected v1alpha2.ComponentStatus + expectedError bool + }{ + { + "no component", + "random", + "foo", + map[string]string{"app": "foo"}, + 2, + 4, + v1alpha2.ComponentStatus{ + Name: "", + Namespace: "", + SelfLink: "", + Label: nil, + StartedAt: time.Time{}, + TotalBackends: 0, + HealthyBackends: 0, + }, + true, + }, + { + "all healthy", + "ks-apiserver", + "kubesphere-system", + map[string]string{"app": "foo"}, + 2, + 4, + v1alpha2.ComponentStatus{ + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 4, + HealthyBackends: 2, + }, + false, + }, + { + "all unhealthy", + "ks-apiserver", + "kubesphere-system", + map[string]string{"app": "foo"}, + 0, + 4, + v1alpha2.ComponentStatus{ + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 4, + HealthyBackends: 0, + }, + false, + }, + { + "half healthy", + "ks-apiserver", + "kubesphere-system", + map[string]string{"app": "foo"}, + 2, + 4, + v1alpha2.ComponentStatus{ + Name: "ks-apiserver", + Namespace: "kubesphere-system", + Label: map[string]string{"app": "foo"}, + TotalBackends: 4, + HealthyBackends: 2, + }, + false, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods) + svc := service(test.name, test.namespace, test.labels) + + var objs []runtime.Object + objs = append(objs, ps...) + objs = append(objs, svc) + + client := fake.NewSimpleClientset(objs...) + + informer := informers.NewSharedInformerFactory(client, time.Minute*10) + + informer.Core().V1().Services().Informer().GetIndexer().Add(svc) + + for _, obj := range ps { + informer.Core().V1().Pods().Informer().GetIndexer().Add(obj) + } + + c := NewComponentsGetter(informer) + healthStatus, err := c.GetComponentStatus(test.name) + if err == nil && test.expectedError { + t.Fatalf("expected error while got nothing") + } else if err != nil && !test.expectedError { + t.Fatal(err) + } + + if diff := cmp.Diff(healthStatus, test.expected); diff != "" { + t.Errorf("%T differ (-got, +want): %s", test.expected, diff) + return + } + }) + } +} diff --git a/pkg/models/devops/devops.go b/pkg/models/devops/devops.go index 87c22bbe4..6b032ddac 100644 --- a/pkg/models/devops/devops.go +++ b/pkg/models/devops/devops.go @@ -42,6 +42,12 @@ const ( cronJobLayout = "Monday, January 2, 2006 15:04:05 PM" ) +type DevopsOperator interface { +} + +type devopsOperator struct { +} + func GetPipeline(projectName, pipelineName string, req *http.Request) ([]byte, error) { devops, err := cs.ClientSets().Devops() if err != nil { diff --git a/pkg/models/devops/s2ibinary_handler.go b/pkg/models/devops/s2ibinary_handler.go index 73a0d1425..71c3c060c 100644 --- a/pkg/models/devops/s2ibinary_handler.go +++ b/pkg/models/devops/s2ibinary_handler.go @@ -3,33 +3,37 @@ package devops import ( "code.cloudfoundry.org/bytefmt" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/emicklei/go-restful" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/util/retry" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/client/clientset/versioned" + "kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/simple/client" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "mime/multipart" "net/http" "reflect" - "time" ) const ( GetS2iBinaryURL = "http://ks-apiserver.kubesphere-system.svc/kapis/devops.kubesphere.io/v1alpha2/namespaces/%s/s2ibinaries/%s/file/%s" ) -func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) { - s3Client, err := client.ClientSets().S3() - if err != nil { - return nil, err - } +type S2iBinaryUploader interface { + UploadBinary(name, namespace, md5 string, header *multipart.FileHeader) (*v1alpha1.S2iBinary, error) + DownloadBinary(name, namespace, fileName string) (string, error) +} + +type s2iBinaryUploader struct { + client versioned.Interface + informers externalversions.SharedInformerFactory + s3Client s3.Interface +} + +func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) { binFile, err := fileHeader.Open() if err != nil { klog.Errorf("%+v", err) @@ -37,7 +41,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead } defer binFile.Close() - origin, err := informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) + origin, err := s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) if err != nil { klog.Errorf("%+v", err) return nil, err @@ -58,7 +62,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead } //Set status Uploading to lock resource - uploading, err := SetS2iBinaryStatus(copy, v1alpha1.StatusUploading) + uploading, err := s.SetS2iBinaryStatus(copy, v1alpha1.StatusUploading) if err != nil { err := restful.NewError(http.StatusConflict, fmt.Sprintf("could not set status: %+v", err)) klog.Error(err) @@ -71,51 +75,53 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead copy.Spec.FileName = fileHeader.Filename copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName) - s3session := s3Client.Session() - if s3session == nil { - err := fmt.Errorf("could not connect to s2i s3") - klog.Error(err) - _, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase) - if serr != nil { - klog.Error(serr) - return nil, err - } - return nil, err - } - uploader := s3manager.NewUploader(s3session, func(uploader *s3manager.Uploader) { - uploader.PartSize = 5 * bytefmt.MEGABYTE - uploader.LeavePartsOnError = true - }) - _, err = uploader.Upload(&s3manager.UploadInput{ - Bucket: s3Client.Bucket(), - Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)), - Body: binFile, - ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", copy.Spec.FileName)), - }) - - if err != nil { - if aerr, ok := err.(awserr.Error); ok { - switch aerr.Code() { - case s3.ErrCodeNoSuchBucket: - klog.Error(err) - _, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase) - if serr != nil { - klog.Error(serr) - } - return nil, err - default: - klog.Error(err) - _, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed) - if serr != nil { - klog.Error(serr) - } + /* + TODO: upload binary file use s3.Interface + s3session := s3Client.Session() + if s3session == nil { + err := fmt.Errorf("could not connect to s2i s3") + klog.Error(err) + _, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase) + if serr != nil { + klog.Error(serr) return nil, err } + return nil, err } - klog.Error(err) - return nil, err - } + uploader := s3manager.NewUploader(s3session, func(uploader *s3manager.Uploader) { + uploader.PartSize = 5 * bytefmt.MEGABYTE + uploader.LeavePartsOnError = true + }) + _, err = uploader.Upload(&s3manager.UploadInput{ + Bucket: s3Client.Bucket(), + Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)), + Body: binFile, + ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", copy.Spec.FileName)), + }) + if err != nil { + if aerr, ok := err.(awserr.Error); ok { + switch aerr.Code() { + case s3.ErrCodeNoSuchBucket: + klog.Error(err) + _, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase) + if serr != nil { + klog.Error(serr) + } + return nil, err + default: + klog.Error(err) + _, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed) + if serr != nil { + klog.Error(serr) + } + return nil, err + } + } + klog.Error(err) + return nil, err + } + */ if copy.Spec.UploadTimeStamp == nil { copy.Spec.UploadTimeStamp = new(metav1.Time) } @@ -126,7 +132,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead return nil, err } - copy, err = SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusReady) + copy, err = s.SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusReady) if err != nil { klog.Error(err) return nil, err @@ -134,46 +140,47 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead return copy, nil } -func DownloadS2iBinary(namespace, name, fileName string) (string, error) { - s3Client, err := client.ClientSets().S3() - if err != nil { - return "", err - } +func (s *s2iBinaryUploader) DownloadS2iBinary(namespace, name, fileName string) (string, error) { - origin, err := informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) + origin, err := s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) if err != nil { klog.Errorf("%+v", err) return "", err } + if origin.Spec.FileName != fileName { err := fmt.Errorf("could not fould file %s", fileName) klog.Error(err) return "", err } + if origin.Status.Phase != v1alpha1.StatusReady { err := restful.NewError(http.StatusBadRequest, "file is not ready, please try later") klog.Error(err) return "", err } - req, _ := s3Client.Client().GetObjectRequest(&s3.GetObjectInput{ - Bucket: s3Client.Bucket(), - Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)), - ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", origin.Spec.FileName)), - }) - url, err := req.Presign(5 * time.Minute) - if err != nil { - klog.Error(err) - return "", err - } - return url, nil + /* + TODO: get download url of requested binary + req, _ := s.s3Client.Client().GetObjectRequest(&s3.GetObjectInput{ + Bucket: s3Client.Bucket(), + Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)), + ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", origin.Spec.FileName)), + }) + url, err := req.Presign(5 * time.Minute) + if err != nil { + klog.Error(err) + return "", err + } + */ + return "", nil } -func SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { +func (s *s2iBinaryUploader) SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { copy := s2ibin.DeepCopy() copy.Status.Phase = status - copy, err := client.ClientSets().K8s().KubeSphere().DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(copy) + copy, err := s.client.DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(copy) if err != nil { klog.Error(err) return nil, err @@ -181,18 +188,18 @@ func SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2 return copy, nil } -func SetS2iBinaryStatusWithRetry(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { +func (s *s2iBinaryUploader) SetS2iBinaryStatusWithRetry(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { var bin *v1alpha1.S2iBinary var err error err = retry.RetryOnConflict(retry.DefaultRetry, func() error { - bin, err = informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name) + bin, err = s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name) if err != nil { klog.Error(err) return err } bin.Status.Phase = status - bin, err = client.ClientSets().K8s().KubeSphere().DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(bin) + bin, err = s.client.DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(bin) if err != nil { klog.Error(err) return err diff --git a/pkg/models/git/git.go b/pkg/models/git/git.go index c4f6a027c..ef147dfd8 100644 --- a/pkg/models/git/git.go +++ b/pkg/models/git/git.go @@ -7,7 +7,7 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing/transport/http" "gopkg.in/src-d/go-git.v4/storage/memory" corev1 "k8s.io/api/core/v1" - "kubesphere.io/kubesphere/pkg/informers" + "k8s.io/client-go/informers" ) type AuthInfo struct { @@ -15,12 +15,23 @@ type AuthInfo struct { SecretRef *corev1.SecretReference `json:"secretRef,omitempty" description:"auth secret reference"` } -func GitReadVerify(namespace string, authInfo AuthInfo) error { - username := "" - password := "" - if authInfo.SecretRef != nil { - secret, err := informers.SharedInformerFactory().Core().V1().Secrets().Lister(). - Secrets(authInfo.SecretRef.Namespace).Get(authInfo.SecretRef.Name) +type GitVerifier interface { + VerifyGitCredential(remoteUrl, namespace, secretName string) error +} + +type gitVerifier struct { + informers informers.SharedInformerFactory +} + +func NewGitVerifier(informers informers.SharedInformerFactory) GitVerifier { + return &gitVerifier{informers: informers} +} + +func (c *gitVerifier) VerifyGitCredential(remoteUrl, namespace, secretName string) error { + var username, password string + + if len(secretName) > 0 { + secret, err := c.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName) if err != nil { return err } @@ -36,10 +47,10 @@ func GitReadVerify(namespace string, authInfo AuthInfo) error { password = string(passwordBytes) } - return gitReadVerifyWithBasicAuth(string(username), string(password), authInfo.RemoteUrl) + return c.gitReadVerifyWithBasicAuth(username, password, remoteUrl) } -func gitReadVerifyWithBasicAuth(username string, password string, remote string) error { +func (c *gitVerifier) gitReadVerifyWithBasicAuth(username string, password string, remote string) error { r, _ := git.Init(memory.NewStorage(), nil) // Add a new remote, with the default fetch refspec diff --git a/pkg/models/git/git_test.go b/pkg/models/git/git_test.go index fdc0954bd..7989f60ba 100644 --- a/pkg/models/git/git_test.go +++ b/pkg/models/git/git_test.go @@ -34,8 +34,10 @@ func TestGitReadVerifyWithBasicAuth(t *testing.T) { "remote": "git@fdsfs41342`@@@2414!!!!github.com:kubesphere/kubesphere.git", }, } + verifier := gitVerifier{informers: nil} + for _, item := range shouldSuccess { - err := gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) + err := verifier.gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) if err != nil { t.Errorf("should could access repo [%s] with %s:%s, %v", item["username"], item["password"], item["remote"], err) @@ -43,7 +45,7 @@ func TestGitReadVerifyWithBasicAuth(t *testing.T) { } for _, item := range shouldFailed { - err := gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) + err := verifier.gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) if err == nil { t.Errorf("should could access repo [%s] with %s:%s ", item["username"], item["password"], item["remote"]) } diff --git a/pkg/models/iam/am.go b/pkg/models/iam/am.go index 8131e14de..8867e3415 100644 --- a/pkg/models/iam/am.go +++ b/pkg/models/iam/am.go @@ -26,12 +26,13 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/apiserver/resources" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models/iam/policy" "kubesphere.io/kubesphere/pkg/models/kubectl" - "kubesphere.io/kubesphere/pkg/models/resources" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/utils/k8sutil" @@ -354,7 +355,7 @@ func ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions, switch orderBy { default: fallthrough - case resources.Name: + case v1alpha2.Name: return strings.Compare(users[i].Username, users[j].Username) <= 0 } }) @@ -401,13 +402,13 @@ func RoleUsers(namespace string, roleName string) ([]*models.User, error) { } func ListRoles(namespace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { - return resources.ListResources(namespace, resources.Roles, conditions, orderBy, reverse, limit, offset) + return resources.ListResources(namespace, v1alpha2.Roles, conditions, orderBy, reverse, limit, offset) } func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { - conditions.Match[resources.OwnerName] = workspace - conditions.Match[resources.OwnerKind] = "Workspace" - result, err := resources.ListResources("", resources.ClusterRoles, conditions, orderBy, reverse, limit, offset) + conditions.Match[v1alpha2.OwnerName] = workspace + conditions.Match[v1alpha2.OwnerKind] = "Workspace" + result, err := resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset) if err != nil { return nil, err @@ -424,7 +425,7 @@ func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy } func ListClusterRoles(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { - return resources.ListResources("", resources.ClusterRoles, conditions, orderBy, reverse, limit, offset) + return resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset) } func NamespaceUsers(namespaceName string) ([]*models.User, error) { diff --git a/pkg/models/iam/im.go b/pkg/models/iam/im.go index 4a1c02c40..1c35d2a5b 100644 --- a/pkg/models/iam/im.go +++ b/pkg/models/iam/im.go @@ -799,8 +799,8 @@ func deleteUserInDevOps(username string) error { devopsDb, err := clientset.ClientSets().MySQL() if err != nil { - if _, ok := err.(clientset.ClientSetNotEnabledError); ok { - klog.Warning("devops client is not enable") + if err == clientset.ErrClientSetNotEnabled { + klog.Warning("mysql is not enable") return nil } return err @@ -808,11 +808,10 @@ func deleteUserInDevOps(username string) error { dp, err := clientset.ClientSets().Devops() if err != nil { - if _, ok := err.(clientset.ClientSetNotEnabledError); ok { + if err == clientset.ErrClientSetNotEnabled { klog.Warning("devops client is not enable") return nil } - return err } diff --git a/pkg/models/log/logcrd.go b/pkg/models/log/logcrd.go index 14a21e542..82f6855f6 100644 --- a/pkg/models/log/logcrd.go +++ b/pkg/models/log/logcrd.go @@ -28,7 +28,6 @@ import ( "k8s.io/klog" "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2" "kubesphere.io/kubesphere/pkg/informers" - fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit" "net/http" "strings" "time" diff --git a/pkg/models/log/types.go b/pkg/models/log/types.go index b4b402fa6..3da3620e2 100644 --- a/pkg/models/log/types.go +++ b/pkg/models/log/types.go @@ -18,10 +18,6 @@ package log -import ( - fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit" -) - type FluentbitOutputsResult struct { Status int `json:"status" description:"response status"` Error string `json:"error,omitempty" description:"debug information"` diff --git a/pkg/models/nodes/nodes.go b/pkg/models/nodes/nodes.go deleted file mode 100644 index b05a237c2..000000000 --- a/pkg/models/nodes/nodes.go +++ /dev/null @@ -1,279 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package nodes - -import ( - "fmt" - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/simple/client" - "math" - "strings" - "time" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" - policy "k8s.io/api/policy/v1beta1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" -) - -func DrainNode(nodename string) (err error) { - - k8sclient := client.ClientSets().K8s().Kubernetes() - node, err := k8sclient.CoreV1().Nodes().Get(nodename, metav1.GetOptions{}) - if err != nil { - return err - } - - if node.Spec.Unschedulable { - return fmt.Errorf("node %s have been drained", nodename) - } - - data := []byte(" {\"spec\":{\"unschedulable\":true}}") - _, err = k8sclient.CoreV1().Nodes().Patch(nodename, types.StrategicMergePatchType, data) - if err != nil { - return err - } - donech := make(chan bool) - errch := make(chan error) - go drainEviction(nodename, donech, errch) - for { - select { - case err := <-errch: - return err - case <-donech: - return nil - } - } - -} - -func drainEviction(nodename string, donech chan bool, errch chan error) { - - k8sclient := client.ClientSets().K8s().Kubernetes() - var options metav1.ListOptions - pods := make([]v1.Pod, 0) - options.FieldSelector = "spec.nodeName=" + nodename - podList, err := k8sclient.CoreV1().Pods("").List(options) - if err != nil { - klog.Fatal(err) - errch <- err - } - options.FieldSelector = "" - daemonsetList, err := k8sclient.AppsV1().DaemonSets("").List(options) - - if err != nil { - - klog.Fatal(err) - errch <- err - - } - // remove mirror pod static pod - if len(podList.Items) > 0 { - - for _, pod := range podList.Items { - - if !containDaemonset(pod, *daemonsetList) { - //static or mirror pod - if isStaticPod(&pod) || isMirrorPod(&pod) { - continue - } else { - pods = append(pods, pod) - } - } - } - } - if len(pods) == 0 { - donech <- true - } else { - - //create eviction - getPodFn := func(namespace, name string) (*v1.Pod, error) { - return k8sclient.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - } - evicerr := evictPods(pods, 0, getPodFn) - - if evicerr == nil { - donech <- true - } else { - klog.Fatal(evicerr) - errch <- err - } - } -} - -func getPodSource(pod *v1.Pod) (string, error) { - if pod.Annotations != nil { - if source, ok := pod.Annotations["kubernetes.io/config.source"]; ok { - return source, nil - } - } - return "", fmt.Errorf("cannot get source of pod %q", pod.UID) -} - -func isStaticPod(pod *v1.Pod) bool { - source, err := getPodSource(pod) - return err == nil && source != "api" -} - -func isMirrorPod(pod *v1.Pod) bool { - _, ok := pod.Annotations[v1.MirrorPodAnnotationKey] - return ok -} - -func containDaemonset(pod v1.Pod, daemonsetList appsv1.DaemonSetList) bool { - - flag := false - for _, daemonset := range daemonsetList.Items { - - if strings.Contains(pod.Name, daemonset.Name) { - - flag = true - } - - } - return flag - -} - -func evictPod(pod v1.Pod, GracePeriodSeconds int) error { - - k8sclient := client.ClientSets().K8s().Kubernetes() - deleteOptions := &metav1.DeleteOptions{} - if GracePeriodSeconds >= 0 { - gracePeriodSeconds := int64(GracePeriodSeconds) - deleteOptions.GracePeriodSeconds = &gracePeriodSeconds - } - - var eviction policy.Eviction - eviction.Kind = "Eviction" - eviction.APIVersion = "policy/v1beta1" - eviction.Namespace = pod.Namespace - eviction.Name = pod.Name - eviction.DeleteOptions = deleteOptions - err := k8sclient.CoreV1().Pods(pod.Namespace).Evict(&eviction) - if err != nil { - return err - } - - return nil -} - -func evictPods(pods []v1.Pod, GracePeriodSeconds int, getPodFn func(namespace, name string) (*v1.Pod, error)) error { - doneCh := make(chan bool, len(pods)) - errCh := make(chan error, 1) - - for _, pod := range pods { - go func(pod v1.Pod, doneCh chan bool, errCh chan error) { - var err error - var count int - for { - err = evictPod(pod, GracePeriodSeconds) - if err == nil { - count++ - if count > 2 { - break - } else { - continue - } - } else if apierrors.IsNotFound(err) { - count = 0 - doneCh <- true - klog.Info(fmt.Sprintf("pod %s evict", pod.Name)) - return - } else if apierrors.IsTooManyRequests(err) { - count = 0 - time.Sleep(5 * time.Second) - } else { - count = 0 - errCh <- fmt.Errorf("error when evicting pod %q: %v", pod.Name, err) - return - } - } - - podArray := []v1.Pod{pod} - _, err = waitForDelete(podArray, time.Second, time.Duration(math.MaxInt64), getPodFn) - if err == nil { - doneCh <- true - klog.Info(fmt.Sprintf("pod %s delete", pod.Name)) - } else { - errCh <- fmt.Errorf("error when waiting for pod %q terminating: %v", pod.Name, err) - } - }(pod, doneCh, errCh) - } - - Timeout := 300 * power(10, 9) - doneCount := 0 - // 0 timeout means infinite, we use MaxInt64 to represent it. - var globalTimeout time.Duration - if Timeout == 0 { - globalTimeout = time.Duration(math.MaxInt64) - } else { - globalTimeout = time.Duration(Timeout) - } - for { - select { - case err := <-errCh: - return err - case <-doneCh: - doneCount++ - if doneCount == len(pods) { - return nil - } - case <-time.After(globalTimeout): - return fmt.Errorf("drain did not complete within %v", globalTimeout) - } - } -} - -func waitForDelete(pods []v1.Pod, interval, timeout time.Duration, getPodFn func(string, string) (*v1.Pod, error)) ([]v1.Pod, error) { - - err := wait.PollImmediate(interval, timeout, func() (bool, error) { - var pendingPods []v1.Pod - for i, pod := range pods { - p, err := getPodFn(pod.Namespace, pod.Name) - if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) { - continue - } else if err != nil { - return false, err - } else { - pendingPods = append(pendingPods, pods[i]) - } - } - pods = pendingPods - if len(pendingPods) > 0 { - return false, nil - } - return true, nil - }) - return pods, err -} - -func power(x int64, n int) int64 { - - var res int64 = 1 - for n != 0 { - res *= x - n-- - } - - return res - -} diff --git a/pkg/models/openpitrix/applications.go b/pkg/models/openpitrix/applications.go index 2254f1619..3eb42d5d2 100644 --- a/pkg/models/openpitrix/applications.go +++ b/pkg/models/openpitrix/applications.go @@ -28,11 +28,10 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/informers" "k8s.io/klog" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models" - "kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/server/params" cs "kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" @@ -40,6 +39,26 @@ import ( "strings" ) +type Interface interface { + List(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error) + Get(namespace, clusterID string) (*Application, error) + Create(namespace string, request CreateClusterRequest) error + Patch(request ModifyClusterAttributesRequest) error + Delete(id string) error +} + +type applicationOperator struct { + informers informers.SharedInformerFactory + opClient pb.ClusterManagerClient +} + +func NewApplicaitonOperator(informers informers.SharedInformerFactory, client pb.ClusterManagerClient) Interface { + return &applicationOperator{ + informers: informers, + opClient: client, + } +} + type Application struct { Name string `json:"name" description:"application name"` Cluster *Cluster `json:"cluster,omitempty" description:"application cluster info"` @@ -56,7 +75,7 @@ type workLoads struct { Daemonsets []appsv1.DaemonSet `json:"daemonsets,omitempty" description:"daemonset list"` } -func ListApplications(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error) { +func (c *applicationOperator) List(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error) { client, err := cs.ClientSets().OpenPitrix() if err != nil { klog.Error(err) @@ -92,7 +111,7 @@ func ListApplications(conditions *params.Conditions, limit, offset int, orderBy result := models.PageableResponse{TotalCount: int(resp.TotalCount)} result.Items = make([]interface{}, 0) for _, cluster := range resp.ClusterSet { - app, err := describeApplication(cluster) + app, err := c.describeApplication(cluster) if err != nil { klog.Errorln(err) return nil, err @@ -103,7 +122,7 @@ func ListApplications(conditions *params.Conditions, limit, offset int, orderBy return &result, nil } -func describeApplication(cluster *pb.Cluster) (*Application, error) { +func (c *applicationOperator) describeApplication(cluster *pb.Cluster) (*Application, error) { op, err := cs.ClientSets().OpenPitrix() if err != nil { klog.Error(err) @@ -131,15 +150,9 @@ func describeApplication(cluster *pb.Cluster) (*Application, error) { return &app, nil } -func DescribeApplication(namespace string, clusterId string) (*Application, error) { +func (c *applicationOperator) Get(namespace string, clusterId string) (*Application, error) { - client, err := cs.ClientSets().OpenPitrix() - if err != nil { - klog.Error(err) - return nil, err - } - - clusters, err := client.Cluster().DescribeClusters(openpitrix.SystemContext(), &pb.DescribeClustersRequest{ClusterId: []string{clusterId}, Limit: 1}) + clusters, err := c.opClient.DescribeClusters(openpitrix.SystemContext(), &pb.DescribeClustersRequest{ClusterId: []string{clusterId}, Limit: 1}) if err != nil { klog.Errorln(err) @@ -154,26 +167,26 @@ func DescribeApplication(namespace string, clusterId string) (*Application, erro klog.Errorln(err) return nil, err } - app, err := describeApplication(cluster) + app, err := c.describeApplication(cluster) if err != nil { klog.Errorln(err) return nil, err } - workloads, err := getWorkLoads(namespace, cluster.ClusterRoleSet) + workloads, err := c.getWorkLoads(namespace, cluster.ClusterRoleSet) if err != nil { klog.Errorln(err) return nil, err } app.WorkLoads = workloads - workloadLabels := getLabels(namespace, app.WorkLoads) - app.Services = getSvcs(namespace, workloadLabels) - app.Ingresses = getIng(namespace, app.Services) + workloadLabels := c.getLabels(namespace, app.WorkLoads) + app.Services = c.getSvcs(namespace, workloadLabels) + app.Ingresses = c.getIng(namespace, app.Services) return app, nil } -func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, error) { +func (c *applicationOperator) getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, error) { var works workLoads for _, clusterRole := range clusterRoles { @@ -182,7 +195,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, if strings.HasSuffix(workLoadName, openpitrix.DeploySuffix) { name := strings.Split(workLoadName, openpitrix.DeploySuffix)[0] - item, err := informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).Get(name) + item, err := c.informers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name) if err != nil { // app not ready @@ -199,7 +212,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, if strings.HasSuffix(workLoadName, openpitrix.DaemonSuffix) { name := strings.Split(workLoadName, openpitrix.DaemonSuffix)[0] - item, err := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name) + item, err := c.informers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name) if err != nil { // app not ready if errors.IsNotFound(err) { @@ -214,7 +227,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, if strings.HasSuffix(workLoadName, openpitrix.StateSuffix) { name := strings.Split(workLoadName, openpitrix.StateSuffix)[0] - item, err := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name) + item, err := c.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name) if err != nil { // app not ready if errors.IsNotFound(err) { @@ -231,8 +244,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, return &works, nil } -func getLabels(namespace string, workloads *workLoads) *[]map[string]string { - k8sClient := cs.ClientSets().K8s().Kubernetes() +func (c *applicationOperator) getLabels(namespace string, workloads *workLoads) *[]map[string]string { var workloadLabels []map[string]string if workloads == nil { @@ -240,7 +252,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string { } for _, workload := range workloads.Deployments { - deploy, err := k8sClient.AppsV1().Deployments(namespace).Get(workload.Name, metav1.GetOptions{}) + deploy, err := c.informers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(workload.Name) if errors.IsNotFound(err) { continue } @@ -248,7 +260,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string { } for _, workload := range workloads.Daemonsets { - daemonset, err := k8sClient.AppsV1().DaemonSets(namespace).Get(workload.Name, metav1.GetOptions{}) + daemonset, err := c.informers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(workload.Name) if errors.IsNotFound(err) { continue } @@ -256,7 +268,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string { } for _, workload := range workloads.Statefulsets { - statefulset, err := k8sClient.AppsV1().StatefulSets(namespace).Get(workload.Name, metav1.GetOptions{}) + statefulset, err := c.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(workload.Name) if errors.IsNotFound(err) { continue } @@ -266,7 +278,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string { return &workloadLabels } -func isExist(svcs []v1.Service, svc v1.Service) bool { +func (c *applicationOperator) isExist(svcs []v1.Service, svc v1.Service) bool { for _, item := range svcs { if item.Name == svc.Name && item.Namespace == svc.Namespace { return true @@ -275,7 +287,7 @@ func isExist(svcs []v1.Service, svc v1.Service) bool { return false } -func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service { +func (c *applicationOperator) getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service { if len(*workLoadLabels) == 0 { return nil } @@ -288,7 +300,7 @@ func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service klog.Errorf("get app's svc failed, reason: %v", err) } for _, item := range svcs.Items { - if !isExist(services, item) { + if !c.isExist(services, item) { services = append(services, item) } } @@ -297,21 +309,23 @@ func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service return services } -func getIng(namespace string, services []v1.Service) []v1beta1.Ingress { +func (c *applicationOperator) getIng(namespace string, services []v1.Service) []v1beta1.Ingress { if services == nil { return nil } var ings []v1beta1.Ingress for _, svc := range services { - result, err := resources.ListResources(namespace, "ingress", ¶ms.Conditions{Fuzzy: map[string]string{"serviceName": svc.Name}}, "", false, -1, 0) + ingresses, err := c.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything()) if err != nil { - klog.Errorln(err) - return nil + klog.Error(err) + return ings } - for _, i := range result.Items { - ingress := i.(*v1beta1.Ingress) + for _, ingress := range ingresses { + if ingress.Spec.Backend.ServiceName != svc.Name { + continue + } exist := false var tmpRules []v1beta1.IngressRule @@ -322,7 +336,6 @@ func getIng(namespace string, services []v1.Service) []v1beta1.Ingress { tmpRules = append(tmpRules, rule) } } - } if exist { @@ -337,8 +350,8 @@ func getIng(namespace string, services []v1.Service) []v1beta1.Ingress { return ings } -func CreateApplication(namespace string, request CreateClusterRequest) error { - ns, err := informers.SharedInformerFactory().Core().V1().Namespaces().Lister().Get(namespace) +func (c *applicationOperator) Create(namespace string, request CreateClusterRequest) error { + ns, err := c.informers.Core().V1().Namespaces().Lister().Get(namespace) if err != nil { klog.Error(err) return err @@ -372,7 +385,7 @@ func CreateApplication(namespace string, request CreateClusterRequest) error { return nil } -func PatchApplication(request *ModifyClusterAttributesRequest) error { +func (c *applicationOperator) Patch(request ModifyClusterAttributesRequest) error { op, err := cs.ClientSets().OpenPitrix() if err != nil { @@ -397,15 +410,8 @@ func PatchApplication(request *ModifyClusterAttributesRequest) error { return nil } -func DeleteApplication(clusterId string) error { - client, err := cs.ClientSets().OpenPitrix() - - if err != nil { - klog.Error(err) - return err - } - - _, err = client.Cluster().DeleteClusters(openpitrix.SystemContext(), &pb.DeleteClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}}) +func (c *applicationOperator) Delete(clusterId string) error { + _, err := c.opClient.DeleteClusters(openpitrix.SystemContext(), &pb.DeleteClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}}) if err != nil { klog.Errorln(err) diff --git a/pkg/models/quotas/quotas.go b/pkg/models/quotas/quotas.go index 53259bef2..6ab606adb 100644 --- a/pkg/models/quotas/quotas.go +++ b/pkg/models/quotas/quotas.go @@ -22,11 +22,10 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/informers" - "kubesphere.io/kubesphere/pkg/models" - "kubesphere.io/kubesphere/pkg/models/resources" - "kubesphere.io/kubesphere/pkg/server/params" + "kubesphere.io/kubesphere/pkg/api" ) const ( @@ -42,71 +41,69 @@ const ( s2iBuilders = "count/s2ibuilders.devops.kubesphere.io" ) -type NamespacedResourceQuota struct { - Namespace string `json:"namespace,omitempty"` - - Data struct { - v1.ResourceQuotaStatus - - // quota left status, do the math on the side, cause it's - // a lot easier with go-client library - Left v1.ResourceList `json:"left,omitempty"` - } `json:"data,omitempty"` +var supportedResources = map[string]schema.GroupVersionResource{ + deploymentsKey: {Group: "apps", Version: "v1", Resource: "deployments"}, + daemonsetsKey: {Group: "apps", Version: "v1", Resource: "daemonsets"}, + statefulsetsKey: {Group: "apps", Version: "v1", Resource: "statefulsets"}, + podsKey: {Group: "", Version: "v1", Resource: "pods"}, + servicesKey: {Group: "", Version: "v1", Resource: "services"}, + persistentvolumeclaimsKey: {Group: "", Version: "v1", Resource: "persistentvolumeclaims"}, + ingressKey: {Group: "extensions", Version: "v1beta1", Resource: "ingresses"}, + jobsKey: {Group: "batch", Version: "v1", Resource: "jobs"}, + cronJobsKey: {Group: "batch", Version: "v1beta1", Resource: "cronjobs"}, + s2iBuilders: {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"}, } -var ( - resourceMap = map[string]string{ - daemonsetsKey: resources.DaemonSets, - deploymentsKey: resources.Deployments, - ingressKey: resources.Ingresses, - servicesKey: resources.Services, - statefulsetsKey: resources.StatefulSets, - persistentvolumeclaimsKey: resources.PersistentVolumeClaims, - podsKey: resources.Pods, - jobsKey: resources.Jobs, - cronJobsKey: resources.CronJobs, - s2iBuilders: resources.S2iBuilders, - } -) +type ResourceQuotaGetter interface { + GetClusterQuota() (*api.ResourceQuota, error) + GetNamespaceQuota(namespace string) (*api.NamespacedResourceQuota, error) +} -func getUsage(namespace, resource string) (int, error) { - var result *models.PageableResponse - var err error - if resource == resources.Namespaces || resource == resources.StorageClasses { - result, err = resources.ListResources("", resource, ¶ms.Conditions{}, "", false, 1, 0) - } else { - result, err = resources.ListResources(namespace, resource, ¶ms.Conditions{}, "", false, 1, 0) - } +type resourceQuotaGetter struct { + informers informers.SharedInformerFactory +} +func NewResourceQuotaGetter(informers informers.SharedInformerFactory) ResourceQuotaGetter { + return &resourceQuotaGetter{informers: informers} +} + +func (c *resourceQuotaGetter) getUsage(namespace, resource string) (int, error) { + + genericInformer, err := c.informers.ForResource(supportedResources[resource]) + if err != nil { + // we deliberately ignore error if trying to get non existed resource + return 0, nil + } + + result, err := genericInformer.Lister().ByNamespace(namespace).List(labels.Everything()) if err != nil { - klog.Error(err) return 0, err } - return result.TotalCount, nil + return len(result), nil } // no one use this api anymore, marked as deprecated -func GetClusterQuotas() (*models.ResourceQuota, error) { +func (c *resourceQuotaGetter) GetClusterQuota() (*api.ResourceQuota, error) { quota := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)} - for k, v := range resourceMap { - used, err := getUsage("", v) + for r := range supportedResources { + used, err := c.getUsage("", r) if err != nil { return nil, err } var quantity resource.Quantity quantity.Set(int64(used)) - quota.Used[v1.ResourceName(k)] = quantity + quota.Used[v1.ResourceName(r)] = quantity } - return &models.ResourceQuota{Namespace: "\"\"", Data: quota}, nil + return &api.ResourceQuota{Namespace: "\"\"", Data: quota}, nil } -func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) { - quota, err := getNamespaceResourceQuota(namespace) +func (c *resourceQuotaGetter) GetNamespaceQuota(namespace string) (*api.NamespacedResourceQuota, error) { + quota, err := c.getNamespaceResourceQuota(namespace) if err != nil { klog.Error(err) return nil, err @@ -130,10 +127,10 @@ func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) { } // add extra quota usage, cause user may not specify them - for key, val := range resourceMap { + for key := range supportedResources { // only add them when they don't exist in quotastatus if _, ok := quota.Used[v1.ResourceName(key)]; !ok { - used, err := getUsage(namespace, val) + used, err := c.getUsage(namespace, key) if err != nil { klog.Error(err) return nil, err @@ -143,7 +140,7 @@ func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) { } } - var result = NamespacedResourceQuota{ + var result = api.NamespacedResourceQuota{ Namespace: namespace, } result.Data.Hard = quota.Hard @@ -169,8 +166,8 @@ func updateNamespaceQuota(tmpResourceList, resourceList v1.ResourceList) { } } -func getNamespaceResourceQuota(namespace string) (*v1.ResourceQuotaStatus, error) { - resourceQuotaLister := informers.SharedInformerFactory().Core().V1().ResourceQuotas().Lister() +func (c *resourceQuotaGetter) getNamespaceResourceQuota(namespace string) (*v1.ResourceQuotaStatus, error) { + resourceQuotaLister := c.informers.Core().V1().ResourceQuotas().Lister() quotaList, err := resourceQuotaLister.ResourceQuotas(namespace).List(labels.Everything()) if err != nil { klog.Error(err) diff --git a/pkg/models/registries/image_type.go b/pkg/models/registries/image_type.go index f7646d95d..e52690623 100644 --- a/pkg/models/registries/image_type.go +++ b/pkg/models/registries/image_type.go @@ -5,26 +5,15 @@ import ( "time" ) -type AuthInfo struct { - Username string `json:"username" description:"username"` - Password string `json:"password" description:"password"` - ServerHost string `json:"serverhost" description:"registry server host"` -} - // ImageBlobInfo describes the info of an image. type ImageDetails struct { // Status is the status of the image search, such as "failed","succeeded". - Status string `json:"status,omitempty" description:"Status is the status of the image search, such as \"succeeded\"."` - - Message string `json:"message,omitempty" description:"Status message."` - + Status string `json:"status,omitempty" description:"Status is the status of the image search, such as \"succeeded\"."` + Message string `json:"message,omitempty" description:"Status message."` ImageManifest *ImageManifest `json:"imageManifest,omitempty" description:"Retrieve the manifest from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#manifest"` - - ImageBlob *ImageBlob `json:"imageBlob,omitempty" description:"Retrieve the blob from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#blob"` - - ImageTag string `json:"imageTag,omitempty" description:"image tag."` - - Registry string `json:"registry,omitempty" description:"registry domain."` + ImageBlob *ImageBlob `json:"imageBlob,omitempty" description:"Retrieve the blob from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#blob"` + ImageTag string `json:"imageTag,omitempty" description:"image tag."` + Registry string `json:"registry,omitempty" description:"registry domain."` } type ImageBlob struct { diff --git a/pkg/models/registries/registries.go b/pkg/models/registries/registries.go index 6fbf5a041..2040b2210 100644 --- a/pkg/models/registries/registries.go +++ b/pkg/models/registries/registries.go @@ -24,10 +24,11 @@ import ( "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/client" + "github.com/emicklei/go-restful" corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/informers" "k8s.io/klog" - log "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/api" ) const ( @@ -52,8 +53,21 @@ type DockerConfigEntry struct { ServerAddress string `json:"serverAddress,omitempty"` } -func RegistryVerify(authInfo AuthInfo) error { - auth := base64.StdEncoding.EncodeToString([]byte(authInfo.Username + ":" + authInfo.Password)) +type RegistryGetter interface { + VerifyRegistryCredential(credential api.RegistryCredential) error + GetEntry(namespace, secretName, imageName string) (ImageDetails, error) +} + +type registryGetter struct { + informers informers.SharedInformerFactory +} + +func NewRegistryGetter(informers informers.SharedInformerFactory) RegistryGetter { + return ®istryGetter{informers: informers} +} + +func (c *registryGetter) VerifyRegistryCredential(credential api.RegistryCredential) error { + auth := base64.StdEncoding.EncodeToString([]byte(credential.Username + ":" + credential.Password)) ctx := context.Background() cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation()) @@ -62,10 +76,10 @@ func RegistryVerify(authInfo AuthInfo) error { } config := types.AuthConfig{ - Username: authInfo.Username, - Password: authInfo.Password, + Username: credential.Username, + Password: credential.Password, Auth: auth, - ServerAddress: authInfo.ServerHost, + ServerAddress: credential.ServerHost, } resp, err := cli.RegistryLogin(ctx, config) @@ -82,21 +96,77 @@ func RegistryVerify(authInfo AuthInfo) error { } } -func GetEntryBySecret(namespace, secretName string) (dockerConfigEntry *DockerConfigEntry, err error) { - if namespace == "" || secretName == "" { - return &DockerConfigEntry{}, nil +func (c *registryGetter) GetEntry(namespace, secretName, imageName string) (ImageDetails, error) { + imageDetails, err := c.getEntryBySecret(namespace, secretName, imageName) + if imageDetails.Status == StatusFailed { + imageDetails.Message = err.Error() } - secret, err := informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName) + + return imageDetails, err +} + +func (c *registryGetter) getEntryBySecret(namespace, secretName, imageName string) (imageDetails ImageDetails, err error) { + failedImageDetails := ImageDetails{ + Status: StatusFailed, + Message: "", + } + + if namespace == "" || secretName == "" { + return failedImageDetails, fmt.Errorf("namespace or secret name not provided") + } + secret, err := c.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName) if err != nil { - log.Errorf("%+v", err) - return nil, err + return failedImageDetails, err } entry, err := getDockerEntryFromDockerSecret(secret) if err != nil { - log.Errorf("%+v", err) - return nil, err + return failedImageDetails, err } - return entry, nil + + // parse image + image, err := ParseImage(imageName) + if err != nil { + return failedImageDetails, err + } + + // Create the registry client. + r, err := CreateRegistryClient(entry.Username, entry.Password, image.Domain) + if err != nil { + return failedImageDetails, err + } + + digestUrl := r.GetDigestUrl(image) + + // Get token. + token, err := r.Token(digestUrl) + if err != nil { + return failedImageDetails, err + } + + // Get digest. + imageManifest, err := r.ImageManifest(image, token) + if err != nil { + if serviceError, ok := err.(restful.ServiceError); ok { + return failedImageDetails, serviceError + } + return failedImageDetails, err + } + + image.Digest = imageManifest.ManifestConfig.Digest + + // Get blob. + imageBlob, err := r.ImageBlob(image, token) + if err != nil { + return failedImageDetails, err + } + + return ImageDetails{ + Status: StatusSuccess, + ImageManifest: imageManifest, + ImageBlob: imageBlob, + ImageTag: image.Tag, + Registry: image.Domain, + }, nil } func getDockerEntryFromDockerSecret(instance *corev1.Secret) (dockerConfigEntry *DockerConfigEntry, err error) { @@ -117,9 +187,9 @@ func getDockerEntryFromDockerSecret(instance *corev1.Secret) (dockerConfigEntry if len(dockerConfig.Auths) == 0 { return nil, fmt.Errorf("docker config auth len should not be 0") } - for registryAddress, dockerConfigEntry := range dockerConfig.Auths { - dockerConfigEntry.ServerAddress = registryAddress - return &dockerConfigEntry, nil + for registryAddress, dce := range dockerConfig.Auths { + dce.ServerAddress = registryAddress + return &dce, nil } return nil, nil } diff --git a/pkg/models/resources/deployments.go b/pkg/models/resources/deployments.go deleted file mode 100644 index 5980c6d70..000000000 --- a/pkg/models/resources/deployments.go +++ /dev/null @@ -1,167 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package resources - -import ( - "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" - "kubesphere.io/kubesphere/pkg/server/params" - "kubesphere.io/kubesphere/pkg/utils/sliceutil" - "sort" - "strings" - "time" - - "k8s.io/apimachinery/pkg/labels" - - "k8s.io/api/apps/v1" -) - -type deploymentSearcher struct { -} - -func (*deploymentSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).Get(name) -} - -func deploymentStatus(item *v1.Deployment) string { - if item.Spec.Replicas != nil { - if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 { - return StatusStopped - } else if item.Status.ReadyReplicas == *item.Spec.Replicas { - return StatusRunning - } else { - return StatusUpdating - } - } - return StatusStopped -} - -// Exactly Match -func (*deploymentSearcher) match(match map[string]string, item *v1.Deployment) bool { - for k, v := range match { - switch k { - case Status: - if deploymentStatus(item) != v { - return false - } - case Name: - names := strings.Split(v, "|") - if !sliceutil.HasString(names, item.Name) { - return false - } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { - return false - } - default: - // label not exist or value not equal - if val, ok := item.Labels[k]; !ok || val != v { - return false - } - } - } - return true -} - -func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) bool { - - for k, v := range fuzzy { - switch k { - case Name: - if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { - return false - } - case Label: - if !searchFuzzy(item.Labels, "", v) { - return false - } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { - return false - } - return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } - default: - if !searchFuzzy(item.Labels, k, v) { - return false - } - } - } - - return true -} - -func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool { - switch orderBy { - case CreateTime: - return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case UpdateTime: - return s.lastUpdateTime(a).Before(s.lastUpdateTime(b)) - case Name: - fallthrough - default: - return strings.Compare(a.Name, b.Name) <= 0 - } -} - -func (s *deploymentSearcher) lastUpdateTime(deployment *v1.Deployment) time.Time { - lastUpdateTime := deployment.CreationTimestamp.Time - for _, condition := range deployment.Status.Conditions { - if condition.LastUpdateTime.After(lastUpdateTime) { - lastUpdateTime = condition.LastUpdateTime.Time - } - } - return lastUpdateTime -} - -func (s *deploymentSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - deployments, err := informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything()) - - if err != nil { - return nil, err - } - - result := make([]*v1.Deployment, 0) - - if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 { - result = deployments - } else { - for _, item := range deployments { - if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) { - result = append(result, item) - } - } - } - sort.Slice(result, func(i, j int) bool { - if reverse { - tmp := i - i = j - j = tmp - } - return s.compare(result[i], result[j], orderBy) - }) - - r := make([]interface{}, 0) - for _, i := range result { - r = append(r, i) - } - return r, nil -} diff --git a/pkg/models/resources/extraannotations.go b/pkg/models/resources/extraannotations.go deleted file mode 100644 index 711c6602d..000000000 --- a/pkg/models/resources/extraannotations.go +++ /dev/null @@ -1,120 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package resources - -import ( - corev1 "k8s.io/api/core/v1" - storagev1 "k8s.io/api/storage/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/informers" - "strconv" -) - -type extraAnnotationInjector struct { -} - -func (i extraAnnotationInjector) addExtraAnnotations(item interface{}) interface{} { - - switch item.(type) { - case *corev1.PersistentVolumeClaim: - return i.injectPersistentVolumeClaim(item.(*corev1.PersistentVolumeClaim)) - case *storagev1.StorageClass: - return i.injectStorageClass(item.(*storagev1.StorageClass)) - } - - return item -} - -func (i extraAnnotationInjector) injectStorageClass(item *storagev1.StorageClass) *storagev1.StorageClass { - - count, err := countPvcByStorageClass(item.Name) - - if err != nil { - klog.Errorf("inject annotation failed %+v", err) - return item - } - - item = item.DeepCopy() - - if item.Annotations == nil { - item.Annotations = make(map[string]string, 0) - } - - item.Annotations["kubesphere.io/pvc-count"] = strconv.Itoa(count) - - return item -} - -func (i extraAnnotationInjector) injectPersistentVolumeClaim(item *corev1.PersistentVolumeClaim) *corev1.PersistentVolumeClaim { - podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister() - pods, err := podLister.Pods(item.Namespace).List(labels.Everything()) - if err != nil { - klog.Errorf("inject annotation failed %+v", err) - return item - } - - item = item.DeepCopy() - - if item.Annotations == nil { - item.Annotations = make(map[string]string, 0) - } - - if isPvcInUse(pods, item.Name) { - item.Annotations["kubesphere.io/in-use"] = "true" - } else { - item.Annotations["kubesphere.io/in-use"] = "false" - } - - return item -} - -func isPvcInUse(pods []*corev1.Pod, pvcName string) bool { - for _, pod := range pods { - volumes := pod.Spec.Volumes - for _, volume := range volumes { - pvc := volume.PersistentVolumeClaim - if pvc != nil && pvc.ClaimName == pvcName { - return true - } - } - } - return false -} - -func countPvcByStorageClass(scName string) (int, error) { - persistentVolumeClaimLister := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister() - all, err := persistentVolumeClaimLister.List(labels.Everything()) - - if err != nil { - return 0, err - } - - count := 0 - - for _, item := range all { - if item.Spec.StorageClassName != nil { - if *item.Spec.StorageClassName == scName { - count++ - } - } else if item.GetAnnotations()[corev1.BetaStorageClassAnnotation] == scName { - count++ - } - } - return count, nil -} diff --git a/pkg/models/resources/resources.go b/pkg/models/resources/resources.go deleted file mode 100644 index d23fffd5b..000000000 --- a/pkg/models/resources/resources.go +++ /dev/null @@ -1,186 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package resources - -import ( - "fmt" - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/models" - "kubesphere.io/kubesphere/pkg/server/params" - "kubesphere.io/kubesphere/pkg/utils/sliceutil" - "strings" -) - -func init() { - resources[ConfigMaps] = &configMapSearcher{} - resources[CronJobs] = &cronJobSearcher{} - resources[DaemonSets] = &daemonSetSearcher{} - resources[Deployments] = &deploymentSearcher{} - resources[Ingresses] = &ingressSearcher{} - resources[Jobs] = &jobSearcher{} - resources[PersistentVolumeClaims] = &persistentVolumeClaimSearcher{} - resources[Secrets] = &secretSearcher{} - resources[Services] = &serviceSearcher{} - resources[StatefulSets] = &statefulSetSearcher{} - resources[Pods] = &podSearcher{} - resources[Roles] = &roleSearcher{} - resources[S2iBuilders] = &s2iBuilderSearcher{} - resources[S2iRuns] = &s2iRunSearcher{} - resources[HorizontalPodAutoscalers] = &hpaSearcher{} - resources[Applications] = &appSearcher{} - - resources[Nodes] = &nodeSearcher{} - resources[Namespaces] = &namespaceSearcher{} - resources[ClusterRoles] = &clusterRoleSearcher{} - resources[StorageClasses] = &storageClassesSearcher{} - resources[S2iBuilderTemplates] = &s2iBuilderTemplateSearcher{} - resources[Workspaces] = &workspaceSearcher{} -} - -var ( - injector = extraAnnotationInjector{} - resources = make(map[string]resourceSearchInterface) - clusterResources = []string{Nodes, Workspaces, Namespaces, ClusterRoles, StorageClasses, S2iBuilderTemplates} -) - -const ( - Name = "name" - Label = "label" - OwnerKind = "ownerKind" - OwnerName = "ownerName" - TargetKind = "targetKind" - TargetName = "targetName" - Role = "role" - CreateTime = "createTime" - UpdateTime = "updateTime" - StartTime = "startTime" - LastScheduleTime = "lastScheduleTime" - chart = "chart" - release = "release" - annotation = "annotation" - Keyword = "keyword" - UserFacing = "userfacing" - Status = "status" - includeCronJob = "includeCronJob" - storageClassName = "storageClassName" - cronJobKind = "CronJob" - s2iRunKind = "S2iRun" - includeS2iRun = "includeS2iRun" - StatusRunning = "running" - StatusPaused = "paused" - StatusPending = "pending" - StatusUpdating = "updating" - StatusStopped = "stopped" - StatusFailed = "failed" - StatusBound = "bound" - StatusLost = "lost" - StatusComplete = "complete" - StatusWarning = "warning" - StatusUnschedulable = "unschedulable" - app = "app" - Deployments = "deployments" - DaemonSets = "daemonsets" - Roles = "roles" - Workspaces = "workspaces" - WorkspaceRoles = "workspaceroles" - CronJobs = "cronjobs" - ConfigMaps = "configmaps" - Ingresses = "ingresses" - Jobs = "jobs" - PersistentVolumeClaims = "persistentvolumeclaims" - Pods = "pods" - Secrets = "secrets" - Services = "services" - StatefulSets = "statefulsets" - HorizontalPodAutoscalers = "horizontalpodautoscalers" - Applications = "applications" - Nodes = "nodes" - Namespaces = "namespaces" - StorageClasses = "storageclasses" - ClusterRoles = "clusterroles" - S2iBuilderTemplates = "s2ibuildertemplates" - S2iBuilders = "s2ibuilders" - S2iRuns = "s2iruns" -) - -type resourceSearchInterface interface { - get(namespace, name string) (interface{}, error) - search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) -} - -func GetResource(namespace, resource, name string) (interface{}, error) { - if searcher, ok := resources[resource]; ok { - resource, err := searcher.get(namespace, name) - if err != nil { - klog.Errorf("resource %s.%s.%s not found: %s", namespace, resource, name, err) - return nil, err - } - return resource, nil - } - return nil, fmt.Errorf("resource %s.%s.%s not found", namespace, resource, name) -} - -func ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { - items := make([]interface{}, 0) - var err error - var result []interface{} - - // none namespace resource - if namespace != "" && sliceutil.HasString(clusterResources, resource) { - err = fmt.Errorf("namespaced resource %s not found", resource) - klog.Errorln(err) - return nil, err - } - - if searcher, ok := resources[resource]; ok { - result, err = searcher.search(namespace, conditions, orderBy, reverse) - } else { - err = fmt.Errorf("namespaced resource %s not found", resource) - klog.Errorln(err) - return nil, err - } - - if err != nil { - klog.Errorln(err) - return nil, err - } - - if limit == -1 || limit+offset > len(result) { - limit = len(result) - offset - } - - result = result[offset : offset+limit] - for _, item := range result { - items = append(items, injector.addExtraAnnotations(item)) - } - - return &models.PageableResponse{TotalCount: len(result), Items: items}, nil -} - -func searchFuzzy(m map[string]string, key, value string) bool { - - val, exist := m[key] - - if value == "" && (!exist || val == "") { - return true - } else if value != "" && strings.Contains(val, value) { - return true - } - - return false -} diff --git a/pkg/models/resources/appplications.go b/pkg/models/resources/v1alpha2/application/appplications.go similarity index 67% rename from pkg/models/resources/appplications.go rename to pkg/models/resources/v1alpha2/application/appplications.go index 53bad8c38..de6adaed2 100644 --- a/pkg/models/resources/appplications.go +++ b/pkg/models/resources/v1alpha2/application/appplications.go @@ -16,37 +16,49 @@ * / */ -package resources +package application import ( "github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1" + "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions" "k8s.io/apimachinery/pkg/labels" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" "strings" ) +const ( + app = "app" + chart = "chart" + release = "release" +) + type appSearcher struct { + informer externalversions.SharedInformerFactory } -func (*appSearcher) get(namespace, name string) (interface{}, error) { - return informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).Get(name) +func NewApplicationSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface { + return &appSearcher{informer: informers} +} + +func (s *appSearcher) Get(namespace, name string) (interface{}, error) { + return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name) } // exactly Match -func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bool { +func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,16 +75,16 @@ func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bo func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false @@ -81,7 +93,7 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,17 +103,17 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *appSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - apps, err := informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything()) +func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/clusterroles.go b/pkg/models/resources/v1alpha2/clusterrole/clusterroles.go similarity index 71% rename from pkg/models/resources/clusterroles.go rename to pkg/models/resources/v1alpha2/clusterrole/clusterroles.go index e0dfac238..7af194d9d 100644 --- a/pkg/models/resources/clusterroles.go +++ b/pkg/models/resources/v1alpha2/clusterrole/clusterroles.go @@ -15,11 +15,12 @@ limitations under the License. */ -package resources +package clusterrole import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil" @@ -31,34 +32,39 @@ import ( ) type clusterRoleSearcher struct { + informer informers.SharedInformerFactory } -func (*clusterRoleSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().Get(name) +func NewClusterRoleSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface { + return &clusterRoleSearcher{informer: informer} +} + +func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) { + return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name) } // exactly Match func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool { for k, v := range match { switch k { - case OwnerKind: + case v1alpha2.OwnerKind: fallthrough - case OwnerName: - kind := match[OwnerKind] - name := match[OwnerName] + case v1alpha2.OwnerName: + kind := match[v1alpha2.OwnerKind] + name := match[v1alpha2.OwnerName] if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) { return false } - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } - case UserFacing: + case v1alpha2.UserFacing: if v == "true" { if !isUserFacingClusterRole(item) { return false @@ -78,21 +84,21 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -102,17 +108,17 @@ func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRol func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *clusterRoleSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - clusterRoles, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().List(labels.Everything()) +func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/configmaps.go b/pkg/models/resources/v1alpha2/configmap/configmaps.go similarity index 67% rename from pkg/models/resources/configmaps.go rename to pkg/models/resources/v1alpha2/configmap/configmaps.go index 312d989ab..8ee068061 100644 --- a/pkg/models/resources/configmaps.go +++ b/pkg/models/resources/v1alpha2/configmap/configmaps.go @@ -15,11 +15,12 @@ limitations under the License. */ -package resources +package configmap import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +31,28 @@ import ( ) type configMapSearcher struct { + informer informers.SharedInformerFactory } -func (*configMapSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name) +func NewConfigmapSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &configMapSearcher{informer: informers} +} + +func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) { + return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name) } // exactly Match func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,25 +69,25 @@ func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) boo func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,17 +97,17 @@ func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) boo func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *configMapSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - configMaps, err := informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything()) +func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything()) if err != nil { return nil, err @@ -120,9 +126,7 @@ func (s *configMapSearcher) search(namespace string, conditions *params.Conditio } sort.Slice(result, func(i, j int) bool { if reverse { - tmp := i - i = j - j = tmp + i, j = j, i } return s.compare(result[i], result[j], orderBy) }) diff --git a/pkg/models/resources/cronjobs.go b/pkg/models/resources/v1alpha2/cronjob/cronjobs.go similarity index 65% rename from pkg/models/resources/cronjobs.go rename to pkg/models/resources/v1alpha2/cronjob/cronjobs.go index 8a61a776b..3392cdf6c 100644 --- a/pkg/models/resources/cronjobs.go +++ b/pkg/models/resources/v1alpha2/cronjob/cronjobs.go @@ -15,11 +15,12 @@ limitations under the License. */ -package resources +package cronjob import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -31,34 +32,39 @@ import ( ) type cronJobSearcher struct { + informer informers.SharedInformerFactory } -func (*cronJobSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).Get(name) +func NewCronJobSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface { + return &cronJobSearcher{informer: informer} +} + +func (c *cronJobSearcher) Get(namespace, name string) (interface{}, error) { + return c.informer.Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).Get(name) } func cronJobStatus(item *v1beta1.CronJob) string { if item.Spec.Suspend != nil && *item.Spec.Suspend { - return StatusPaused + return v1alpha2.StatusPaused } - return StatusRunning + return v1alpha2.StatusRunning } // Exactly Match func (*cronJobSearcher) match(match map[string]string, item *v1beta1.CronJob) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Status: + case v1alpha2.Status: if cronJobStatus(item) != v { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -75,25 +81,25 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -104,7 +110,7 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool { switch orderBy { - case LastScheduleTime: + case v1alpha2.LastScheduleTime: if a.Status.LastScheduleTime == nil { return true } @@ -112,17 +118,17 @@ func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool { return false } return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime) - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) default: fallthrough - case Name: + case v1alpha2.Name: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *cronJobSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - cronJobs, err := informers.SharedInformerFactory().Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).List(labels.Everything()) +func (c *cronJobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + cronJobs, err := c.informer.Batch().V1beta1().CronJobs().Lister().CronJobs(namespace).List(labels.Everything()) if err != nil { return nil, err @@ -134,18 +140,16 @@ func (s *cronJobSearcher) search(namespace string, conditions *params.Conditions result = cronJobs } else { for _, item := range cronJobs { - if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) { + if c.match(conditions.Match, item) && c.fuzzy(conditions.Fuzzy, item) { result = append(result, item) } } } sort.Slice(result, func(i, j int) bool { if reverse { - tmp := i - i = j - j = tmp + i, j = j, i } - return s.compare(result[i], result[j], orderBy) + return c.compare(result[i], result[j], orderBy) }) r := make([]interface{}, 0) diff --git a/pkg/models/resources/daemonsets.go b/pkg/models/resources/v1alpha2/daemonset/daemonsets.go similarity index 64% rename from pkg/models/resources/daemonsets.go rename to pkg/models/resources/v1alpha2/daemonset/daemonsets.go index 9ae1eeef4..5f5f585ba 100644 --- a/pkg/models/resources/daemonsets.go +++ b/pkg/models/resources/v1alpha2/daemonset/daemonsets.go @@ -15,11 +15,12 @@ limitations under the License. */ -package resources +package daemonset import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,19 +31,24 @@ import ( ) type daemonSetSearcher struct { + informer informers.SharedInformerFactory } -func (*daemonSetSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name) +func NewDaemonSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &daemonSetSearcher{informer: informers} +} + +func (c *daemonSetSearcher) Get(namespace, name string) (interface{}, error) { + return c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name) } func daemonSetStatus(item *v1.DaemonSet) string { if item.Status.NumberAvailable == 0 { - return StatusStopped + return v1alpha2.StatusStopped } else if item.Status.DesiredNumberScheduled == item.Status.NumberAvailable { - return StatusRunning + return v1alpha2.StatusRunning } else { - return StatusUpdating + return v1alpha2.StatusUpdating } } @@ -50,17 +56,17 @@ func daemonSetStatus(item *v1.DaemonSet) string { func (*daemonSetSearcher) match(match map[string]string, item *v1.DaemonSet) bool { for k, v := range match { switch k { - case Status: + case v1alpha2.Status: if daemonSetStatus(item) != v { return false } - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -77,25 +83,25 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -106,17 +112,17 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo func (*daemonSetSearcher) compare(a, b *v1.DaemonSet, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *daemonSetSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - daemonSets, err := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything()) +func (c *daemonSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + daemonSets, err := c.informer.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).List(labels.Everything()) if err != nil { return nil, err @@ -128,18 +134,16 @@ func (s *daemonSetSearcher) search(namespace string, conditions *params.Conditio result = daemonSets } else { for _, item := range daemonSets { - if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) { + if c.match(conditions.Match, item) && c.fuzzy(conditions.Fuzzy, item) { result = append(result, item) } } } sort.Slice(result, func(i, j int) bool { if reverse { - tmp := i - i = j - j = tmp + i, j = j, i } - return s.compare(result[i], result[j], orderBy) + return c.compare(result[i], result[j], orderBy) }) r := make([]interface{}, 0) diff --git a/pkg/models/resources/horizontalpodautoscalers.go b/pkg/models/resources/v1alpha2/hpa/horizontalpodautoscalers.go similarity index 66% rename from pkg/models/resources/horizontalpodautoscalers.go rename to pkg/models/resources/v1alpha2/hpa/horizontalpodautoscalers.go index 1b64656d2..f1010cd76 100644 --- a/pkg/models/resources/horizontalpodautoscalers.go +++ b/pkg/models/resources/v1alpha2/hpa/horizontalpodautoscalers.go @@ -15,12 +15,13 @@ * limitations under the License. * / */ -package resources +package hpa import ( autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,10 +31,15 @@ import ( ) type hpaSearcher struct { + informers informers.SharedInformerFactory } -func (*hpaSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).Get(name) +func NewHpaSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &hpaSearcher{informers: informers} +} + +func (s *hpaSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).Get(name) } func hpaTargetMatch(item *autoscalingv2beta2.HorizontalPodAutoscaler, kind, name string) bool { @@ -44,21 +50,21 @@ func hpaTargetMatch(item *autoscalingv2beta2.HorizontalPodAutoscaler, kind, name func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool { for k, v := range match { switch k { - case TargetKind: + case v1alpha2.TargetKind: fallthrough - case TargetName: - kind := match[TargetKind] - name := match[TargetName] + case v1alpha2.TargetName: + kind := match[v1alpha2.TargetKind] + name := match[v1alpha2.TargetName] if !hpaTargetMatch(item, kind, name) { return false } - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -74,25 +80,25 @@ func (*hpaSearcher) match(match map[string]string, item *autoscalingv2beta2.Hori func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.HorizontalPodAutoscaler) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) && !searchFuzzy(item.Annotations, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) && !v1alpha2.SearchFuzzy(item.Annotations, k, v) { return false } } @@ -102,18 +108,18 @@ func (*hpaSearcher) fuzzy(fuzzy map[string]string, item *autoscalingv2beta2.Hori func (*hpaSearcher) compare(a, b *autoscalingv2beta2.HorizontalPodAutoscaler, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *hpaSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { +func (s *hpaSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - horizontalPodAutoscalers, err := informers.SharedInformerFactory().Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything()) + horizontalPodAutoscalers, err := s.informers.Autoscaling().V2beta2().HorizontalPodAutoscalers().Lister().HorizontalPodAutoscalers(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/ingresses.go b/pkg/models/resources/v1alpha2/ingress/ingresses.go similarity index 59% rename from pkg/models/resources/ingresses.go rename to pkg/models/resources/v1alpha2/ingress/ingresses.go index 28ba94279..387e5d0b7 100644 --- a/pkg/models/resources/ingresses.go +++ b/pkg/models/resources/v1alpha2/ingress/ingresses.go @@ -15,39 +15,45 @@ limitations under the License. */ -package resources +package ingress import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" "strings" - extensions "k8s.io/api/extensions/v1beta1" + "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/labels" ) type ingressSearcher struct { + informers informers.SharedInformerFactory } -func (*ingressSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name) +func NewIngressSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &ingressSearcher{informers: informers} +} + +func (s *ingressSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name) } // exactly Match -func (*ingressSearcher) match(match map[string]string, item *extensions.Ingress) bool { +func (*ingressSearcher) match(match map[string]string, item *v1beta1.Ingress) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -61,28 +67,28 @@ func (*ingressSearcher) match(match map[string]string, item *extensions.Ingress) } // Fuzzy searchInNamespace -func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress) bool { +func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Ingress) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -90,25 +96,25 @@ func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress) return true } -func (*ingressSearcher) compare(a, b *extensions.Ingress, orderBy string) bool { +func (*ingressSearcher) compare(a, b *v1beta1.Ingress, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *ingressSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - ingresses, err := informers.SharedInformerFactory().Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything()) +func (s *ingressSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + ingresses, err := s.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything()) if err != nil { return nil, err } - result := make([]*extensions.Ingress, 0) + result := make([]*v1beta1.Ingress, 0) if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 { result = ingresses diff --git a/pkg/models/resources/v1alpha2/interface.go b/pkg/models/resources/v1alpha2/interface.go new file mode 100644 index 000000000..acf5f5f32 --- /dev/null +++ b/pkg/models/resources/v1alpha2/interface.go @@ -0,0 +1,80 @@ +package v1alpha2 + +import ( + "kubesphere.io/kubesphere/pkg/server/params" + "strings" +) + +const ( + App = "app" + Chart = "chart" + Release = "release" + Name = "name" + Label = "label" + OwnerKind = "ownerKind" + OwnerName = "ownerName" + TargetKind = "targetKind" + TargetName = "targetName" + Role = "role" + CreateTime = "createTime" + UpdateTime = "updateTime" + StartTime = "startTime" + LastScheduleTime = "lastScheduleTime" + Annotation = "Annotation" + Keyword = "keyword" + UserFacing = "userfacing" + Status = "status" + + StatusRunning = "running" + StatusPaused = "paused" + StatusPending = "pending" + StatusUpdating = "updating" + StatusStopped = "stopped" + StatusFailed = "failed" + StatusBound = "bound" + StatusLost = "lost" + StatusComplete = "complete" + StatusWarning = "warning" + StatusUnschedulable = "unschedulable" + Deployments = "deployments" + DaemonSets = "daemonsets" + Roles = "roles" + Workspaces = "workspaces" + WorkspaceRoles = "workspaceroles" + CronJobs = "cronjobs" + ConfigMaps = "configmaps" + Ingresses = "ingresses" + Jobs = "jobs" + PersistentVolumeClaims = "persistentvolumeclaims" + Pods = "pods" + Secrets = "secrets" + Services = "services" + StatefulSets = "statefulsets" + HorizontalPodAutoscalers = "horizontalpodautoscalers" + Applications = "applications" + Nodes = "nodes" + Namespaces = "namespaces" + StorageClasses = "storageclasses" + ClusterRoles = "clusterroles" + S2iBuilderTemplates = "s2ibuildertemplates" + S2iBuilders = "s2ibuilders" + S2iRuns = "s2iruns" +) + +type Interface interface { + Get(namespace, name string) (interface{}, error) + Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) +} + +func SearchFuzzy(m map[string]string, key, value string) bool { + + val, exist := m[key] + + if value == "" && (!exist || val == "") { + return true + } else if value != "" && strings.Contains(val, value) { + return true + } + + return false +} diff --git a/pkg/models/resources/jobs.go b/pkg/models/resources/v1alpha2/job/jobs.go similarity index 69% rename from pkg/models/resources/jobs.go rename to pkg/models/resources/v1alpha2/job/jobs.go index d9585f20c..509d3e2ae 100644 --- a/pkg/models/resources/jobs.go +++ b/pkg/models/resources/v1alpha2/job/jobs.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package job import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil" @@ -31,21 +33,33 @@ import ( "k8s.io/apimachinery/pkg/labels" ) +const ( + includeCronJob = "includeCronJob" + cronJobKind = "CronJob" + s2iRunKind = "S2iRun" + includeS2iRun = "includeS2iRun" +) + type jobSearcher struct { + informers informers.SharedInformerFactory } -func (*jobSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Batch().V1().Jobs().Lister().Jobs(namespace).Get(name) +func NewJobSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &jobSearcher{informers: informers} +} + +func (s *jobSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).Get(name) } func jobStatus(item *batchv1.Job) string { - status := StatusFailed + status := v1alpha2.StatusFailed if item.Status.Active > 0 { - status = StatusRunning + status = v1alpha2.StatusRunning } else if item.Status.Failed > 0 { - status = StatusFailed + status = v1alpha2.StatusFailed } else if item.Status.Succeeded > 0 { - status = StatusComplete + status = v1alpha2.StatusComplete } return status } @@ -54,7 +68,7 @@ func jobStatus(item *batchv1.Job) string { func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool { for k, v := range match { switch k { - case Status: + case v1alpha2.Status: if jobStatus(item) != v { return false } @@ -66,13 +80,13 @@ func (*jobSearcher) match(match map[string]string, item *batchv1.Job) bool { if v == "false" && k8sutil.IsControlledBy(item.OwnerReferences, s2iRunKind, "") { return false } - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -89,25 +103,25 @@ func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -131,19 +145,19 @@ func jobUpdateTime(item *batchv1.Job) time.Time { func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case UpdateTime: + case v1alpha2.UpdateTime: return jobUpdateTime(a).Before(jobUpdateTime(b)) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *jobSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - jobs, err := informers.SharedInformerFactory().Batch().V1().Jobs().Lister().Jobs(namespace).List(labels.Everything()) +func (s *jobSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + jobs, err := s.informers.Batch().V1().Jobs().Lister().Jobs(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/namespaces.go b/pkg/models/resources/v1alpha2/namespace/namespaces.go similarity index 70% rename from pkg/models/resources/namespaces.go rename to pkg/models/resources/v1alpha2/namespace/namespaces.go index 1ba4e8670..ff206df26 100644 --- a/pkg/models/resources/namespaces.go +++ b/pkg/models/resources/v1alpha2/namespace/namespaces.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package namespace import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type namespaceSearcher struct { + informers informers.SharedInformerFactory } -func (*namespaceSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().Namespaces().Lister().Get(name) +func NewNamespaceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &namespaceSearcher{informers: informers} +} + +func (s *namespaceSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Core().V1().Namespaces().Lister().Get(name) } // exactly Match func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,25 +70,21 @@ func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) boo func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,17 +94,17 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *namespaceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - namespaces, err := informers.SharedInformerFactory().Core().V1().Namespaces().Lister().List(labels.Everything()) +func (s *namespaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + namespaces, err := s.informers.Core().V1().Namespaces().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/nodes.go b/pkg/models/resources/v1alpha2/node/nodes.go similarity index 69% rename from pkg/models/resources/nodes.go rename to pkg/models/resources/v1alpha2/node/nodes.go index 0a2e02fbe..fff798e77 100644 --- a/pkg/models/resources/nodes.go +++ b/pkg/models/resources/v1alpha2/node/nodes.go @@ -15,12 +15,14 @@ limitations under the License. */ -package resources +package node import ( "fmt" + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,40 +32,47 @@ import ( "k8s.io/apimachinery/pkg/labels" ) +const ( + nodeConfigOK v1.NodeConditionType = "ConfigOK" + nodeKubeletReady v1.NodeConditionType = "KubeletReady" +) + type nodeSearcher struct { + informers informers.SharedInformerFactory } -func (*nodeSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().Nodes().Lister().Get(name) +func NewNodeSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &nodeSearcher{informers: informers} +} + +func (s *nodeSearcher) Get(_, name string) (interface{}, error) { + return s.informers.Core().V1().Nodes().Lister().Get(name) } func getNodeStatus(node *v1.Node) string { if node.Spec.Unschedulable { - return StatusUnschedulable + return v1alpha2.StatusUnschedulable } for _, condition := range node.Status.Conditions { - if isUnhealthStatus(condition) { - return StatusWarning + if isUnhealthyStatus(condition) { + return v1alpha2.StatusWarning } } - return StatusRunning + return v1alpha2.StatusRunning } -const NodeConfigOK v1.NodeConditionType = "ConfigOK" -const NodeKubeletReady v1.NodeConditionType = "KubeletReady" - var expectedConditions = map[v1.NodeConditionType]v1.ConditionStatus{ v1.NodeMemoryPressure: v1.ConditionFalse, v1.NodeDiskPressure: v1.ConditionFalse, v1.NodePIDPressure: v1.ConditionFalse, v1.NodeNetworkUnavailable: v1.ConditionFalse, - NodeConfigOK: v1.ConditionTrue, - NodeKubeletReady: v1.ConditionTrue, + nodeConfigOK: v1.ConditionTrue, + nodeKubeletReady: v1.ConditionTrue, v1.NodeReady: v1.ConditionTrue, } -func isUnhealthStatus(condition v1.NodeCondition) bool { +func isUnhealthyStatus(condition v1.NodeCondition) bool { expectedStatus := expectedConditions[condition.Type] if expectedStatus != "" && condition.Status != expectedStatus { return true @@ -75,22 +84,22 @@ func isUnhealthStatus(condition v1.NodeCondition) bool { func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Role: + case v1alpha2.Role: labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v) if _, ok := item.Labels[labelKey]; !ok { return false } - case Status: + case v1alpha2.Status: if getNodeStatus(item) != v { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -107,25 +116,21 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool { func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -135,17 +140,17 @@ func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool { func (*nodeSearcher) compare(a, b *v1.Node, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *nodeSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - nodes, err := informers.SharedInformerFactory().Core().V1().Nodes().Lister().List(labels.Everything()) +func (s *nodeSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + nodes, err := s.informers.Core().V1().Nodes().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/persistentvolumeclaims.go b/pkg/models/resources/v1alpha2/persistentvolumeclaim/persistentvolumeclaims.go similarity index 59% rename from pkg/models/resources/persistentvolumeclaims.go rename to pkg/models/resources/v1alpha2/persistentvolumeclaim/persistentvolumeclaims.go index bdbdeaec2..df6704092 100644 --- a/pkg/models/resources/persistentvolumeclaims.go +++ b/pkg/models/resources/v1alpha2/persistentvolumeclaim/persistentvolumeclaims.go @@ -15,11 +15,14 @@ limitations under the License. */ -package resources +package persistentvolumeclaim import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "strconv" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -29,21 +32,30 @@ import ( "k8s.io/apimachinery/pkg/labels" ) +const ( + storageClassName = "storageClassName" +) + type persistentVolumeClaimSearcher struct { + informers informers.SharedInformerFactory } -func (*persistentVolumeClaimSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name) +func NewPersistentVolumeClaimSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &persistentVolumeClaimSearcher{informers: informers} +} + +func (s *persistentVolumeClaimSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name) } func pvcStatus(item *v1.PersistentVolumeClaim) string { - status := StatusPending + status := v1alpha2.StatusPending if item.Status.Phase == v1.ClaimPending { - status = StatusPending + status = v1alpha2.StatusPending } else if item.Status.Phase == v1.ClaimBound { - status = StatusBound + status = v1alpha2.StatusBound } else if item.Status.Phase == v1.ClaimLost { - status = StatusLost + status = v1alpha2.StatusLost } return status } @@ -52,12 +64,12 @@ func pvcStatus(item *v1.PersistentVolumeClaim) string { func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.PersistentVolumeClaim) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Status: + case v1alpha2.Status: statuses := strings.Split(v, "|") if !sliceutil.HasString(statuses, pvcStatus(item)) { return false @@ -66,8 +78,8 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe if item.Spec.StorageClassName == nil || *item.Spec.StorageClassName != v { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -84,25 +96,25 @@ func (*persistentVolumeClaimSearcher) match(match map[string]string, item *v1.Pe func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.PersistentVolumeClaim) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -112,17 +124,17 @@ func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.Pe func (*persistentVolumeClaimSearcher) compare(a, b *v1.PersistentVolumeClaim, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *persistentVolumeClaimSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - persistentVolumeClaims, err := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything()) +func (s *persistentVolumeClaimSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + persistentVolumeClaims, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(labels.Everything()) if err != nil { return nil, err @@ -150,7 +162,29 @@ func (s *persistentVolumeClaimSearcher) search(namespace string, conditions *par r := make([]interface{}, 0) for _, i := range result { + inUse := s.countPods(i.Name, i.Namespace) + if i.Annotations == nil { + i.Annotations = make(map[string]string) + } + i.Annotations["kubesphere.io/in-use"] = strconv.FormatBool(inUse) + r = append(r, i) } return r, nil } + +func (s *persistentVolumeClaimSearcher) countPods(name, namespace string) bool { + pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything()) + if err != nil { + return false + } + for _, pod := range pods { + for _, pvc := range pod.Spec.Volumes { + if pvc.PersistentVolumeClaim != nil && pvc.PersistentVolumeClaim.ClaimName == name { + return true + } + } + } + + return false +} diff --git a/pkg/models/resources/pods.go b/pkg/models/resources/v1alpha2/pod/pods.go similarity index 71% rename from pkg/models/resources/pods.go rename to pkg/models/resources/v1alpha2/pod/pods.go index 8652ca00a..3ee226595 100644 --- a/pkg/models/resources/pods.go +++ b/pkg/models/resources/v1alpha2/pod/pods.go @@ -15,12 +15,14 @@ limitations under the License. */ -package resources +package pod import ( appsv1 "k8s.io/api/apps/v1" + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -31,16 +33,21 @@ import ( ) type podSearcher struct { + informers informers.SharedInformerFactory } -func (*podSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().Pods().Lister().Pods(namespace).Get(name) +func NewPodSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &podSearcher{informers: informers} } -func podBelongTo(item *v1.Pod, kind string, name string) bool { +func (s *podSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Core().V1().Pods().Lister().Pods(namespace).Get(name) +} + +func (s *podSearcher) podBelongTo(item *v1.Pod, kind string, name string) bool { switch kind { case "Deployment": - if podBelongToDeployment(item, name) { + if s.podBelongToDeployment(item, name) { return true } case "ReplicaSet": @@ -108,8 +115,8 @@ func podBelongToStatefulSet(item *v1.Pod, statefulSetName string) bool { return false } -func podBelongToDeployment(item *v1.Pod, deploymentName string) bool { - replicas, err := informers.SharedInformerFactory().Apps().V1().ReplicaSets().Lister().ReplicaSets(item.Namespace).List(labels.Everything()) +func (s *podSearcher) podBelongToDeployment(item *v1.Pod, deploymentName string) bool { + replicas, err := s.informers.Apps().V1().ReplicaSets().Lister().ReplicaSets(item.Namespace).List(labels.Everything()) if err != nil { return false } @@ -133,8 +140,8 @@ func podBindPVC(item *v1.Pod, pvcName string) bool { return false } -func podBelongToService(item *v1.Pod, serviceName string) bool { - service, err := informers.SharedInformerFactory().Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName) +func (s *podSearcher) podBelongToService(item *v1.Pod, serviceName string) bool { + service, err := s.informers.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName) if err != nil { return false } @@ -147,15 +154,15 @@ func podBelongToService(item *v1.Pod, serviceName string) bool { } // exactly Match -func (*podSearcher) match(match map[string]string, item *v1.Pod) bool { +func (s *podSearcher) match(match map[string]string, item *v1.Pod) bool { for k, v := range match { switch k { - case OwnerKind: + case v1alpha2.OwnerKind: fallthrough - case OwnerName: - kind := match[OwnerKind] - name := match[OwnerName] - if !podBelongTo(item, kind, name) { + case v1alpha2.OwnerName: + kind := match[v1alpha2.OwnerKind] + name := match[v1alpha2.OwnerName] + if !s.podBelongTo(item, kind, name) { return false } case "nodeName": @@ -167,16 +174,16 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool { return false } case "serviceName": - if !podBelongToService(item, v) { + if !s.podBelongToService(item, v) { return false } - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -193,25 +200,25 @@ func (*podSearcher) match(match map[string]string, item *v1.Pod) bool { func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -221,7 +228,7 @@ func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool { func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool { switch orderBy { - case StartTime: + case v1alpha2.StartTime: if a.Status.StartTime == nil { return false } @@ -229,18 +236,18 @@ func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool { return true } return a.Status.StartTime.Before(b.Status.StartTime) - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *podSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { +func (s *podSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - pods, err := informers.SharedInformerFactory().Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything()) + pods, err := s.informers.Core().V1().Pods().Lister().Pods(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/v1alpha2/resource/resources.go b/pkg/models/resources/v1alpha2/resource/resources.go new file mode 100644 index 000000000..c767d9d85 --- /dev/null +++ b/pkg/models/resources/v1alpha2/resource/resources.go @@ -0,0 +1,137 @@ +/* + + Copyright 2019 The KubeSphere Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package resource + +import ( + "fmt" + "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/application" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/configmap" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/cronjob" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/daemonset" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/hpa" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/ingress" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/job" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/namespace" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/node" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/persistentvolumeclaim" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/pod" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2buildertemplate" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2ibuilder" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/s2irun" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/secret" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/service" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/statefulset" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/storageclass" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/workspace" + "kubesphere.io/kubesphere/pkg/server/params" + "kubesphere.io/kubesphere/pkg/utils/sliceutil" +) + +type ResourceGetter struct { + resourcesGetters map[string]v1alpha2.Interface +} + +func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter { + resourceGetters := make(map[string]v1alpha2.Interface) + + resourceGetters[v1alpha2.ConfigMaps] = configmap.NewConfigmapSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.CronJobs] = cronjob.NewCronJobSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.DaemonSets] = daemonset.NewDaemonSetSearcher(factory.KubernetesSharedInformerFactory()) + // resourceGetters[Deployments] = + resourceGetters[v1alpha2.Ingresses] = ingress.NewIngressSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Jobs] = job.NewJobSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.PersistentVolumeClaims] = persistentvolumeclaim.NewPersistentVolumeClaimSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Secrets] = secret.NewSecretSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Services] = service.NewServiceSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.StatefulSets] = statefulset.NewStatefulSetSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Pods] = pod.NewPodSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Roles] = role.NewRoleSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Nodes] = node.NewNodeSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.Namespaces] = namespace.NewNamespaceSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.ClusterRoles] = clusterrole.NewClusterRoleSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory()) + resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory()) + + resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.S2iSharedInformerFactory()) + resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.S2iSharedInformerFactory()) + resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.S2iSharedInformerFactory()) + + resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory()) + + resourceGetters[v1alpha2.Applications] = application.NewApplicationSearcher(factory.ApplicationSharedInformerFactory()) + + return &ResourceGetter{resourcesGetters: resourceGetters} + +} + +var ( + //injector = v1alpha2.extraAnnotationInjector{} + clusterResources = []string{v1alpha2.Nodes, v1alpha2.Workspaces, v1alpha2.Namespaces, v1alpha2.ClusterRoles, v1alpha2.StorageClasses, v1alpha2.S2iBuilderTemplates} +) + +func (r *ResourceGetter) GetResource(namespace, resource, name string) (interface{}, error) { + if searcher, ok := r.resourcesGetters[resource]; ok { + resource, err := searcher.Get(namespace, name) + if err != nil { + klog.Errorf("resource %s.%s.%s not found: %s", namespace, resource, name, err) + return nil, err + } + return resource, nil + } + return nil, fmt.Errorf("resource %s.%s.%s not found", namespace, resource, name) +} + +func (r *ResourceGetter) ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { + items := make([]interface{}, 0) + var err error + var result []interface{} + + // none namespace resource + if namespace != "" && sliceutil.HasString(clusterResources, resource) { + err = fmt.Errorf("namespaced resource %s not found", resource) + klog.Errorln(err) + return nil, err + } + + if searcher, ok := r.resourcesGetters[resource]; ok { + result, err = searcher.Search(namespace, conditions, orderBy, reverse) + } else { + err = fmt.Errorf("namespaced resource %s not found", resource) + klog.Errorln(err) + return nil, err + } + + if err != nil { + klog.Errorln(err) + return nil, err + } + + if limit == -1 || limit+offset > len(result) { + limit = len(result) - offset + } + + result = result[offset : offset+limit] + + return &models.PageableResponse{TotalCount: len(result), Items: items}, nil +} diff --git a/pkg/models/resources/roles.go b/pkg/models/resources/v1alpha2/role/roles.go similarity index 72% rename from pkg/models/resources/roles.go rename to pkg/models/resources/v1alpha2/role/roles.go index b08f30ef6..3f651a8ed 100644 --- a/pkg/models/resources/roles.go +++ b/pkg/models/resources/v1alpha2/role/roles.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package role import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,26 +32,31 @@ import ( ) type roleSearcher struct { + informers informers.SharedInformerFactory } -func (*roleSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Rbac().V1().Roles().Lister().Roles(namespace).Get(name) +func NewRoleSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &roleSearcher{informers: informers} +} + +func (s *roleSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Rbac().V1().Roles().Lister().Roles(namespace).Get(name) } // exactly Match func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } - case UserFacing: + case v1alpha2.UserFacing: if v == "true" { if !isUserFacingRole(item) { return false @@ -69,21 +76,21 @@ func (*roleSearcher) match(match map[string]string, item *rbac.Role) bool { func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -93,17 +100,17 @@ func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool { func (*roleSearcher) compare(a, b *rbac.Role, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *roleSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - roles, err := informers.SharedInformerFactory().Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything()) +func (s *roleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + roles, err := s.informers.Rbac().V1().Roles().Lister().Roles(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/s2ibuildertemplate.go b/pkg/models/resources/v1alpha2/s2buildertemplate/s2ibuildertemplate.go similarity index 69% rename from pkg/models/resources/s2ibuildertemplate.go rename to pkg/models/resources/v1alpha2/s2buildertemplate/s2ibuildertemplate.go index 03c6b469c..0b638ab3a 100644 --- a/pkg/models/resources/s2ibuildertemplate.go +++ b/pkg/models/resources/v1alpha2/s2buildertemplate/s2ibuildertemplate.go @@ -15,12 +15,14 @@ limitations under the License. */ -package resources +package s2buildertemplate import ( "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1" + "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type s2iBuilderTemplateSearcher struct { + informers externalversions.SharedInformerFactory } -func (*s2iBuilderTemplateSearcher) get(namespace, name string) (interface{}, error) { - return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name) +func NewS2iBuidlerTemplateSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface { + return &s2iBuilderTemplateSearcher{informers: informers} +} + +func (s *s2iBuilderTemplateSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().Get(name) } // exactly Match func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1.S2iBuilderTemplate) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,21 +70,21 @@ func (*s2iBuilderTemplateSearcher) match(match map[string]string, item *v1alpha1 func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilderTemplate) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -87,17 +94,17 @@ func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1 func (*s2iBuilderTemplateSearcher) compare(a, b *v1alpha1.S2iBuilderTemplate, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *s2iBuilderTemplateSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - builderTemplates, err := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything()) +func (s *s2iBuilderTemplateSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + builderTemplates, err := s.informers.Devops().V1alpha1().S2iBuilderTemplates().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/s2ibuilder.go b/pkg/models/resources/v1alpha2/s2ibuilder/s2ibuilder.go similarity index 69% rename from pkg/models/resources/s2ibuilder.go rename to pkg/models/resources/v1alpha2/s2ibuilder/s2ibuilder.go index 4710a6cdf..8b826c08f 100644 --- a/pkg/models/resources/s2ibuilder.go +++ b/pkg/models/resources/v1alpha2/s2ibuilder/s2ibuilder.go @@ -16,13 +16,15 @@ */ -package resources +package s2ibuilder import ( "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1" + "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions" "k8s.io/apimachinery/pkg/labels" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type s2iBuilderSearcher struct { + informers externalversions.SharedInformerFactory } -func (*s2iBuilderSearcher) get(namespace, name string) (interface{}, error) { - return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name) +func NewS2iBuilderSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface { + return &s2iBuilderSearcher{informers: informers} +} + +func (s *s2iBuilderSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).Get(name) } // exactly Match func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuilder) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,25 +70,21 @@ func (*s2iBuilderSearcher) match(match map[string]string, item *v1alpha1.S2iBuil func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuilder) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,17 +94,17 @@ func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuil func (*s2iBuilderSearcher) compare(a, b *v1alpha1.S2iBuilder, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *s2iBuilderSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - s2iBuilders, err := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything()) +func (s *s2iBuilderSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + s2iBuilders, err := s.informers.Devops().V1alpha1().S2iBuilders().Lister().S2iBuilders(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/s2irun.go b/pkg/models/resources/v1alpha2/s2irun/s2irun.go similarity index 69% rename from pkg/models/resources/s2irun.go rename to pkg/models/resources/v1alpha2/s2irun/s2irun.go index 6d437e225..aaee19366 100644 --- a/pkg/models/resources/s2irun.go +++ b/pkg/models/resources/v1alpha2/s2irun/s2irun.go @@ -16,15 +16,17 @@ */ -package resources +package s2irun import ( + "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/constants" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" "strings" - "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/server/params" "k8s.io/apimachinery/pkg/labels" @@ -33,27 +35,32 @@ import ( ) type s2iRunSearcher struct { + informers externalversions.SharedInformerFactory } -func (*s2iRunSearcher) get(namespace, name string) (interface{}, error) { - return informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name) +func NewS2iRunSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface { + return &s2iRunSearcher{informers: informers} +} + +func (s *s2iRunSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).Get(name) } // exactly Match func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Status: + case v1alpha2.Status: if string(item.Status.RunState) != v { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -70,25 +77,21 @@ func (*s2iRunSearcher) match(match map[string]string, item *v1alpha1.S2iRun) boo func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -98,17 +101,17 @@ func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) boo func (*s2iRunSearcher) compare(a, b *v1alpha1.S2iRun, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *s2iRunSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - s2iRuns, err := informers.S2iSharedInformerFactory().Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything()) +func (s *s2iRunSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + s2iRuns, err := s.informers.Devops().V1alpha1().S2iRuns().Lister().S2iRuns(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/secrets.go b/pkg/models/resources/v1alpha2/secret/secrets.go similarity index 68% rename from pkg/models/resources/secrets.go rename to pkg/models/resources/v1alpha2/secret/secrets.go index 2fe113af3..a2d57bc4f 100644 --- a/pkg/models/resources/secrets.go +++ b/pkg/models/resources/v1alpha2/secret/secrets.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package secret import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,17 +32,22 @@ import ( ) type secretSearcher struct { + informers informers.SharedInformerFactory } -func (*secretSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).Get(name) +func NewSecretSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &secretSearcher{informers: informers} +} + +func (s *secretSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(name) } // exactly Match func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false @@ -49,8 +56,8 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool { if string(item.Type) != v { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -67,25 +74,25 @@ func (*secretSearcher) match(match map[string]string, item *v1.Secret) bool { func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -95,17 +102,17 @@ func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool { func (*secretSearcher) compare(a, b *v1.Secret, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *secretSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - secrets, err := informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything()) +func (s *secretSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + secrets, err := s.informers.Core().V1().Secrets().Lister().Secrets(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/services.go b/pkg/models/resources/v1alpha2/service/services.go similarity index 67% rename from pkg/models/resources/services.go rename to pkg/models/resources/v1alpha2/service/services.go index f957d5d2b..7e406c9d5 100644 --- a/pkg/models/resources/services.go +++ b/pkg/models/resources/v1alpha2/service/services.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package service import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type serviceSearcher struct { + informers informers.SharedInformerFactory } -func (*serviceSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Core().V1().Services().Lister().Services(namespace).Get(name) +func NewServiceSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &serviceSearcher{informers: informers} +} + +func (s *serviceSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Core().V1().Services().Lister().Services(namespace).Get(name) } // exactly Match func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,25 +70,25 @@ func (*serviceSearcher) match(match map[string]string, item *v1.Service) bool { func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,17 +98,17 @@ func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool { func (*serviceSearcher) compare(a, b *v1.Service, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *serviceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - services, err := informers.SharedInformerFactory().Core().V1().Services().Lister().Services(namespace).List(labels.Everything()) +func (s *serviceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + services, err := s.informers.Core().V1().Services().Lister().Services(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/statefulsets.go b/pkg/models/resources/v1alpha2/statefulset/statefulsets.go similarity index 67% rename from pkg/models/resources/statefulsets.go rename to pkg/models/resources/v1alpha2/statefulset/statefulsets.go index fd915dcd6..ecb7af006 100644 --- a/pkg/models/resources/statefulsets.go +++ b/pkg/models/resources/v1alpha2/statefulset/statefulsets.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package statefulset import ( + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,39 +32,44 @@ import ( ) type statefulSetSearcher struct { + informers informers.SharedInformerFactory } -func (*statefulSetSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name) +func NewStatefulSetSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &statefulSetSearcher{informers: informers} +} + +func (s *statefulSetSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name) } func statefulSetStatus(item *v1.StatefulSet) string { if item.Spec.Replicas != nil { if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 { - return StatusStopped + return v1alpha2.StatusStopped } else if item.Status.ReadyReplicas == *item.Spec.Replicas { - return StatusRunning + return v1alpha2.StatusRunning } else { - return StatusUpdating + return v1alpha2.StatusUpdating } } - return StatusStopped + return v1alpha2.StatusStopped } // Exactly Match func (*statefulSetSearcher) match(match map[string]string, item *v1.StatefulSet) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } - case Status: + case v1alpha2.Status: if statefulSetStatus(item) != v { return false } @@ -80,25 +87,25 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { + case v1alpha2.App: + if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) { return false } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -109,17 +116,17 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) func (*statefulSetSearcher) compare(a, b *v1.StatefulSet, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *statefulSetSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - statefulSets, err := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything()) +func (s *statefulSetSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + statefulSets, err := s.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/storageclasses.go b/pkg/models/resources/v1alpha2/storageclass/storageclasses.go similarity index 59% rename from pkg/models/resources/storageclasses.go rename to pkg/models/resources/v1alpha2/storageclass/storageclasses.go index 248047978..e90c07e59 100644 --- a/pkg/models/resources/storageclasses.go +++ b/pkg/models/resources/v1alpha2/storageclass/storageclasses.go @@ -15,11 +15,13 @@ limitations under the License. */ -package resources +package storageclass import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/informers" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type storageClassesSearcher struct { + informers informers.SharedInformerFactory } -func (*storageClassesSearcher) get(namespace, name string) (interface{}, error) { - return informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister().Get(name) +func NewStorageClassesSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface { + return &storageClassesSearcher{informers: informers} +} + +func (s *storageClassesSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Storage().V1().StorageClasses().Lister().Get(name) } // exactly Match func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageClass) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,21 +70,21 @@ func (*storageClassesSearcher) match(match map[string]string, item *v1.StorageCl func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageClass) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -87,17 +94,17 @@ func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageCl func (*storageClassesSearcher) compare(a, b *v1.StorageClass, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *storageClassesSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - storageClasses, err := informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister().List(labels.Everything()) +func (s *storageClassesSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { + storageClasses, err := s.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything()) if err != nil { return nil, err @@ -116,16 +123,36 @@ func (s *storageClassesSearcher) search(namespace string, conditions *params.Con } sort.Slice(result, func(i, j int) bool { if reverse { - tmp := i - i = j - j = tmp + i, j = j, i } return s.compare(result[i], result[j], orderBy) }) r := make([]interface{}, 0) for _, i := range result { + count := s.countPersistentVolumeClaims(i.Name) + if i.Annotations == nil { + i.Annotations = make(map[string]string) + i.Annotations["kubesphere.io/pvc-count"] = string(count) + } + r = append(r, i) } return r, nil } + +func (s *storageClassesSearcher) countPersistentVolumeClaims(name string) int { + pvcs, err := s.informers.Core().V1().PersistentVolumeClaims().Lister().List(labels.Everything()) + if err != nil { + return 0 + } + var count int + + for _, pvc := range pvcs { + if *pvc.Spec.StorageClassName == name || (pvc.Annotations != nil && pvc.Annotations[corev1.BetaStorageClassAnnotation] == name) { + count++ + } + } + + return count +} diff --git a/pkg/models/resources/workspaces.go b/pkg/models/resources/v1alpha2/workspace/workspaces.go similarity index 70% rename from pkg/models/resources/workspaces.go rename to pkg/models/resources/v1alpha2/workspace/workspaces.go index 43c92e0d3..22dda69d6 100644 --- a/pkg/models/resources/workspaces.go +++ b/pkg/models/resources/v1alpha2/workspace/workspaces.go @@ -15,12 +15,14 @@ limitations under the License. */ -package resources +package workspace import ( tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" + "kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" + "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -30,23 +32,28 @@ import ( ) type workspaceSearcher struct { + informers externalversions.SharedInformerFactory } -func (*workspaceSearcher) get(namespace, name string) (interface{}, error) { - return informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().Get(name) +func NewWorkspaceSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface { + return &workspaceSearcher{informers: informers} +} + +func (s *workspaceSearcher) Get(namespace, name string) (interface{}, error) { + return s.informers.Tenant().V1alpha1().Workspaces().Lister().Get(name) } // exactly Match func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Workspace) bool { for k, v := range match { switch k { - case Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case Keyword: - if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Keyword: + if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } default: @@ -63,25 +70,21 @@ func (*workspaceSearcher) match(match map[string]string, item *tenantv1alpha1.Wo func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Workspace) bool { for k, v := range fuzzy { switch k { - case Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case Label: - if !searchFuzzy(item.Labels, "", v) { + case v1alpha2.Label: + if !v1alpha2.SearchFuzzy(item.Labels, "", v) { return false } - case annotation: - if !searchFuzzy(item.Annotations, "", v) { + case v1alpha2.Annotation: + if !v1alpha2.SearchFuzzy(item.Annotations, "", v) { return false } return false - case app: - if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { - return false - } default: - if !searchFuzzy(item.Labels, k, v) { + if !v1alpha2.SearchFuzzy(item.Labels, k, v) { return false } } @@ -91,18 +94,18 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Wo func (*workspaceSearcher) compare(a, b *tenantv1alpha1.Workspace, orderBy string) bool { switch orderBy { - case CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 } } -func (s *workspaceSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { +func (s *workspaceSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { - workspaces, err := informers.KsSharedInformerFactory().Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything()) + workspaces, err := s.informers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/resources/v1alpha3/deployment/deployments.go b/pkg/models/resources/v1alpha3/deployment/deployments.go new file mode 100644 index 000000000..444d19c15 --- /dev/null +++ b/pkg/models/resources/v1alpha3/deployment/deployments.go @@ -0,0 +1,131 @@ +/* + + Copyright 2019 The KubeSphere Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +package deployment + +import ( + "k8s.io/client-go/informers" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "strings" + "time" + + "k8s.io/apimachinery/pkg/labels" + + "k8s.io/api/apps/v1" +) + +const ( + applicationLabel = "app.kubernetes.io/name" + ReleaseLabel = "relase" + + statusStopped = "stopped" + statusRunning = "running" + statusUpdating = "updating" +) + +type deploymentsGetter struct { + sharedInformers informers.SharedInformerFactory +} + +func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface { + return &deploymentsGetter{sharedInformers: sharedInformers} +} + +func (d *deploymentsGetter) Get(namespace, name string) (interface{}, error) { + return d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name) +} + +func (d *deploymentsGetter) List(namespace string) ([]interface{}, error) { + // first retrieves all deployments within given namespace + all, err := d.sharedInformers.Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything()) + if err != nil { + return nil, err + } + + var result []interface{} + for _, deploy := range all { + result = append(result, deploy) + } + + return result, nil +} + +func (d *deploymentsGetter) Compare(left interface{}, right interface{}, field query.Field) bool { + + leftDeployment, ok := left.(*v1.Deployment) + if !ok { + return false + } + + rightDeployment, ok := right.(*v1.Deployment) + if !ok { + return false + } + + switch field { + case query.FieldCreationTimeStamp: + return leftDeployment.CreationTimestamp.After(rightDeployment.CreationTimestamp.Time) + case query.FieldLastUpdateTimestamp: + return lastUpdateTime(leftDeployment).After(lastUpdateTime(rightDeployment)) + default: + fallthrough + case query.FieldName: + return strings.Compare(leftDeployment.Name, rightDeployment.Name) > 0 + } +} + +func (d *deploymentsGetter) Filter(object interface{}, filter query.Filter) bool { + deployment, ok := object.(*v1.Deployment) + if !ok { + return false + } + + switch filter.Field { + case query.FieldName: + return query.ComparableString(deployment.Name).Contains(filter.Value) + case query.FieldApplication: + if app, ok := deployment.Labels[applicationLabel]; ok { + return query.ComparableString(app).Contains(filter.Value) + } + case query.FieldStatus: + return filter.Value.Compare(query.ComparableString(deploymentStatus(deployment.Status))) == 0 + default: + return false + } + return false +} + +func deploymentStatus(status v1.DeploymentStatus) string { + if status.ReadyReplicas == 0 && status.Replicas == 0 { + return statusStopped + } else if status.ReadyReplicas == status.Replicas { + return statusRunning + } else { + return statusUpdating + } +} + +func lastUpdateTime(deployment *v1.Deployment) time.Time { + lut := deployment.CreationTimestamp.Time + for _, condition := range deployment.Status.Conditions { + if condition.LastUpdateTime.After(lut) { + lut = condition.LastUpdateTime.Time + } + } + return lut +} diff --git a/pkg/models/resources/v1alpha3/deployment/deployments_test.go b/pkg/models/resources/v1alpha3/deployment/deployments_test.go new file mode 100644 index 000000000..fc01130cd --- /dev/null +++ b/pkg/models/resources/v1alpha3/deployment/deployments_test.go @@ -0,0 +1,150 @@ +package deployment + +import ( + "fmt" + "github.com/google/go-cmp/cmp" + v1 "k8s.io/api/apps/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "testing" + "time" +) + +func newDeployments(total int, name, namespace, application string) []*v1.Deployment { + var deployments []*v1.Deployment + + for i := 0; i < total; i++ { + deploy := &v1.Deployment{ + TypeMeta: metaV1.TypeMeta{ + Kind: "Deployment", + APIVersion: "v1", + }, + ObjectMeta: metaV1.ObjectMeta{ + Name: fmt.Sprintf("%s-%d", name, i), + Namespace: namespace, + Labels: map[string]string{ + "seq": fmt.Sprintf("seq-%d", i), + }, + Annotations: map[string]string{}, + CreationTimestamp: metaV1.Time{Time: time.Now().Add(time.Duration(i*5) * time.Second)}, + }, + Status: v1.DeploymentStatus{ + ReadyReplicas: int32(i + 1), + Replicas: int32(i + 1), + AvailableReplicas: int32(i + 1), + Conditions: []v1.DeploymentCondition{ + { + Type: v1.DeploymentAvailable, + LastUpdateTime: metaV1.Time{Time: time.Now().Add(time.Duration(i*5) * time.Second)}, + }, + }, + }, + } + + deployments = append(deployments, deploy) + } + + return deployments +} + +func deploymentsToRuntimeObjects(deployments ...*v1.Deployment) []runtime.Object { + var objs []runtime.Object + for _, deploy := range deployments { + objs = append(objs, deploy) + } + + return objs +} + +func TestListDeployments(t *testing.T) { + tests := []struct { + description string + namespace string + deployments []*v1.Deployment + query *query.Query + expected api.ListResult + expectedErr error + }{ + { + "test name filter", + "bar", + []*v1.Deployment{ + { + ObjectMeta: metaV1.ObjectMeta{ + Name: "foo-1", + Namespace: "bar", + }, + }, + { + ObjectMeta: metaV1.ObjectMeta{ + Name: "foo-2", + Namespace: "bar", + }, + }, + { + ObjectMeta: metaV1.ObjectMeta{ + Name: "bar-1", + Namespace: "bar", + }, + }, + }, + &query.Query{ + Pagination: &query.Pagination{ + Limit: 1, + Page: 1, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: []query.Filter{ + { + Field: query.FieldName, + Value: query.ComparableString("foo"), + }, + }, + }, + api.ListResult{ + Items: []interface{}{ + v1.Deployment{ + ObjectMeta: metaV1.ObjectMeta{ + Name: "foo-2", + Namespace: "bar", + }, + }, + }, + TotalItems: 2, + }, + nil, + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + objs := deploymentsToRuntimeObjects(test.deployments...) + client := fake.NewSimpleClientset(objs...) + //client := fake.NewSimpleClientset() + + informer := informers.NewSharedInformerFactory(client, 0) + + for _, deployment := range test.deployments { + informer.Apps().V1().Deployments().Informer().GetIndexer().Add(deployment) + } + + getter := New(informer) + + got, err := getter.List(test.namespace, test.query) + if test.expectedErr != nil && err != test.expectedErr { + t.Errorf("expected error, got nothing") + } else if err != nil { + t.Fatal(err) + } + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("%T differ (-got, +want): %s", test.expected, diff) + } + }) + } +} diff --git a/pkg/models/resources/v1alpha3/interface.go b/pkg/models/resources/v1alpha3/interface.go new file mode 100644 index 000000000..564ae56fb --- /dev/null +++ b/pkg/models/resources/v1alpha3/interface.go @@ -0,0 +1,19 @@ +package v1alpha3 + +import ( + "kubesphere.io/kubesphere/pkg/apiserver/query" +) + +type Interface interface { + // Get retrieves a single object by its namespace and name + Get(namespace, name string) (interface{}, error) + + // List retrieves a collection of objects matches given query + List(namespace string) ([]interface{}, error) + + // + Filter(item interface{}, filter query.Filter) bool + + // + Compare(left interface{}, right interface{}, field query.Field) bool +} diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go new file mode 100644 index 000000000..ba49c2744 --- /dev/null +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -0,0 +1,98 @@ +package resource + +import ( + "errors" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/deployment" + "sort" +) + +var ErrResourceNotSupported = errors.New("resource is not supported") + +type NamespacedResourceGetter struct { + getters map[schema.GroupVersionResource]v1alpha3.Interface +} + +func New(informers informers.SharedInformerFactory) *NamespacedResourceGetter { + getters := make(map[schema.GroupVersionResource]v1alpha3.Interface) + + getters[schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}] = deployment.New(informers) + + return &NamespacedResourceGetter{ + getters: getters, + } +} + +// tryResource will retrieve a getter with resource name, it doesn't guarantee find resource with correct group version +// need to refactor this use schema.GroupVersionResource +func (r *NamespacedResourceGetter) tryResource(resource string) v1alpha3.Interface { + for k, v := range r.getters { + if k.Resource == resource { + return v + } + } + + return nil +} + +func (r *NamespacedResourceGetter) Get(resource, namespace, name string) (interface{}, error) { + getter := r.tryResource(resource) + if getter == nil { + return nil, ErrResourceNotSupported + } + + return getter.Get(namespace, name) +} + +func (r *NamespacedResourceGetter) List(resource, namespace string, query *query.Query) (*api.ListResult, error) { + getter := r.tryResource(resource) + if getter == nil { + return nil, ErrResourceNotSupported + } + + all, err := getter.List(namespace) + if err != nil { + return nil, err + } + + // selected matched ones + var filtered []interface{} + for _, deploy := range all { + for _, filter := range query.Filters { + if getter.Filter(deploy, filter) { + filtered = append(filtered, deploy) + } + } + } + + // sort + sort.Slice(filtered, func(i, j int) bool { + if !query.Ascending { + return !getter.Compare(filtered[i], filtered[j], query.SortBy) + } + return getter.Compare(filtered[i], filtered[j], query.SortBy) + }) + + start, end := query.Pagination.GetPaginationSettings(len(filtered)) + if query.Pagination.IsPageAvailable(len(filtered), start) { + var result []interface{} + + for i := start; i < end; i++ { + result = append(result, filtered[i]) + } + + return &api.ListResult{ + Items: result, + TotalItems: len(filtered), + }, nil + } + + return &api.ListResult{ + Items: nil, + TotalItems: len(filtered), + }, nil +} diff --git a/pkg/models/revisions/revisions.go b/pkg/models/revisions/revisions.go index d3d402ce4..c5e3f0687 100644 --- a/pkg/models/revisions/revisions.go +++ b/pkg/models/revisions/revisions.go @@ -20,15 +20,29 @@ package revisions import ( "fmt" + "k8s.io/client-go/informers" "k8s.io/klog" "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/labels" - "kubesphere.io/kubesphere/pkg/informers" ) -func GetDeployRevision(namespace, name, revision string) (*v1.ReplicaSet, error) { - deploymentLister := informers.SharedInformerFactory().Apps().V1().Deployments().Lister() +type RevisionGetter interface { + GetDeploymentRevision(namespace, name, revision string) (*v1.ReplicaSet, error) + GetStatefulSetRevision(namespace, name string, revision int) (*v1.ControllerRevision, error) + GetDaemonSetRevision(namespace, name string, revision int) (*v1.ControllerRevision, error) +} + +type revisionGetter struct { + informers informers.SharedInformerFactory +} + +func NewRevisionGetter(informers informers.SharedInformerFactory) RevisionGetter { + return &revisionGetter{informers: informers} +} + +func (c *revisionGetter) GetDeploymentRevision(namespace, name, revision string) (*v1.ReplicaSet, error) { + deploymentLister := c.informers.Apps().V1().Deployments().Lister() deploy, err := deploymentLister.Deployments(namespace).Get(name) if err != nil { klog.Errorf("get deployment %s failed, reason: %s", name, err) @@ -38,7 +52,7 @@ func GetDeployRevision(namespace, name, revision string) (*v1.ReplicaSet, error) labelMap := deploy.Spec.Template.Labels labelSelector := labels.Set(labelMap).AsSelector() - replicaSetLister := informers.SharedInformerFactory().Apps().V1().ReplicaSets().Lister() + replicaSetLister := c.informers.Apps().V1().ReplicaSets().Lister() rsList, err := replicaSetLister.ReplicaSets(namespace).List(labelSelector) if err != nil { return nil, err @@ -53,34 +67,34 @@ func GetDeployRevision(namespace, name, revision string) (*v1.ReplicaSet, error) return nil, fmt.Errorf("revision not found %v#%v", name, revision) } -func GetDaemonSetRevision(namespace, name string, revisionInt int) (*v1.ControllerRevision, error) { - daemonSetLister := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister() +func (c *revisionGetter) GetDaemonSetRevision(namespace, name string, revisionInt int) (*v1.ControllerRevision, error) { + daemonSetLister := c.informers.Apps().V1().DaemonSets().Lister() ds, err := daemonSetLister.DaemonSets(namespace).Get(name) if err != nil { return nil, err } - labels := ds.Spec.Template.Labels + lbs := ds.Spec.Template.Labels - return getControllerRevision(namespace, name, labels, revisionInt) + return c.getControllerRevision(namespace, name, lbs, revisionInt) } -func GetStatefulSetRevision(namespace, name string, revisionInt int) (*v1.ControllerRevision, error) { - statefulSetLister := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister() +func (c *revisionGetter) GetStatefulSetRevision(namespace, name string, revisionInt int) (*v1.ControllerRevision, error) { + statefulSetLister := c.informers.Apps().V1().StatefulSets().Lister() st, err := statefulSetLister.StatefulSets(namespace).Get(name) if err != nil { return nil, err } - return getControllerRevision(namespace, name, st.Spec.Template.Labels, revisionInt) + return c.getControllerRevision(namespace, name, st.Spec.Template.Labels, revisionInt) } -func getControllerRevision(namespace, name string, labelMap map[string]string, revision int) (*v1.ControllerRevision, error) { +func (c *revisionGetter) getControllerRevision(namespace, name string, labelMap map[string]string, revision int) (*v1.ControllerRevision, error) { labelSelector := labels.Set(labelMap).AsSelector() - controllerRevisionLister := informers.SharedInformerFactory().Apps().V1().ControllerRevisions().Lister() + controllerRevisionLister := c.informers.Apps().V1().ControllerRevisions().Lister() revisions, err := controllerRevisionLister.ControllerRevisions(namespace).List(labelSelector) if err != nil { diff --git a/pkg/models/routers/routers.go b/pkg/models/routers/routers.go index 602067231..f4c1e00be 100644 --- a/pkg/models/routers/routers.go +++ b/pkg/models/routers/routers.go @@ -22,22 +22,17 @@ import ( "fmt" "io/ioutil" v1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/simple/client" - "sort" - - "k8s.io/apimachinery/pkg/labels" - "kubesphere.io/kubesphere/pkg/informers" - corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" - + "k8s.io/klog" + "sort" "strings" - - "kubesphere.io/kubesphere/pkg/constants" ) // choose router node ip by labels, currently select master node @@ -46,20 +41,32 @@ var routerNodeIPLabelSelector = map[string]string{ } const ( - servicemeshEnabled = "servicemesh.kubesphere.io/enabled" - sidecarInject = "sidecar.istio.io/inject" + servicemeshEnabled = "servicemesh.kubesphere.io/enabled" + sidecarInject = "sidecar.istio.io/inject" + ingressControllerFolder = "/etc/kubesphere/ingress-controller" + ingressControllerPrefix = "kubesphere-router-" + ingressControllerNamespace = "kubesphere-controls-system" ) -var routerTemplates map[string]runtime.Object +type RouterOperator interface { + GetRouter(namespace string) (*corev1.Service, error) + CreateRouter(namespace string, serviceType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) + DeleteRouter(namespace string) (*corev1.Service, error) + UpdateRouter(namespace string, serviceType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) +} -// Load yamls -func init() { +type routerOperator struct { + routerTemplates map[string]runtime.Object + client kubernetes.Interface + informers informers.SharedInformerFactory +} + +func NewRouterOperator(client kubernetes.Interface, informers informers.SharedInformerFactory) RouterOperator { yamls, err := loadYamls() - routerTemplates = make(map[string]runtime.Object, 2) + routerTemplates := make(map[string]runtime.Object, 2) if err != nil { - klog.Warning("error happened during loading external yamls", err) - return + klog.Fatalf("error happened during loading external yamls, %v", err) } for _, f := range yamls { @@ -79,13 +86,18 @@ func init() { } } + return &routerOperator{ + client: client, + informers: informers, + routerTemplates: routerTemplates, + } } // get master node ip, if there are multiple master nodes, // choose first one according by their names alphabetically -func getMasterNodeIp() string { +func (c *routerOperator) getMasterNodeIp() string { - nodeLister := informers.SharedInformerFactory().Core().V1().Nodes().Lister() + nodeLister := c.informers.Core().V1().Nodes().Lister() selector := labels.SelectorFromSet(routerNodeIPLabelSelector) masters, err := nodeLister.List(selector) @@ -110,7 +122,7 @@ func getMasterNodeIp() string { return "" } -func addLoadBalancerIp(service *corev1.Service) { +func (c *routerOperator) addLoadBalancerIp(service *corev1.Service) { if service == nil { return @@ -118,7 +130,7 @@ func addLoadBalancerIp(service *corev1.Service) { // append selected node ip as loadbalancer ingress ip if service.Spec.Type != corev1.ServiceTypeLoadBalancer && len(service.Status.LoadBalancer.Ingress) == 0 { - rip := getMasterNodeIp() + rip := c.getMasterNodeIp() if len(rip) == 0 { klog.Info("can not get node ip") return @@ -132,36 +144,17 @@ func addLoadBalancerIp(service *corev1.Service) { } } -func GetAllRouters() ([]*corev1.Service, error) { - - selector := labels.SelectorFromSet(labels.Set{"app": "kubesphere", "component": "ks-router", "tier": "backend"}) - serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister() - services, err := serviceLister.Services(constants.IngressControllerNamespace).List(selector) - - for i := range services { - addLoadBalancerIp(services[i]) - } - - if err != nil { - klog.Error(err) - return nil, err - } - - return services, nil -} - // Get router from a namespace -func GetRouter(namespace string) (*corev1.Service, error) { - service, err := getRouterService(namespace) - addLoadBalancerIp(service) +func (c *routerOperator) GetRouter(namespace string) (*corev1.Service, error) { + service, err := c.getRouterService(namespace) + c.addLoadBalancerIp(service) return service, err } -func getRouterService(namespace string) (*corev1.Service, error) { - serviceName := constants.IngressControllerPrefix + namespace - - serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister() - service, err := serviceLister.Services(constants.IngressControllerNamespace).Get(serviceName) +func (c *routerOperator) getRouterService(namespace string) (*corev1.Service, error) { + serviceName := ingressControllerPrefix + namespace + serviceLister := c.informers.Core().V1().Services().Lister() + service, err := serviceLister.Services(ingressControllerNamespace).Get(serviceName) if err != nil { if errors.IsNotFound(err) { @@ -175,10 +168,8 @@ func getRouterService(namespace string) (*corev1.Service, error) { // Load all resource yamls func loadYamls() ([]string, error) { - var yamls []string - - files, err := ioutil.ReadDir(constants.IngressControllerFolder) + files, err := ioutil.ReadDir(ingressControllerFolder) if err != nil { klog.Warning(err) return nil, err @@ -188,7 +179,7 @@ func loadYamls() ([]string, error) { if file.IsDir() || !strings.HasSuffix(file.Name(), ".yaml") { continue } - content, err := ioutil.ReadFile(constants.IngressControllerFolder + "/" + file.Name()) + content, err := ioutil.ReadFile(ingressControllerFolder + "/" + file.Name()) if err != nil { klog.Error(err) @@ -202,7 +193,7 @@ func loadYamls() ([]string, error) { } // Create a ingress controller in a namespace -func CreateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { +func (c *routerOperator) CreateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { injectSidecar := false if enabled, ok := annotations[servicemeshEnabled]; ok { @@ -211,32 +202,32 @@ func CreateRouter(namespace string, routerType corev1.ServiceType, annotations m } } - err := createOrUpdateRouterWorkload(namespace, routerType == corev1.ServiceTypeLoadBalancer, injectSidecar) + err := c.createOrUpdateRouterWorkload(namespace, routerType == corev1.ServiceTypeLoadBalancer, injectSidecar) if err != nil { klog.Error(err) return nil, err } - router, err := createRouterService(namespace, routerType, annotations) + router, err := c.createRouterService(namespace, routerType, annotations) if err != nil { klog.Error(err) - _ = deleteRouterWorkload(namespace) + _ = c.deleteRouterWorkload(namespace) return nil, err } - addLoadBalancerIp(router) + c.addLoadBalancerIp(router) return router, nil } // DeleteRouter is used to delete ingress controller related resources in namespace // It will not delete ClusterRole resource cause it maybe used by other controllers -func DeleteRouter(namespace string) (*corev1.Service, error) { - err := deleteRouterWorkload(namespace) +func (c *routerOperator) DeleteRouter(namespace string) (*corev1.Service, error) { + err := c.deleteRouterWorkload(namespace) if err != nil { klog.Error(err) } - router, err := deleteRouterService(namespace) + router, err := c.deleteRouterService(namespace) if err != nil { klog.Error(err) @@ -245,28 +236,23 @@ func DeleteRouter(namespace string) (*corev1.Service, error) { return router, nil } -func createRouterService(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { +func (c *routerOperator) createRouterService(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { - obj, ok := routerTemplates["SERVICE"] + obj, ok := c.routerTemplates["SERVICE"] if !ok { klog.Error("service template not loaded") return nil, fmt.Errorf("service template not loaded") } - k8sClient := client.ClientSets().K8s().Kubernetes() - service := obj.(*corev1.Service) - service.SetAnnotations(annotations) service.Spec.Type = routerType - service.Name = constants.IngressControllerPrefix + namespace + service.Name = ingressControllerPrefix + namespace // Add project selector service.Labels["project"] = namespace - service.Spec.Selector["project"] = namespace - - service, err := k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Create(service) + service, err := c.client.CoreV1().Services(ingressControllerNamespace).Create(service) if err != nil { klog.Error(err) return nil, err @@ -275,41 +261,32 @@ func createRouterService(namespace string, routerType corev1.ServiceType, annota return service, nil } -func updateRouterService(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { - - k8sClient := client.ClientSets().K8s().Kubernetes() - - service, err := getRouterService(namespace) +func (c *routerOperator) updateRouterService(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { + service, err := c.getRouterService(namespace) if err != nil { klog.Error(err, "get router failed") return service, err } service.Spec.Type = routerType - service.SetAnnotations(annotations) - - service, err = k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Update(service) - + service, err = c.client.CoreV1().Services(ingressControllerNamespace).Update(service) return service, err } -func deleteRouterService(namespace string) (*corev1.Service, error) { - - service, err := getRouterService(namespace) +func (c *routerOperator) deleteRouterService(namespace string) (*corev1.Service, error) { + service, err := c.getRouterService(namespace) if err != nil { klog.Error(err) return service, err } - k8sClient := client.ClientSets().K8s().Kubernetes() - // delete controller service - serviceName := constants.IngressControllerPrefix + namespace + serviceName := ingressControllerPrefix + namespace deleteOptions := metav1.DeleteOptions{} - err = k8sClient.CoreV1().Services(constants.IngressControllerNamespace).Delete(serviceName, &deleteOptions) + err = c.client.CoreV1().Services(ingressControllerNamespace).Delete(serviceName, &deleteOptions) if err != nil { klog.Error(err) return service, err @@ -318,17 +295,16 @@ func deleteRouterService(namespace string) (*corev1.Service, error) { return service, nil } -func createOrUpdateRouterWorkload(namespace string, publishService bool, servicemeshEnabled bool) error { - obj, ok := routerTemplates["DEPLOYMENT"] +func (c *routerOperator) createOrUpdateRouterWorkload(namespace string, publishService bool, servicemeshEnabled bool) error { + obj, ok := c.routerTemplates["DEPLOYMENT"] if !ok { klog.Error("Deployment template file not loaded") return fmt.Errorf("deployment template file not loaded") } - deployName := constants.IngressControllerPrefix + namespace + deployName := ingressControllerPrefix + namespace - k8sClient := client.ClientSets().K8s().Kubernetes() - deployment, err := k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Get(deployName, metav1.GetOptions{}) + deployment, err := c.client.AppsV1().Deployments(ingressControllerNamespace).Get(deployName, metav1.GetOptions{}) createDeployment := true @@ -336,7 +312,7 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service if errors.IsNotFound(err) { deployment = obj.(*v1.Deployment) - deployment.Name = constants.IngressControllerPrefix + namespace + deployment.Name = ingressControllerPrefix + namespace // Add project label deployment.Spec.Selector.MatchLabels["project"] = namespace @@ -382,15 +358,15 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service } if publishService { - deployment.Spec.Template.Spec.Containers[0].Args = append(deployment.Spec.Template.Spec.Containers[0].Args, "--publish-service="+constants.IngressControllerNamespace+"/"+constants.IngressControllerPrefix+namespace) + deployment.Spec.Template.Spec.Containers[0].Args = append(deployment.Spec.Template.Spec.Containers[0].Args, "--publish-service="+ingressControllerNamespace+"/"+ingressControllerPrefix+namespace) } else { deployment.Spec.Template.Spec.Containers[0].Args = append(deployment.Spec.Template.Spec.Containers[0].Args, "--report-node-internal-ip-address") } if createDeployment { - deployment, err = k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Create(deployment) + deployment, err = c.client.AppsV1().Deployments(ingressControllerNamespace).Create(deployment) } else { - deployment, err = k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Update(deployment) + deployment, err = c.client.AppsV1().Deployments(ingressControllerNamespace).Update(deployment) } if err != nil { @@ -401,13 +377,11 @@ func createOrUpdateRouterWorkload(namespace string, publishService bool, service return nil } -func deleteRouterWorkload(namespace string) error { - k8sClient := client.ClientSets().K8s().Kubernetes() - +func (c *routerOperator) deleteRouterWorkload(namespace string) error { deleteOptions := metav1.DeleteOptions{} // delete controller deployment - deploymentName := constants.IngressControllerPrefix + namespace - err := k8sClient.AppsV1().Deployments(constants.IngressControllerNamespace).Delete(deploymentName, &deleteOptions) + deploymentName := ingressControllerPrefix + namespace + err := c.client.AppsV1().Deployments(ingressControllerNamespace).Delete(deploymentName, &deleteOptions) if err != nil { klog.Error(err) } @@ -420,15 +394,14 @@ func deleteRouterWorkload(namespace string) error { "tier": "backend", "project": namespace, }) - replicaSetLister := informers.SharedInformerFactory().Apps().V1().ReplicaSets().Lister() - replicaSets, err := replicaSetLister.ReplicaSets(constants.IngressControllerNamespace).List(selector) - + replicaSetLister := c.informers.Apps().V1().ReplicaSets().Lister() + replicaSets, err := replicaSetLister.ReplicaSets(ingressControllerNamespace).List(selector) if err != nil { klog.Error(err) } for i := range replicaSets { - err = k8sClient.AppsV1().ReplicaSets(constants.IngressControllerNamespace).Delete(replicaSets[i].Name, &deleteOptions) + err = c.client.AppsV1().ReplicaSets(ingressControllerNamespace).Delete(replicaSets[i].Name, &deleteOptions) if err != nil { klog.Error(err) } @@ -438,10 +411,10 @@ func deleteRouterWorkload(namespace string) error { } // Update Ingress Controller Service, change type from NodePort to loadbalancer or vice versa. -func UpdateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { +func (c *routerOperator) UpdateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) { var router *corev1.Service - router, err := getRouterService(namespace) + router, err := c.getRouterService(namespace) if err != nil { klog.Error(err) @@ -450,14 +423,13 @@ func UpdateRouter(namespace string, routerType corev1.ServiceType, annotations m enableServicemesh := annotations[servicemeshEnabled] == "true" - err = createOrUpdateRouterWorkload(namespace, routerType == corev1.ServiceTypeLoadBalancer, enableServicemesh) + err = c.createOrUpdateRouterWorkload(namespace, routerType == corev1.ServiceTypeLoadBalancer, enableServicemesh) if err != nil { klog.Error(err) return router, err } - newRouter, err := updateRouterService(namespace, routerType, annotations) - + newRouter, err := c.updateRouterService(namespace, routerType, annotations) if err != nil { klog.Error(err) return newRouter, err diff --git a/pkg/models/status/status.go b/pkg/models/status/status.go deleted file mode 100644 index e92a11911..000000000 --- a/pkg/models/status/status.go +++ /dev/null @@ -1,67 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package status - -import ( - "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/models" - "kubesphere.io/kubesphere/pkg/server/params" - "strings" - - "kubesphere.io/kubesphere/pkg/models/resources" -) - -type WorkLoadStatus struct { - Namespace string `json:"namespace" description:"the name of the namespace"` - Count map[string]int `json:"data" description:"the number of unhealthy workloads"` - Items map[string]interface{} `json:"items,omitempty" description:"unhealthy workloads"` -} - -func GetNamespacesResourceStatus(namespace string) (*WorkLoadStatus, error) { - res := WorkLoadStatus{Count: make(map[string]int), Namespace: namespace, Items: make(map[string]interface{})} - var notReadyList *models.PageableResponse - var err error - for _, resource := range []string{resources.Deployments, resources.StatefulSets, resources.DaemonSets, resources.PersistentVolumeClaims, resources.Jobs} { - var notReadyStatus string - - switch resource { - case resources.PersistentVolumeClaims: - notReadyStatus = strings.Join([]string{resources.StatusPending, resources.StatusLost}, "|") - case resources.Jobs: - notReadyStatus = resources.StatusFailed - default: - notReadyStatus = resources.StatusUpdating - } - - notReadyList, err = resources.ListResources(namespace, resource, ¶ms.Conditions{Match: map[string]string{resources.Status: notReadyStatus}}, "", false, -1, 0) - - if err != nil { - klog.Errorf("list resources failed: %+v", err) - return nil, err - } - - res.Count[resource] = notReadyList.TotalCount - } - - return &res, nil -} - -func GetClusterResourceStatus() (*WorkLoadStatus, error) { - - return GetNamespacesResourceStatus("") -} diff --git a/pkg/models/storage/storage.go b/pkg/models/storage/storage.go index 4c784defb..88dca126c 100644 --- a/pkg/models/storage/storage.go +++ b/pkg/models/storage/storage.go @@ -18,13 +18,13 @@ package storage import ( + "k8s.io/client-go/informers" "strconv" "k8s.io/api/core/v1" storageV1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/labels" - "kubesphere.io/kubesphere/pkg/informers" ) type ScMetrics struct { @@ -33,12 +33,20 @@ type ScMetrics struct { PvcNumber string `json:"pvcNumber"` } -func init() { - +type PersistentVolumeClaimGetter interface { + GetPersistentVolumeClaimByStorageClass(storageClassName string) ([]*v1.PersistentVolumeClaim, error) } -func GetPvcListBySc(scName string) ([]*v1.PersistentVolumeClaim, error) { - persistentVolumeClaimLister := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister() +type persistentVolumeClaimGetter struct { + informers informers.SharedInformerFactory +} + +func NewPersistentVolumeClaimGetter(informers informers.SharedInformerFactory) PersistentVolumeClaimGetter { + return &persistentVolumeClaimGetter{informers: informers} +} + +func (c *persistentVolumeClaimGetter) GetPersistentVolumeClaimByStorageClass(scName string) ([]*v1.PersistentVolumeClaim, error) { + persistentVolumeClaimLister := c.informers.Core().V1().PersistentVolumeClaims().Lister() all, err := persistentVolumeClaimLister.List(labels.Everything()) if err != nil { @@ -60,14 +68,14 @@ func GetPvcListBySc(scName string) ([]*v1.PersistentVolumeClaim, error) { } // Get info of metrics -func GetScMetrics(scName string) (*ScMetrics, error) { - persistentVolumeLister := informers.SharedInformerFactory().Core().V1().PersistentVolumes().Lister() +func (c *persistentVolumeClaimGetter) GetScMetrics(scName string) (*ScMetrics, error) { + persistentVolumeLister := c.informers.Core().V1().PersistentVolumes().Lister() pvList, err := persistentVolumeLister.List(labels.Everything()) if err != nil { return nil, err } // Get PVC - pvcList, err := GetPvcListBySc(scName) + pvcList, err := c.GetPersistentVolumeClaimByStorageClass(scName) if err != nil { return nil, err @@ -91,10 +99,10 @@ func GetScMetrics(scName string) (*ScMetrics, error) { } // Get SC item list -func GetScList() ([]*storageV1.StorageClass, error) { +func (c *persistentVolumeClaimGetter) GetScList() ([]*storageV1.StorageClass, error) { // Get StorageClass list - scList, err := informers.SharedInformerFactory().Storage().V1().StorageClasses().Lister().List(labels.Everything()) + scList, err := c.informers.Storage().V1().StorageClasses().Lister().List(labels.Everything()) if err != nil { return nil, err diff --git a/pkg/models/storage/volumes.go b/pkg/models/storage/volumes.go deleted file mode 100644 index a656ad895..000000000 --- a/pkg/models/storage/volumes.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - - Copyright 2019 The KubeSphere Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -package storage - -import ( - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/labels" - "kubesphere.io/kubesphere/pkg/informers" -) - -// List pods of a specific persistent volume claims -func GetPodListByPvc(pvc string, ns string) (res []*v1.Pod, err error) { - podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister() - podList, err := podLister.Pods(ns).List(labels.Everything()) - if err != nil { - return nil, err - } - for _, pod := range podList { - if IsPvcInPod(pod, pvc) == true { - res = append(res, pod.DeepCopy()) - } - } - return res, nil -} - -// Check if the persistent volume claim is related to the pod -func IsPvcInPod(pod *v1.Pod, pvcName string) bool { - for _, v := range pod.Spec.Volumes { - if v.VolumeSource.PersistentVolumeClaim != nil && - v.VolumeSource.PersistentVolumeClaim.ClaimName == pvcName { - return true - } - } - return false -} diff --git a/pkg/models/tenant/namespaces.go b/pkg/models/tenant/namespaces.go index 5fb4a791e..d9161d04d 100644 --- a/pkg/models/tenant/namespaces.go +++ b/pkg/models/tenant/namespaces.go @@ -25,7 +25,7 @@ import ( "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models/iam" - "kubesphere.io/kubesphere/pkg/models/resources" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -39,12 +39,12 @@ type namespaceSearcher struct { func (*namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool { for k, v := range match { switch k { - case resources.Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case resources.Keyword: + case v1alpha2.Keyword: if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) { return false } @@ -62,7 +62,7 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo for k, v := range fuzzy { switch k { - case resources.Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } diff --git a/pkg/models/tenant/workspaces.go b/pkg/models/tenant/workspaces.go index fefc8d9e4..ac98aa0b2 100644 --- a/pkg/models/tenant/workspaces.go +++ b/pkg/models/tenant/workspaces.go @@ -24,7 +24,7 @@ import ( "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models/iam" - "kubesphere.io/kubesphere/pkg/models/resources" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2" "kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" @@ -38,12 +38,12 @@ type workspaceSearcher struct { func (*workspaceSearcher) match(match map[string]string, item *v1alpha1.Workspace) bool { for k, v := range match { switch k { - case resources.Name: + case v1alpha2.Name: names := strings.Split(v, "|") if !sliceutil.HasString(names, item.Name) { return false } - case resources.Keyword: + case v1alpha2.Keyword: if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) { return false } @@ -61,7 +61,7 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspac for k, v := range fuzzy { switch k { - case resources.Name: + case v1alpha2.Name: if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } @@ -75,9 +75,9 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspac func (*workspaceSearcher) compare(a, b *v1alpha1.Workspace, orderBy string) bool { switch orderBy { - case resources.CreateTime: + case v1alpha2.CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case resources.Name: + case v1alpha2.Name: fallthrough default: return strings.Compare(a.Name, b.Name) <= 0 diff --git a/pkg/models/types.go b/pkg/models/types.go index f22fbd4ad..18a410c42 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -18,7 +18,6 @@ package models import ( - corev1 "k8s.io/api/core/v1" "time" "k8s.io/api/rbac/v1" @@ -81,25 +80,6 @@ type Group struct { Description string `json:"description"` } -type ComponentStatus struct { - Name string `json:"name" description:"component name"` - Namespace string `json:"namespace" description:"the name of the namespace"` - SelfLink string `json:"selfLink" description:"self link"` - Label interface{} `json:"label" description:"labels"` - StartedAt time.Time `json:"startedAt" description:"started time"` - TotalBackends int `json:"totalBackends" description:"the total replicas of each backend system component"` - HealthyBackends int `json:"healthyBackends" description:"the number of healthy backend components"` -} -type NodeStatus struct { - TotalNodes int `json:"totalNodes" description:"total number of nodes"` - HealthyNodes int `json:"healthyNodes" description:"the number of healthy nodes"` -} - -type HealthStatus struct { - KubeSphereComponents []ComponentStatus `json:"kubesphereStatus" description:"kubesphere components status"` - NodeStatus NodeStatus `json:"nodeStatus" description:"nodes status"` -} - type PodInfo struct { Namespace string `json:"namespace" description:"namespace"` Pod string `json:"pod" description:"pod name"` @@ -112,8 +92,3 @@ type AuthGrantResponse struct { ExpiresIn float64 `json:"expires_in,omitempty"` RefreshToken string `json:"refresh_token,omitempty"` } - -type ResourceQuota struct { - Namespace string `json:"namespace" description:"namespace"` - Data corev1.ResourceQuotaStatus `json:"data" description:"resource quota status"` -} diff --git a/pkg/models/workloads/jobs.go b/pkg/models/workloads/jobs.go index 9c5838a4f..f639f866a 100644 --- a/pkg/models/workloads/jobs.go +++ b/pkg/models/workloads/jobs.go @@ -23,17 +23,28 @@ import ( k8serr "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" "k8s.io/klog" - "kubesphere.io/kubesphere/pkg/simple/client" "strings" "time" ) const retryTimes = 3 -func JobReRun(namespace, jobName, resourceVersion string) error { - k8sClient := client.ClientSets().K8s().Kubernetes() - job, err := k8sClient.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{}) +type JobRunner interface { + JobReRun(namespace, name, resourceVersion string) error +} + +type jobRunner struct { + client kubernetes.Interface +} + +func NewJobRunner(client kubernetes.Interface) JobRunner { + return &jobRunner{client: client} +} + +func (r *jobRunner) JobReRun(namespace, jobName, resourceVersion string) error { + job, err := r.client.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{}) if err != nil { return err } @@ -55,7 +66,7 @@ func JobReRun(namespace, jobName, resourceVersion string) error { delete(newJob.Spec.Selector.MatchLabels, "controller-uid") delete(newJob.Spec.Template.ObjectMeta.Labels, "controller-uid") - err = deleteJob(namespace, jobName) + err = r.deleteJob(namespace, jobName) if err != nil { klog.Errorf("failed to rerun job %s, reason: %s", jobName, err) @@ -63,7 +74,7 @@ func JobReRun(namespace, jobName, resourceVersion string) error { } for i := 0; i < retryTimes; i++ { - _, err = k8sClient.BatchV1().Jobs(namespace).Create(&newJob) + _, err = r.client.BatchV1().Jobs(namespace).Create(&newJob) if err != nil { time.Sleep(time.Second) continue @@ -79,9 +90,8 @@ func JobReRun(namespace, jobName, resourceVersion string) error { return nil } -func deleteJob(namespace, job string) error { - k8sClient := client.ClientSets().K8s().Kubernetes() +func (r *jobRunner) deleteJob(namespace, job string) error { deletePolicy := metav1.DeletePropagationBackground - err := k8sClient.BatchV1().Jobs(namespace).Delete(job, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) + err := r.client.BatchV1().Jobs(namespace).Delete(job, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) return err } diff --git a/pkg/models/workspaces/workspaces.go b/pkg/models/workspaces/workspaces.go index 47df460f0..cbaf3439a 100644 --- a/pkg/models/workspaces/workspaces.go +++ b/pkg/models/workspaces/workspaces.go @@ -20,16 +20,17 @@ package workspaces import ( "fmt" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" "k8s.io/klog" + "kubesphere.io/kubesphere/pkg/client/informers/externalversions" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/db" - "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models/devops" "kubesphere.io/kubesphere/pkg/models/iam" - "kubesphere.io/kubesphere/pkg/models/resources" - "kubesphere.io/kubesphere/pkg/server/params" clientset "kubesphere.io/kubesphere/pkg/simple/client" + "kubesphere.io/kubesphere/pkg/simple/client/mysql" "kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil" "strings" @@ -43,53 +44,76 @@ import ( "k8s.io/apimachinery/pkg/labels" ) -func Namespaces(workspaceName string) ([]*core.Namespace, error) { - namespaceLister := informers.SharedInformerFactory().Core().V1().Namespaces().Lister() - namespaces, err := namespaceLister.List(labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspaceName})) +type Interface interface { + ListNamespaces(workspace string) ([]*core.Namespace, error) + DeleteNamespace(workspace, namespace string) error + RemoveUser(user, workspace string) error + AddUser(workspace string, user *models.User) error + CountDevopsProjectsInWorkspace(workspace string) (int, error) + CountUsersInWorkspace(workspace string) (int, error) + CountOrgRoles() (int, error) + CountWorkspaces() (int, error) + CountNamespacesInWorkspace(workspace string) (int, error) +} + +type workspaceOperator struct { + client kubernetes.Interface + informers informers.SharedInformerFactory + ksInformers externalversions.SharedInformerFactory + + // TODO: use db interface instead of mysql client + // we can refactor this after rewrite devops using crd + db *mysql.Database +} + +func NewWorkspaceOperator(client kubernetes.Interface, informers informers.SharedInformerFactory, ksinformers externalversions.SharedInformerFactory, db *mysql.Database) Interface { + return &workspaceOperator{ + client: client, + informers: informers, + ksInformers: ksinformers, + db: db, + } +} + +func (c *workspaceOperator) ListNamespaces(workspace string) ([]*core.Namespace, error) { + namespaces, err := c.informers.Core().V1().Namespaces().Lister().List(labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspace})) if err != nil { return nil, err } - if namespaces == nil { - return make([]*core.Namespace, 0), nil - } - - out := make([]*core.Namespace, len(namespaces)) - - for i, v := range namespaces { - out[i] = v.DeepCopy() - } - - return out, nil + return namespaces, nil } -func DeleteNamespace(workspace string, namespaceName string) error { - namespace, err := clientset.ClientSets().K8s().Kubernetes().CoreV1().Namespaces().Get(namespaceName, metav1.GetOptions{}) +func (c *workspaceOperator) DeleteNamespace(workspace string, namespace string) error { + ns, err := c.informers.Core().V1().Namespaces().Lister().Get(namespace) if err != nil { return err } - if namespace.Labels[constants.WorkspaceLabelKey] == workspace { + + if ns.Labels[constants.WorkspaceLabelKey] == workspace { deletePolicy := metav1.DeletePropagationBackground - return clientset.ClientSets().K8s().Kubernetes().CoreV1().Namespaces().Delete(namespaceName, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) + return c.client.CoreV1().Namespaces().Delete(namespace, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) } else { return errors.New("resource not found") } } -func RemoveUser(workspaceName string, username string) error { - workspaceRole, err := iam.GetUserWorkspaceRole(workspaceName, username) +func (c *workspaceOperator) RemoveUser(workspace string, username string) error { + workspaceRole, err := iam.GetUserWorkspaceRole(workspace, username) if err != nil { return err } - err = DeleteWorkspaceRoleBinding(workspaceName, username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]) + + err = c.deleteWorkspaceRoleBinding(workspace, username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]) if err != nil { return err } + return nil } -func InviteUser(workspaceName string, user *models.User) error { +func (c *workspaceOperator) AddUser(workspaceName string, user *models.User) error { workspaceRole, err := iam.GetUserWorkspaceRole(workspaceName, user.Username) @@ -105,7 +129,7 @@ func InviteUser(workspaceName string, user *models.User) error { } if currentWorkspaceRoleName != workspaceRoleName && currentWorkspaceRoleName != "" { - err := DeleteWorkspaceRoleBinding(workspaceName, user.Username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]) + err := c.deleteWorkspaceRoleBinding(workspaceName, user.Username, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]) if err != nil { klog.Errorf("delete workspace role binding failed: %+v", err) return err @@ -114,17 +138,17 @@ func InviteUser(workspaceName string, user *models.User) error { return nil } - return CreateWorkspaceRoleBinding(workspaceName, user.Username, user.WorkspaceRole) + return c.createWorkspaceRoleBinding(workspaceName, user.Username, user.WorkspaceRole) } -func CreateWorkspaceRoleBinding(workspace, username string, role string) error { +func (c *workspaceOperator) createWorkspaceRoleBinding(workspace, username string, role string) error { if !sliceutil.HasString(constants.WorkSpaceRoles, role) { return apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role) } roleBindingName := fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-")) - workspaceRoleBinding, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName) + workspaceRoleBinding, err := c.informers.Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName) if err != nil { return err } @@ -132,7 +156,7 @@ func CreateWorkspaceRoleBinding(workspace, username string, role string) error { if !k8sutil.ContainsUser(workspaceRoleBinding.Subjects, username) { workspaceRoleBinding = workspaceRoleBinding.DeepCopy() workspaceRoleBinding.Subjects = append(workspaceRoleBinding.Subjects, v1.Subject{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: username}) - _, err = clientset.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding) + _, err = c.client.RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding) if err != nil { klog.Errorf("update workspace role binding failed: %+v", err) return err @@ -142,7 +166,7 @@ func CreateWorkspaceRoleBinding(workspace, username string, role string) error { return nil } -func DeleteWorkspaceRoleBinding(workspace, username string, role string) error { +func (c *workspaceOperator) deleteWorkspaceRoleBinding(workspace, username string, role string) error { if !sliceutil.HasString(constants.WorkSpaceRoles, role) { return apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role) @@ -150,7 +174,7 @@ func DeleteWorkspaceRoleBinding(workspace, username string, role string) error { roleBindingName := fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-")) - workspaceRoleBinding, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName) + workspaceRoleBinding, err := c.informers.Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName) if err != nil { return err } @@ -163,23 +187,17 @@ func DeleteWorkspaceRoleBinding(workspace, username string, role string) error { } } - workspaceRoleBinding, err = clientset.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding) + workspaceRoleBinding, err = c.client.RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding) return err } -func GetDevOpsProjectsCount(workspaceName string) (int, error) { - _, err := clientset.ClientSets().Devops() - if _, notEnabled := err.(clientset.ClientSetNotEnabledError); notEnabled { - return 0, err +func (c *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string) (int, error) { + if c.db == nil { + return 0, clientset.ErrClientSetNotEnabled } - dbconn, err := clientset.ClientSets().MySQL() - if err != nil { - return 0, err - } - - query := dbconn.Select(devops.DevOpsProjectIdColumn). + query := c.db.Select(devops.DevOpsProjectIdColumn). From(devops.DevOpsProjectTableName). Where(db.And(db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspaceName), db.Eq(devops.StatusColumn, devops.StatusActive))) @@ -192,7 +210,7 @@ func GetDevOpsProjectsCount(workspaceName string) (int, error) { return len(devOpsProjects), nil } -func WorkspaceUserCount(workspace string) (int, error) { +func (c *workspaceOperator) CountUsersInWorkspace(workspace string) (int, error) { count, err := iam.WorkspaceUsersTotalCount(workspace) if err != nil { return 0, err @@ -200,37 +218,21 @@ func WorkspaceUserCount(workspace string) (int, error) { return count, nil } -func GetOrgRolesCount(name string) (int, error) { +func (c *workspaceOperator) CountOrgRoles() (int, error) { return len(constants.WorkSpaceRoles), nil } -func WorkspaceNamespaceCount(workspaceName string) (int, error) { - ns, err := Namespaces(workspaceName) - - namespaces := make([]string, 0) - +func (c *workspaceOperator) CountNamespacesInWorkspace(workspace string) (int, error) { + ns, err := c.ListNamespaces(workspace) if err != nil { return 0, err } - for i := 0; i < len(ns); i++ { - namespaces = append(namespaces, ns[i].Name) - } - - return len(namespaces), nil -} - -func WorkspaceCount() (int, error) { - - ws, err := resources.ListResources("", resources.Workspaces, ¶ms.Conditions{}, "", false, 1, 0) - - if err != nil { - return 0, err - } - - return ws.TotalCount, nil + return len(ns), nil } +/* +// TODO: move to metrics package func GetAllProjectNums() (int, error) { namespaceLister := informers.SharedInformerFactory().Core().V1().Namespaces().Lister() list, err := namespaceLister.List(labels.Everything()) @@ -262,3 +264,13 @@ func GetAllDevOpsProjectsNums() (int, error) { } return len(devOpsProjects), nil } +*/ + +func (c *workspaceOperator) CountWorkspaces() (int, error) { + ws, err := c.ksInformers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything()) + if err != nil { + return 0, err + } + + return len(ws), nil +} diff --git a/pkg/server/config/config.go b/pkg/server/config/config.go index fcba02cc4..4dc1f6a10 100644 --- a/pkg/server/config/config.go +++ b/pkg/server/config/config.go @@ -8,6 +8,7 @@ import ( "k8s.io/klog" "kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/simple/client/alerting" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "kubesphere.io/kubesphere/pkg/simple/client/devops" "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch" "kubesphere.io/kubesphere/pkg/simple/client/k8s" @@ -17,8 +18,7 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/notification" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/prometheus" - "kubesphere.io/kubesphere/pkg/simple/client/redis" - "kubesphere.io/kubesphere/pkg/simple/client/s2is3" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/simple/client/servicemesh" "kubesphere.io/kubesphere/pkg/simple/client/sonarqube" "net/http" @@ -158,25 +158,25 @@ var ( ) type Config struct { - MySQLOptions *mysql.MySQLOptions `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"` - DevopsOptions *devops.DevopsOptions `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"` - SonarQubeOptions *sonarqube.SonarQubeOptions `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"` - KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"` - ServiceMeshOptions *servicemesh.ServiceMeshOptions `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"` - LdapOptions *ldap.LdapOptions `json:"ldap,omitempty" yaml:"ldap,omitempty" mapstructure:"ldap"` - RedisOptions *redis.RedisOptions `json:"redis,omitempty" yaml:"redis,omitempty" mapstructure:"redis"` - S3Options *s2is3.S3Options `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"` - OpenPitrixOptions *openpitrix.OpenPitrixOptions `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"` - MonitoringOptions *prometheus.PrometheusOptions `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"` - LoggingOptions *esclient.ElasticSearchOptions `json:"logging,omitempty" yaml:"logging,omitempty" mapstructure:"logging"` + MySQLOptions *mysql.Options `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"` + DevopsOptions *devops.Options `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"` + SonarQubeOptions *sonarqube.Options `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"` + KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"` + ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"` + LdapOptions *ldap.Options `json:"ldap,omitempty" yaml:"ldap,omitempty" mapstructure:"ldap"` + RedisOptions *cache.Options `json:"redis,omitempty" yaml:"redis,omitempty" mapstructure:"redis"` + S3Options *s3.Options `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"` + OpenPitrixOptions *openpitrix.Options `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"` + MonitoringOptions *prometheus.Options `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"` + LoggingOptions *esclient.Options `json:"logging,omitempty" yaml:"logging,omitempty" mapstructure:"logging"` // Options below are only loaded from configuration file, no command line flags for these options now. - KubeSphereOptions *kubesphere.KubeSphereOptions `json:"-" yaml:"kubesphere,omitempty" mapstructure:"kubesphere"` + KubeSphereOptions *kubesphere.Options `json:"-" yaml:"kubesphere,omitempty" mapstructure:"kubesphere"` // Options used for enabling components, not actually used now. Once we switch Alerting/Notification API to kubesphere, // we can add these options to kubesphere command lines - AlertingOptions *alerting.AlertingOptions `json:"alerting,omitempty" yaml:"alerting,omitempty" mapstructure:"alerting"` - NotificationOptions *notification.NotificationOptions `json:"notification,omitempty" yaml:"notification,omitempty" mapstructure:"notification"` + AlertingOptions *alerting.Options `json:"alerting,omitempty" yaml:"alerting,omitempty" mapstructure:"alerting"` + NotificationOptions *notification.Options `json:"notification,omitempty" yaml:"notification,omitempty" mapstructure:"notification"` } func newConfig() *Config { @@ -187,8 +187,8 @@ func newConfig() *Config { KubernetesOptions: k8s.NewKubernetesOptions(), ServiceMeshOptions: servicemesh.NewServiceMeshOptions(), LdapOptions: ldap.NewLdapOptions(), - RedisOptions: redis.NewRedisOptions(), - S3Options: s2is3.NewS3Options(), + RedisOptions: cache.NewRedisOptions(), + S3Options: s3.NewS3Options(), OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(), MonitoringOptions: prometheus.NewPrometheusOptions(), KubeSphereOptions: kubesphere.NewKubeSphereOptions(), diff --git a/pkg/server/config/config_test.go b/pkg/server/config/config_test.go index f4f266c87..af73477b2 100644 --- a/pkg/server/config/config_test.go +++ b/pkg/server/config/config_test.go @@ -5,6 +5,7 @@ import ( "gopkg.in/yaml.v2" "io/ioutil" "kubesphere.io/kubesphere/pkg/simple/client/alerting" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "kubesphere.io/kubesphere/pkg/simple/client/devops" "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch" "kubesphere.io/kubesphere/pkg/simple/client/k8s" @@ -14,8 +15,7 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/notification" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/prometheus" - "kubesphere.io/kubesphere/pkg/simple/client/redis" - "kubesphere.io/kubesphere/pkg/simple/client/s2is3" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/simple/client/servicemesh" "kubesphere.io/kubesphere/pkg/simple/client/sonarqube" "kubesphere.io/kubesphere/pkg/utils/reflectutils" @@ -26,7 +26,7 @@ import ( func newTestConfig() *Config { conf := &Config{ - MySQLOptions: &mysql.MySQLOptions{ + MySQLOptions: &mysql.Options{ Host: "10.68.96.5:3306", Username: "root", Password: "admin", @@ -34,13 +34,13 @@ func newTestConfig() *Config { MaxOpenConnections: 20, MaxConnectionLifeTime: time.Duration(10) * time.Second, }, - DevopsOptions: &devops.DevopsOptions{ + DevopsOptions: &devops.Options{ Host: "http://ks-devops.kubesphere-devops-system.svc", Username: "jenkins", Password: "kubesphere", MaxConnections: 10, }, - SonarQubeOptions: &sonarqube.SonarQubeOptions{ + SonarQubeOptions: &sonarqube.Options{ Host: "http://sonarqube.kubesphere-devops-system.svc", Token: "ABCDEFG", }, @@ -50,22 +50,22 @@ func newTestConfig() *Config { QPS: 1e6, Burst: 1e6, }, - ServiceMeshOptions: &servicemesh.ServiceMeshOptions{ + ServiceMeshOptions: &servicemesh.Options{ IstioPilotHost: "http://istio-pilot.istio-system.svc:9090", JaegerQueryHost: "http://jaeger-query.istio-system.svc:80", ServicemeshPrometheusHost: "http://prometheus-k8s.kubesphere-monitoring-system.svc", }, - LdapOptions: &ldap.LdapOptions{ + LdapOptions: &ldap.Options{ Host: "http://openldap.kubesphere-system.svc", ManagerDN: "cn=admin,dc=example,dc=org", ManagerPassword: "P@88w0rd", UserSearchBase: "ou=Users,dc=example,dc=org", GroupSearchBase: "ou=Groups,dc=example,dc=org", }, - RedisOptions: &redis.RedisOptions{ + RedisOptions: &cache.Options{ RedisURL: "redis://:qwerty@localhost:6379/1", }, - S3Options: &s2is3.S3Options{ + S3Options: &s3.Options{ Endpoint: "http://minio.openpitrix-system.svc", Region: "", DisableSSL: false, @@ -75,7 +75,7 @@ func newTestConfig() *Config { SessionToken: "abcdefghijklmn", Bucket: "ssss", }, - OpenPitrixOptions: &openpitrix.OpenPitrixOptions{ + OpenPitrixOptions: &openpitrix.Options{ RuntimeManagerEndpoint: "openpitrix-hyperpitrix.openpitrix-system.svc:9103", ClusterManagerEndpoint: "openpitrix-hyperpitrix.openpitrix-system.svc:9104", RepoManagerEndpoint: "openpitrix-hyperpitrix.openpitrix-system.svc:9101", @@ -83,23 +83,23 @@ func newTestConfig() *Config { CategoryManagerEndpoint: "openpitrix-hyperpitrix.openpitrix-system.svc:9113", AttachmentManagerEndpoint: "openpitrix-hyperpitrix.openpitrix-system.svc:9122", }, - MonitoringOptions: &prometheus.PrometheusOptions{ + MonitoringOptions: &prometheus.Options{ Endpoint: "http://prometheus.kubesphere-monitoring-system.svc", SecondaryEndpoint: "http://prometheus.kubesphere-monitoring-system.svc", }, - LoggingOptions: &esclient.ElasticSearchOptions{ + LoggingOptions: &esclient.Options{ Host: "http://elasticsearch-logging.kubesphere-logging-system.svc:9200", IndexPrefix: "elk", Version: "6", }, - KubeSphereOptions: &kubesphere.KubeSphereOptions{ + KubeSphereOptions: &kubesphere.Options{ APIServer: "http://ks-apiserver.kubesphere-system.svc", AccountServer: "http://ks-account.kubesphere-system.svc", }, - AlertingOptions: &alerting.AlertingOptions{ + AlertingOptions: &alerting.Options{ Endpoint: "http://alerting.kubesphere-alerting-system.svc:9200", }, - NotificationOptions: ¬ification.NotificationOptions{ + NotificationOptions: ¬ification.Options{ Endpoint: "http://notification.kubesphere-alerting-system.svc:9200", }, } diff --git a/pkg/server/options/options.go b/pkg/server/options/options.go index c53d15106..06cd91a2c 100644 --- a/pkg/server/options/options.go +++ b/pkg/server/options/options.go @@ -73,11 +73,11 @@ func (s *ServerRunOptions) Validate() []error { return errs } -func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { +func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet, c *ServerRunOptions) { - fs.StringVar(&s.BindAddress, "bind-address", "0.0.0.0", "server bind address") - fs.IntVar(&s.InsecurePort, "insecure-port", 9090, "insecure port number") - fs.IntVar(&s.SecurePort, "secure-port", 0, "secure port number") - fs.StringVar(&s.TlsCertFile, "tls-cert-file", "", "tls cert file") - fs.StringVar(&s.TlsPrivateKey, "tls-private-key", "", "tls private key") + fs.StringVar(&s.BindAddress, "bind-address", c.BindAddress, "server bind address") + fs.IntVar(&s.InsecurePort, "insecure-port", c.InsecurePort, "insecure port number") + fs.IntVar(&s.SecurePort, "secure-port", s.SecurePort, "secure port number") + fs.StringVar(&s.TlsCertFile, "tls-cert-file", c.TlsCertFile, "tls cert file") + fs.StringVar(&s.TlsPrivateKey, "tls-private-key", c.TlsPrivateKey, "tls private key") } diff --git a/pkg/simple/client/alerting/options.go b/pkg/simple/client/alerting/options.go index 5cb9edd70..ccf25c564 100644 --- a/pkg/simple/client/alerting/options.go +++ b/pkg/simple/client/alerting/options.go @@ -1,16 +1,16 @@ package alerting -type AlertingOptions struct { +type Options struct { Endpoint string `json:"endpoint" yaml:"endpoint"` } -func NewAlertingOptions() *AlertingOptions { - return &AlertingOptions{ +func NewAlertingOptions() *Options { + return &Options{ Endpoint: "", } } -func (s *AlertingOptions) ApplyTo(options *AlertingOptions) { +func (s *Options) ApplyTo(options *Options) { if options == nil { options = s return diff --git a/pkg/simple/client/cache/cache.go b/pkg/simple/client/cache/cache.go new file mode 100644 index 000000000..3fcbd90d3 --- /dev/null +++ b/pkg/simple/client/cache/cache.go @@ -0,0 +1,60 @@ +package cache + +import "time" + +type Interface interface { + // Keys retrieves all keys match the given pattern + Keys(pattern string) ([]string, error) + + // Get retrieves the value of the given key, return error if key doesn't exist + Get(key string) (string, error) + + // Set sets the value and living duration of the given key, zero duration means never expire + Set(key string, value string, duration time.Duration) error + + // Del deletes the given key, no error returned if the key doesn't exists + Del(key string) error + + // Exists checks the existence of a give key + Exists(key string) (bool, error) + + // Expires updates object's expiration time, return err if key doesn't exist + Expire(key string, duration time.Duration) error +} + +type simpleObject struct { + value string + expire time.Time +} + +type SimpleCache struct { + store map[string]simpleObject +} + +func NewSimpleCache() Interface { + return &SimpleCache{store: make(map[string]simpleObject)} +} + +func (s *SimpleCache) Keys(pattern string) ([]string, error) { + panic("implement me") +} + +func (s *SimpleCache) Set(key string, value string, duration time.Duration) error { + panic("implement me") +} + +func (s *SimpleCache) Del(key string) error { + panic("implement me") +} + +func (s *SimpleCache) Get(key string) (string, error) { + return "", nil +} + +func (s *SimpleCache) Exists(key string) (bool, error) { + panic("implement me") +} + +func (s *SimpleCache) Expire(key string, duration time.Duration) error { + panic("implement me") +} diff --git a/pkg/simple/client/redis/options.go b/pkg/simple/client/cache/options.go similarity index 67% rename from pkg/simple/client/redis/options.go rename to pkg/simple/client/cache/options.go index a3e9d25de..f4b8730aa 100644 --- a/pkg/simple/client/redis/options.go +++ b/pkg/simple/client/cache/options.go @@ -1,4 +1,4 @@ -package redis +package cache import ( "github.com/go-redis/redis" @@ -6,20 +6,20 @@ import ( "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -type RedisOptions struct { +type Options struct { RedisURL string } // NewRedisOptions returns options points to nowhere, // because redis is not required for some components -func NewRedisOptions() *RedisOptions { - return &RedisOptions{ +func NewRedisOptions() *Options { + return &Options{ RedisURL: "", } } // Validate check options -func (r *RedisOptions) Validate() []error { +func (r *Options) Validate() []error { errors := make([]error, 0) _, err := redis.ParseURL(r.RedisURL) @@ -32,7 +32,7 @@ func (r *RedisOptions) Validate() []error { } // ApplyTo apply to another options if it's a enabled option(non empty host) -func (r *RedisOptions) ApplyTo(options *RedisOptions) { +func (r *Options) ApplyTo(options *Options) { if r.RedisURL != "" { reflectutils.Override(options, r) } @@ -40,7 +40,7 @@ func (r *RedisOptions) ApplyTo(options *RedisOptions) { // AddFlags add option flags to command line flags, // if redis-host left empty, the following options will be ignored. -func (r *RedisOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&r.RedisURL, "redis-url", "", "Redis connection URL. If left blank, means redis is unnecessary, "+ +func (r *Options) AddFlags(fs *pflag.FlagSet, s *Options) { + fs.StringVar(&r.RedisURL, "redis-url", s.RedisURL, "Redis connection URL. If left blank, means redis is unnecessary, "+ "redis will be disabled. e.g. redis://:password@host:port/db") } diff --git a/pkg/simple/client/redis/redis.go b/pkg/simple/client/cache/redis.go similarity index 58% rename from pkg/simple/client/redis/redis.go rename to pkg/simple/client/cache/redis.go index 4a1fb83b3..e01c3793c 100644 --- a/pkg/simple/client/redis/redis.go +++ b/pkg/simple/client/cache/redis.go @@ -15,28 +15,20 @@ limitations under the License. */ -package redis +package cache import ( "github.com/go-redis/redis" "k8s.io/klog" + "time" ) -type RedisClient struct { +type Client struct { client *redis.Client } -func NewRedisClientOrDie(options *RedisOptions, stopCh <-chan struct{}) *RedisClient { - client, err := NewRedisClient(options, stopCh) - if err != nil { - panic(err) - } - - return client -} - -func NewRedisClient(option *RedisOptions, stopCh <-chan struct{}) (*RedisClient, error) { - var r RedisClient +func NewRedisClient(option *Options, stopCh <-chan struct{}) (Interface, error) { + var r Client options, err := redis.ParseURL(option.RedisURL) @@ -45,6 +37,10 @@ func NewRedisClient(option *RedisOptions, stopCh <-chan struct{}) (*RedisClient, return nil, err } + if stopCh == nil { + klog.Warningf("no stop signal passed, may cause redis connections leaked") + } + r.client = redis.NewClient(options) if err := r.client.Ping().Err(); err != nil { @@ -53,6 +49,7 @@ func NewRedisClient(option *RedisOptions, stopCh <-chan struct{}) (*RedisClient, return nil, err } + // close redis in case of connection leak if stopCh != nil { go func() { <-stopCh @@ -65,6 +62,26 @@ func NewRedisClient(option *RedisOptions, stopCh <-chan struct{}) (*RedisClient, return &r, nil } -func (r *RedisClient) Redis() *redis.Client { - return r.client +func (r *Client) Get(key string) (string, error) { + return "", nil +} + +func (r *Client) Keys(pattern string) ([]string, error) { + panic("implement me") +} + +func (r *Client) Set(key string, value string, duration time.Duration) error { + panic("implement me") +} + +func (r *Client) Del(key string) error { + panic("implement me") +} + +func (r *Client) Exists(key string) (bool, error) { + panic("implement me") +} + +func (r *Client) Expire(key string, duration time.Duration) error { + panic("implement me") } diff --git a/pkg/simple/client/db/db.go b/pkg/simple/client/db/db.go new file mode 100644 index 000000000..8ce9a0c7e --- /dev/null +++ b/pkg/simple/client/db/db.go @@ -0,0 +1,5 @@ +package db + +// +type Interface interface { +} diff --git a/pkg/simple/client/devops/devops.go b/pkg/simple/client/devops/devops.go index 6b5952499..90c03ae61 100644 --- a/pkg/simple/client/devops/devops.go +++ b/pkg/simple/client/devops/devops.go @@ -21,15 +21,15 @@ import ( ) const ( - JenkinsAllUserRoleName = "kubesphere-user" + jenkinsAllUserRoleName = "kubesphere-user" ) -type DevopsClient struct { +type Client struct { jenkinsClient *gojenkins.Jenkins } -func NewDevopsClient(options *DevopsOptions) (*DevopsClient, error) { - var d DevopsClient +func NewDevopsClient(options *Options) (*Client, error) { + var d Client jenkins := gojenkins.CreateJenkins(nil, options.Host, options.MaxConnections, options.Username, options.Password) jenkins, err := jenkins.Init() @@ -49,34 +49,13 @@ func NewDevopsClient(options *DevopsOptions) (*DevopsClient, error) { return &d, nil } -func NewDevopsClientOrDie(options *DevopsOptions) *DevopsClient { - jenkins := gojenkins.CreateJenkins(nil, options.Host, options.MaxConnections, options.Username, options.Password) - jenkins, err := jenkins.Init() - if err != nil { - klog.Errorf("failed to connecto to jenkins role, %+v", err) - panic(err) - } - - d := &DevopsClient{ - jenkinsClient: jenkins, - } - - err = d.initializeJenkins() - if err != nil { - klog.Error(err) - panic(err) - } - - return d -} - -func (c *DevopsClient) Jenkins() *gojenkins.Jenkins { +func (c *Client) Jenkins() *gojenkins.Jenkins { return c.jenkinsClient } var mutex = sync.Mutex{} -func (c *DevopsClient) initializeJenkins() error { +func (c *Client) initializeJenkins() error { mutex.Lock() defer mutex.Unlock() @@ -84,7 +63,7 @@ func (c *DevopsClient) initializeJenkins() error { return fmt.Errorf("jenkins intialization failed") } - globalRole, err := c.jenkinsClient.GetGlobalRole(JenkinsAllUserRoleName) + globalRole, err := c.jenkinsClient.GetGlobalRole(jenkinsAllUserRoleName) if err != nil { klog.Error(err) return err @@ -92,14 +71,14 @@ func (c *DevopsClient) initializeJenkins() error { // Jenkins uninitialized, create global role if globalRole == nil { - _, err := c.jenkinsClient.AddGlobalRole(JenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{GlobalRead: true}, true) + _, err := c.jenkinsClient.AddGlobalRole(jenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{GlobalRead: true}, true) if err != nil { klog.Error(err) return err } } - _, err = c.jenkinsClient.AddProjectRole(JenkinsAllUserRoleName, "\\n\\s*\\r", gojenkins.ProjectPermissionIds{SCMTag: true}, true) + _, err = c.jenkinsClient.AddProjectRole(jenkinsAllUserRoleName, "\\n\\s*\\r", gojenkins.ProjectPermissionIds{SCMTag: true}, true) if err != nil { klog.Error(err) return err diff --git a/pkg/simple/client/devops/interface.go b/pkg/simple/client/devops/interface.go new file mode 100644 index 000000000..e6e83bfd3 --- /dev/null +++ b/pkg/simple/client/devops/interface.go @@ -0,0 +1,18 @@ +package devops + +type Job struct { +} + +type Interface interface { + GetJob(projectId, pipelineName string) (*Job, error) + + DeleteJob(projectId, pipelineId string) (bool, error) + + CreateJobInFolder() + + GetGlobalRole(roleName string) + + AddGlobalRole(roleName string, permission string) + + GetProjectRole(roleName string) +} diff --git a/pkg/simple/client/devops/options.go b/pkg/simple/client/devops/options.go index 3919fadd8..e3b1bd092 100644 --- a/pkg/simple/client/devops/options.go +++ b/pkg/simple/client/devops/options.go @@ -6,7 +6,7 @@ import ( "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -type DevopsOptions struct { +type Options struct { Host string `json:",omitempty" yaml:"host" description:"Jenkins service host address"` Username string `json:",omitempty" yaml:"username" description:"Jenkins admin username"` Password string `json:",omitempty" yaml:"password" description:"Jenkins admin password"` @@ -14,8 +14,8 @@ type DevopsOptions struct { } // NewDevopsOptions returns a `zero` instance -func NewDevopsOptions() *DevopsOptions { - return &DevopsOptions{ +func NewDevopsOptions() *Options { + return &Options{ Host: "", Username: "", Password: "", @@ -24,15 +24,15 @@ func NewDevopsOptions() *DevopsOptions { } // ApplyTo apply configuration to another options -func (s *DevopsOptions) ApplyTo(options *DevopsOptions) { +func (s *Options) ApplyTo(options *Options) { if s.Host != "" { reflectutils.Override(options, s) } } // Validate check if there is misconfiguration in options -func (s *DevopsOptions) Validate() []error { - errors := []error{} +func (s *Options) Validate() []error { + var errors []error // devops is not needed, ignore rest options if s.Host == "" { @@ -50,18 +50,18 @@ func (s *DevopsOptions) Validate() []error { return errors } -func (s *DevopsOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Host, "jenkins-host", s.Host, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.Host, "jenkins-host", c.Host, ""+ "Jenkins service host address. If left blank, means Jenkins "+ "is unnecessary.") - fs.StringVar(&s.Username, "jenkins-username", s.Username, ""+ + fs.StringVar(&s.Username, "jenkins-username", c.Username, ""+ "Username for access to Jenkins service. Leave it blank if there isn't any.") - fs.StringVar(&s.Password, "jenkins-password", s.Password, ""+ + fs.StringVar(&s.Password, "jenkins-password", c.Password, ""+ "Password for access to Jenkins service, used pair with username.") - fs.IntVar(&s.MaxConnections, "jenkins-max-connections", s.MaxConnections, ""+ + fs.IntVar(&s.MaxConnections, "jenkins-max-connections", c.MaxConnections, ""+ "Maximum allowed connections to Jenkins. ") } diff --git a/pkg/simple/client/elasticsearch/esclient.go b/pkg/simple/client/elasticsearch/esclient.go index cb5fd1711..6b8dd19a8 100644 --- a/pkg/simple/client/elasticsearch/esclient.go +++ b/pkg/simple/client/elasticsearch/esclient.go @@ -59,7 +59,7 @@ type ElasticSearchClient struct { client Client } -func NewLoggingClient(options *ElasticSearchOptions) (*ElasticSearchClient, error) { +func NewLoggingClient(options *Options) (*ElasticSearchClient, error) { var version, index string esClient := &ElasticSearchClient{} diff --git a/pkg/simple/client/elasticsearch/options.go b/pkg/simple/client/elasticsearch/options.go index 0ae93442d..3e3ec10ab 100644 --- a/pkg/simple/client/elasticsearch/options.go +++ b/pkg/simple/client/elasticsearch/options.go @@ -5,42 +5,42 @@ import ( "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -type ElasticSearchOptions struct { +type Options struct { Host string `json:"host" yaml:"host"` IndexPrefix string `json:"indexPrefix,omitempty" yaml:"indexPrefix"` Version string `json:"version" yaml:"version"` } -func NewElasticSearchOptions() *ElasticSearchOptions { - return &ElasticSearchOptions{ +func NewElasticSearchOptions() *Options { + return &Options{ Host: "", IndexPrefix: "fluentbit", Version: "", } } -func (s *ElasticSearchOptions) ApplyTo(options *ElasticSearchOptions) { +func (s *Options) ApplyTo(options *Options) { if s.Host != "" { reflectutils.Override(options, s) } } -func (s *ElasticSearchOptions) Validate() []error { +func (s *Options) Validate() []error { errs := []error{} return errs } -func (s *ElasticSearchOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Host, "elasticsearch-host", s.Host, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.Host, "elasticsearch-host", c.Host, ""+ "ElasticSearch logging service host. KubeSphere is using elastic as log store, "+ "if this filed left blank, KubeSphere will use kubernetes builtin log API instead, and"+ " the following elastic search options will be ignored.") - fs.StringVar(&s.IndexPrefix, "index-prefix", s.IndexPrefix, ""+ + fs.StringVar(&s.IndexPrefix, "index-prefix", c.IndexPrefix, ""+ "Index name prefix. KubeSphere will retrieve logs against indices matching the prefix.") - fs.StringVar(&s.Version, "elasticsearch-version", s.Version, ""+ + fs.StringVar(&s.Version, "elasticsearch-version", c.Version, ""+ "ElasticSearch major version, e.g. 5/6/7, if left blank, will detect automatically."+ "Currently, minimum supported version is 5.x") } diff --git a/pkg/simple/client/factory.go b/pkg/simple/client/factory.go index 6fadb2c58..55fd9f3ee 100644 --- a/pkg/simple/client/factory.go +++ b/pkg/simple/client/factory.go @@ -1,8 +1,8 @@ package client import ( - "fmt" - goredis "github.com/go-redis/redis" + "errors" + "kubesphere.io/kubesphere/pkg/simple/client/cache" "kubesphere.io/kubesphere/pkg/simple/client/devops" esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch" "kubesphere.io/kubesphere/pkg/simple/client/k8s" @@ -11,43 +11,36 @@ import ( "kubesphere.io/kubesphere/pkg/simple/client/mysql" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/prometheus" - "kubesphere.io/kubesphere/pkg/simple/client/redis" - "kubesphere.io/kubesphere/pkg/simple/client/s2is3" + "kubesphere.io/kubesphere/pkg/simple/client/s3" "kubesphere.io/kubesphere/pkg/simple/client/sonarqube" "sync" ) -type ClientSetNotEnabledError struct { - err error -} - -func (e ClientSetNotEnabledError) Error() string { - return fmt.Sprintf("client set not enabled: %v", e.err) -} +var ErrClientSetNotEnabled = errors.New("client set not enabled") type ClientSetOptions struct { - mySQLOptions *mysql.MySQLOptions - redisOptions *redis.RedisOptions + mySQLOptions *mysql.Options + redisOptions *cache.Options kubernetesOptions *k8s.KubernetesOptions - devopsOptions *devops.DevopsOptions - sonarqubeOptions *sonarqube.SonarQubeOptions - ldapOptions *ldap.LdapOptions - s3Options *s2is3.S3Options - openPitrixOptions *openpitrix.OpenPitrixOptions - prometheusOptions *prometheus.PrometheusOptions - kubesphereOptions *kubesphere.KubeSphereOptions - elasticSearhOptions *esclient.ElasticSearchOptions + devopsOptions *devops.Options + sonarqubeOptions *sonarqube.Options + ldapOptions *ldap.Options + s3Options *s3.Options + openPitrixOptions *openpitrix.Options + prometheusOptions *prometheus.Options + kubesphereOptions *kubesphere.Options + elasticSearhOptions *esclient.Options } func NewClientSetOptions() *ClientSetOptions { return &ClientSetOptions{ mySQLOptions: mysql.NewMySQLOptions(), - redisOptions: redis.NewRedisOptions(), + redisOptions: cache.NewRedisOptions(), kubernetesOptions: k8s.NewKubernetesOptions(), ldapOptions: ldap.NewLdapOptions(), devopsOptions: devops.NewDevopsOptions(), sonarqubeOptions: sonarqube.NewSonarQubeOptions(), - s3Options: s2is3.NewS3Options(), + s3Options: s3.NewS3Options(), openPitrixOptions: openpitrix.NewOpenPitrixOptions(), prometheusOptions: prometheus.NewPrometheusOptions(), kubesphereOptions: kubesphere.NewKubeSphereOptions(), @@ -55,12 +48,12 @@ func NewClientSetOptions() *ClientSetOptions { } } -func (c *ClientSetOptions) SetMySQLOptions(options *mysql.MySQLOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetMySQLOptions(options *mysql.Options) *ClientSetOptions { c.mySQLOptions = options return c } -func (c *ClientSetOptions) SetRedisOptions(options *redis.RedisOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetRedisOptions(options *cache.Options) *ClientSetOptions { c.redisOptions = options return c } @@ -70,42 +63,42 @@ func (c *ClientSetOptions) SetKubernetesOptions(options *k8s.KubernetesOptions) return c } -func (c *ClientSetOptions) SetDevopsOptions(options *devops.DevopsOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetDevopsOptions(options *devops.Options) *ClientSetOptions { c.devopsOptions = options return c } -func (c *ClientSetOptions) SetLdapOptions(options *ldap.LdapOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetLdapOptions(options *ldap.Options) *ClientSetOptions { c.ldapOptions = options return c } -func (c *ClientSetOptions) SetS3Options(options *s2is3.S3Options) *ClientSetOptions { +func (c *ClientSetOptions) SetS3Options(options *s3.Options) *ClientSetOptions { c.s3Options = options return c } -func (c *ClientSetOptions) SetOpenPitrixOptions(options *openpitrix.OpenPitrixOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetOpenPitrixOptions(options *openpitrix.Options) *ClientSetOptions { c.openPitrixOptions = options return c } -func (c *ClientSetOptions) SetPrometheusOptions(options *prometheus.PrometheusOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetPrometheusOptions(options *prometheus.Options) *ClientSetOptions { c.prometheusOptions = options return c } -func (c *ClientSetOptions) SetSonarQubeOptions(options *sonarqube.SonarQubeOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetSonarQubeOptions(options *sonarqube.Options) *ClientSetOptions { c.sonarqubeOptions = options return c } -func (c *ClientSetOptions) SetKubeSphereOptions(options *kubesphere.KubeSphereOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetKubeSphereOptions(options *kubesphere.Options) *ClientSetOptions { c.kubesphereOptions = options return c } -func (c *ClientSetOptions) SetElasticSearchOptions(options *esclient.ElasticSearchOptions) *ClientSetOptions { +func (c *ClientSetOptions) SetElasticSearchOptions(options *esclient.Options) *ClientSetOptions { c.elasticSearhOptions = options return c } @@ -117,17 +110,17 @@ type ClientSet struct { csoptions *ClientSetOptions stopCh <-chan struct{} - mySQLClient *mysql.MySQLClient + mySQLClient *mysql.Client - k8sClient *k8s.KubernetesClient - ldapClient *ldap.LdapClient - devopsClient *devops.DevopsClient - sonarQubeClient *sonarqube.SonarQubeClient - redisClient *redis.RedisClient - s3Client *s2is3.S3Client - prometheusClient *prometheus.PrometheusClient - openpitrixClient *openpitrix.OpenPitrixClient - kubesphereClient *kubesphere.KubeSphereClient + k8sClient k8s.Client + ldapClient *ldap.Client + devopsClient *devops.Client + sonarQubeClient *sonarqube.Client + redisClient cache.Interface + s3Client s3.Interface + prometheusClient *prometheus.Client + openpitrixClient *openpitrix.Client + kubesphereClient *kubesphere.Client elasticSearchClient *esclient.ElasticSearchClient } @@ -159,7 +152,7 @@ func (cs *ClientSet) MySQL() (*mysql.Database, error) { var err error if cs.csoptions.mySQLOptions == nil || cs.csoptions.mySQLOptions.Host == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.mySQLClient != nil { @@ -178,34 +171,34 @@ func (cs *ClientSet) MySQL() (*mysql.Database, error) { } } -func (cs *ClientSet) Redis() (*goredis.Client, error) { +func (cs *ClientSet) Cache() (cache.Interface, error) { var err error if cs.csoptions.redisOptions == nil || cs.csoptions.redisOptions.RedisURL == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.redisClient != nil { - return cs.redisClient.Redis(), nil + return cs.redisClient, nil } else { mutex.Lock() defer mutex.Unlock() if cs.redisClient == nil { - cs.redisClient, err = redis.NewRedisClient(cs.csoptions.redisOptions, cs.stopCh) + cs.redisClient, err = cache.NewRedisClient(cs.csoptions.redisOptions, cs.stopCh) if err != nil { return nil, err } } - return cs.redisClient.Redis(), nil + return cs.redisClient, nil } } -func (cs *ClientSet) Devops() (*devops.DevopsClient, error) { +func (cs *ClientSet) Devops() (*devops.Client, error) { var err error if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.devopsClient != nil { @@ -224,11 +217,11 @@ func (cs *ClientSet) Devops() (*devops.DevopsClient, error) { } } -func (cs *ClientSet) SonarQube() (*sonarqube.SonarQubeClient, error) { +func (cs *ClientSet) SonarQube() (*sonarqube.Client, error) { var err error if cs.csoptions.sonarqubeOptions == nil || cs.csoptions.sonarqubeOptions.Host == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.sonarQubeClient != nil { @@ -247,11 +240,11 @@ func (cs *ClientSet) SonarQube() (*sonarqube.SonarQubeClient, error) { } } -func (cs *ClientSet) Ldap() (*ldap.LdapClient, error) { +func (cs *ClientSet) Ldap() (*ldap.Client, error) { var err error if cs.csoptions.ldapOptions == nil || cs.csoptions.ldapOptions.Host == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.ldapClient != nil { @@ -272,15 +265,15 @@ func (cs *ClientSet) Ldap() (*ldap.LdapClient, error) { // since kubernetes client is required, we will // create it on setup -func (cs *ClientSet) K8s() *k8s.KubernetesClient { +func (cs *ClientSet) K8s() k8s.Client { return cs.k8sClient } -func (cs *ClientSet) S3() (*s2is3.S3Client, error) { +func (cs *ClientSet) S3() (s3.Interface, error) { var err error if cs.csoptions.s3Options == nil || cs.csoptions.s3Options.Endpoint == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.s3Client != nil { @@ -290,7 +283,7 @@ func (cs *ClientSet) S3() (*s2is3.S3Client, error) { defer mutex.Unlock() if cs.s3Client == nil { - cs.s3Client, err = s2is3.NewS3Client(cs.csoptions.s3Options) + cs.s3Client, err = s3.NewS3Client(cs.csoptions.s3Options) if err != nil { return nil, err } @@ -299,7 +292,7 @@ func (cs *ClientSet) S3() (*s2is3.S3Client, error) { } } -func (cs *ClientSet) OpenPitrix() (*openpitrix.OpenPitrixClient, error) { +func (cs *ClientSet) OpenPitrix() (*openpitrix.Client, error) { var err error if cs.csoptions.openPitrixOptions == nil || @@ -310,7 +303,7 @@ func (cs *ClientSet) OpenPitrix() (*openpitrix.OpenPitrixClient, error) { cs.csoptions.openPitrixOptions.AttachmentManagerEndpoint == "" || cs.csoptions.openPitrixOptions.RepoIndexerEndpoint == "" || cs.csoptions.openPitrixOptions.CategoryManagerEndpoint == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.openpitrixClient != nil { @@ -325,11 +318,11 @@ func (cs *ClientSet) OpenPitrix() (*openpitrix.OpenPitrixClient, error) { } } -func (cs *ClientSet) Prometheus() (*prometheus.PrometheusClient, error) { +func (cs *ClientSet) Prometheus() (*prometheus.Client, error) { var err error if cs.csoptions.prometheusOptions == nil || cs.csoptions.prometheusOptions.Endpoint == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.prometheusClient != nil { @@ -348,7 +341,7 @@ func (cs *ClientSet) Prometheus() (*prometheus.PrometheusClient, error) { } } -func (cs *ClientSet) KubeSphere() *kubesphere.KubeSphereClient { +func (cs *ClientSet) KubeSphere() *kubesphere.Client { return cs.kubesphereClient } @@ -356,7 +349,7 @@ func (cs *ClientSet) ElasticSearch() (*esclient.ElasticSearchClient, error) { var err error if cs.csoptions.elasticSearhOptions == nil || cs.csoptions.elasticSearhOptions.Host == "" { - return nil, ClientSetNotEnabledError{} + return nil, ErrClientSetNotEnabled } if cs.elasticSearchClient != nil { diff --git a/pkg/simple/client/fluentbit/fluentbitcrdclient.go b/pkg/simple/client/fluentbit/fluentbitcrdclient.go deleted file mode 100644 index 9cb26dab4..000000000 --- a/pkg/simple/client/fluentbit/fluentbitcrdclient.go +++ /dev/null @@ -1,288 +0,0 @@ -/* -Copyright 2018 The KubeSphere Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package fluentbitclient - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/clientcmd" - "time" -) - -const ( - CRDPlural string = "fluentbits" - CRDGroup string = "logging.kubesphere.io" - CRDVersion string = "v1alpha1" - FullCRDName string = CRDPlural + "." + CRDGroup -) - -// FluentBitList auto generated by the sdk -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type FluentBitList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - Items []FluentBit `json:"items"` -} - -// FluentBit auto generated by the sdk -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type FluentBit struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata"` - Spec FluentBitSpec `json:"spec"` - Status FluentBitStatus `json:"status,omitempty"` -} - -// FluentBitSpec holds the spec for the operator -type FluentBitSpec struct { - Service []Plugin `json:"service"` - Input []Plugin `json:"input"` - Filter []Plugin `json:"filter"` - Output []Plugin `json:"output"` - Settings []Plugin `json:"settings"` -} - -// FluentBitStatus holds the status info for the operator -type FluentBitStatus struct { - // Fill me -} - -// Plugin struct for fluent-bit plugins -type Plugin struct { - Type string `json:"type" description:"output plugin type, eg. fluentbit-output-es"` - Name string `json:"name" description:"output plugin name, eg. fluentbit-output-es"` - Parameters []Parameter `json:"parameters" description:"output plugin configuration parameters"` -} - -// Fluent-bit output plugins -type OutputPlugin struct { - Plugin - Id string `json:"id,omitempty" description:"output uuid"` - Enable bool `json:"enable" description:"active status, one of true, false"` - Updatetime time.Time `json:"updatetime,omitempty" description:"last updatetime"` -} - -// Parameter generic parameter type to handle values from different sources -type Parameter struct { - Name string `json:"name" description:"configuration parameter key, eg. Name. refer to Fluent bit's Output Plugins Section for more configuration parameters."` - ValueFrom *ValueFrom `json:"valueFrom,omitempty"` - Value string `json:"value" description:"configuration parameter value, eg. es. refer to Fluent bit's Output Plugins Section for more configuration parameters."` -} - -// ValueFrom generic type to determine value origin -type ValueFrom struct { - SecretKeyRef KubernetesSecret `json:"secretKeyRef"` -} - -// KubernetesSecret is a ValueFrom type -type KubernetesSecret struct { - Name string `json:"name"` - Key string `json:"key"` - Namespace string `json:"namespace"` -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentBit) DeepCopyInto(out *FluentBit) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec - out.Status = in.Status - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBit. -func (in *FluentBit) DeepCopy() *FluentBit { - if in == nil { - return nil - } - out := new(FluentBit) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *FluentBit) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentBitList) DeepCopyInto(out *FluentBitList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]FluentBit, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitList. -func (in *FluentBitList) DeepCopy() *FluentBitList { - if in == nil { - return nil - } - out := new(FluentBitList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *FluentBitList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentBitSpec) DeepCopyInto(out *FluentBitSpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitSpec. -func (in *FluentBitSpec) DeepCopy() *FluentBitSpec { - if in == nil { - return nil - } - out := new(FluentBitSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FluentBitStatus) DeepCopyInto(out *FluentBitStatus) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitStatus. -func (in *FluentBitStatus) DeepCopy() *FluentBitStatus { - if in == nil { - return nil - } - out := new(FluentBitStatus) - in.DeepCopyInto(out) - return out -} - -// Create a Rest client with the new CRD Schema -var SchemeGroupVersion = schema.GroupVersion{Group: CRDGroup, Version: CRDVersion} - -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(SchemeGroupVersion, - &FluentBit{}, - &FluentBitList{}, - ) - metav1.AddToGroupVersion(scheme, SchemeGroupVersion) - return nil -} - -func NewFluentbitCRDClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) { - scheme := runtime.NewScheme() - SchemeBuilder := runtime.NewSchemeBuilder(addKnownTypes) - if err := SchemeBuilder.AddToScheme(scheme); err != nil { - return nil, nil, err - } - config := *cfg - config.GroupVersion = &SchemeGroupVersion - config.APIPath = "/apis" - config.ContentType = runtime.ContentTypeJSON - config.NegotiatedSerializer = serializer.NewCodecFactory(runtime.NewScheme()).WithoutConversion() - - client, err := rest.RESTClientFor(&config) - if err != nil { - return nil, nil, err - } - return client, scheme, nil -} - -// This file implement all the (CRUD) client methods we need to access our CRD object - -func CrdClient(cl *rest.RESTClient, scheme *runtime.Scheme, namespace string) *crdclient { - return &crdclient{cl: cl, ns: namespace, plural: CRDPlural, - codec: runtime.NewParameterCodec(scheme)} -} - -type crdclient struct { - cl *rest.RESTClient - ns string - plural string - codec runtime.ParameterCodec -} - -func (f *crdclient) Create(obj *FluentBit) (*FluentBit, error) { - var result FluentBit - err := f.cl.Post(). - Namespace(f.ns).Resource(f.plural). - Body(obj).Do().Into(&result) - return &result, err -} - -func (f *crdclient) Update(name string, obj *FluentBit) (*FluentBit, error) { - var result FluentBit - err := f.cl.Put(). - Namespace(f.ns).Resource(f.plural). - Name(name).Body(obj).Do().Into(&result) - return &result, err -} - -func (f *crdclient) Delete(name string, options *metav1.DeleteOptions) error { - return f.cl.Delete(). - Namespace(f.ns).Resource(f.plural). - Name(name).Body(options).Do(). - Error() -} - -func (f *crdclient) Get(name string) (*FluentBit, error) { - var result FluentBit - err := f.cl.Get(). - Namespace(f.ns).Resource(f.plural). - Name(name).Do().Into(&result) - return &result, err -} - -func (f *crdclient) List(opts metav1.ListOptions) (*FluentBitList, error) { - var result FluentBitList - err := f.cl.Get(). - Namespace(f.ns).Resource(f.plural). - VersionedParams(&opts, f.codec). - Do().Into(&result) - return &result, err -} - -// Create a new List watch for our TPR -func (f *crdclient) NewListWatch() *cache.ListWatch { - return cache.NewListWatchFromClient(f.cl, f.plural, f.ns, fields.Everything()) -} - -// return rest config, if path not specified assume in cluster config -func GetClientConfig(kubeconfig string) (*rest.Config, error) { - if kubeconfig != "" { - return clientcmd.BuildConfigFromFlags("", kubeconfig) - } - return rest.InClusterConfig() -} diff --git a/pkg/simple/client/k8s/kubernetes.go b/pkg/simple/client/k8s/kubernetes.go index a203eb61e..7708360f2 100644 --- a/pkg/simple/client/k8s/kubernetes.go +++ b/pkg/simple/client/k8s/kubernetes.go @@ -11,7 +11,17 @@ import ( "strings" ) -type KubernetesClient struct { +type Client interface { + Kubernetes() kubernetes.Interface + KubeSphere() kubesphere.Interface + S2i() s2i.Interface + Application() applicationclientset.Interface + Discovery() discovery.DiscoveryInterface + Master() string + Config() *rest.Config +} + +type kubernetesClient struct { // kubernetes client interface k8s *kubernetes.Clientset @@ -31,7 +41,7 @@ type KubernetesClient struct { } // NewKubernetesClientOrDie creates KubernetesClient and panic if there is an error -func NewKubernetesClientOrDie(options *KubernetesOptions) *KubernetesClient { +func NewKubernetesClientOrDie(options *KubernetesOptions) Client { config, err := clientcmd.BuildConfigFromFlags("", options.KubeConfig) if err != nil { panic(err) @@ -40,7 +50,7 @@ func NewKubernetesClientOrDie(options *KubernetesOptions) *KubernetesClient { config.QPS = options.QPS config.Burst = options.Burst - k := &KubernetesClient{ + k := &kubernetesClient{ k8s: kubernetes.NewForConfigOrDie(config), discoveryClient: discovery.NewDiscoveryClientForConfigOrDie(config), ks: kubesphere.NewForConfigOrDie(config), @@ -63,7 +73,7 @@ func NewKubernetesClientOrDie(options *KubernetesOptions) *KubernetesClient { } // NewKubernetesClient creates a KubernetesClient -func NewKubernetesClient(options *KubernetesOptions) (*KubernetesClient, error) { +func NewKubernetesClient(options *KubernetesOptions) (Client, error) { config, err := clientcmd.BuildConfigFromFlags("", options.KubeConfig) if err != nil { return nil, err @@ -72,7 +82,7 @@ func NewKubernetesClient(options *KubernetesOptions) (*KubernetesClient, error) config.QPS = options.QPS config.Burst = options.Burst - var k KubernetesClient + var k kubernetesClient k.k8s, err = kubernetes.NewForConfig(config) if err != nil { return nil, err @@ -99,31 +109,31 @@ func NewKubernetesClient(options *KubernetesOptions) (*KubernetesClient, error) return &k, nil } -func (k *KubernetesClient) Kubernetes() kubernetes.Interface { +func (k *kubernetesClient) Kubernetes() kubernetes.Interface { return k.k8s } -func (k *KubernetesClient) Discovery() discovery.DiscoveryInterface { +func (k *kubernetesClient) Discovery() discovery.DiscoveryInterface { return k.discoveryClient } -func (k *KubernetesClient) KubeSphere() kubesphere.Interface { +func (k *kubernetesClient) KubeSphere() kubesphere.Interface { return k.ks } -func (k *KubernetesClient) S2i() s2i.Interface { +func (k *kubernetesClient) S2i() s2i.Interface { return k.s2i } -func (k *KubernetesClient) Application() applicationclientset.Interface { +func (k *kubernetesClient) Application() applicationclientset.Interface { return k.application } // master address used to generate kubeconfig for downloading -func (k *KubernetesClient) Master() string { +func (k *kubernetesClient) Master() string { return k.master } -func (k *KubernetesClient) Config() *rest.Config { +func (k *kubernetesClient) Config() *rest.Config { return k.config } diff --git a/pkg/simple/client/k8s/options.go b/pkg/simple/client/k8s/options.go index 6b0a12bdf..e167d5ca5 100644 --- a/pkg/simple/client/k8s/options.go +++ b/pkg/simple/client/k8s/options.go @@ -49,11 +49,11 @@ func (k *KubernetesOptions) ApplyTo(options *KubernetesOptions) { reflectutils.Override(options, k) } -func (k *KubernetesOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&k.KubeConfig, "kubeconfig", k.KubeConfig, ""+ +func (k *KubernetesOptions) AddFlags(fs *pflag.FlagSet, c *KubernetesOptions) { + fs.StringVar(&k.KubeConfig, "kubeconfig", c.KubeConfig, ""+ "Path for kubernetes kubeconfig file, if left blank, will use "+ "in cluster way.") - fs.StringVar(&k.Master, "master", k.Master, ""+ + fs.StringVar(&k.Master, "master", c.Master, ""+ "Used to generate kubeconfig for downloading, if not specified, will use host in kubeconfig.") } diff --git a/pkg/simple/client/kubesphere/kubesphere.go b/pkg/simple/client/kubesphere/kubesphere.go index c7024e77f..c4a9c54f5 100644 --- a/pkg/simple/client/kubesphere/kubesphere.go +++ b/pkg/simple/client/kubesphere/kubesphere.go @@ -40,15 +40,15 @@ type Interface interface { DeleteWorkspaceDevOpsProjects(workspace, devops string) error } -type KubeSphereClient struct { +type Client struct { client *http.Client apiServer string accountServer string } -func NewKubeSphereClient(options *KubeSphereOptions) *KubeSphereClient { - return &KubeSphereClient{ +func NewKubeSphereClient(options *Options) *Client { + return &Client{ client: &http.Client{}, apiServer: options.APIServer, accountServer: options.AccountServer, @@ -64,7 +64,7 @@ func (e Error) Error() string { return fmt.Sprintf("status: %d,message: %s", e.status, e.message) } -func (c *KubeSphereClient) CreateGroup(group *models.Group) (*models.Group, error) { +func (c *Client) CreateGroup(group *models.Group) (*models.Group, error) { data, err := json.Marshal(group) if err != nil { return nil, err @@ -106,7 +106,7 @@ func (c *KubeSphereClient) CreateGroup(group *models.Group) (*models.Group, erro return group, nil } -func (c *KubeSphereClient) UpdateGroup(group *models.Group) (*models.Group, error) { +func (c *Client) UpdateGroup(group *models.Group) (*models.Group, error) { data, err := json.Marshal(group) if err != nil { @@ -149,7 +149,7 @@ func (c *KubeSphereClient) UpdateGroup(group *models.Group) (*models.Group, erro return group, nil } -func (c *KubeSphereClient) DeleteGroup(name string) error { +func (c *Client) DeleteGroup(name string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/kapis/iam.kubesphere.io/v1alpha2/groups/%s", c.accountServer, name), nil) if err != nil { @@ -178,7 +178,7 @@ func (c *KubeSphereClient) DeleteGroup(name string) error { return nil } -func (c *KubeSphereClient) DescribeGroup(name string) (*models.Group, error) { +func (c *Client) DescribeGroup(name string) (*models.Group, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/kapis/iam.kubesphere.io/v1alpha2/groups/%s", c.accountServer, name), nil) if err != nil { @@ -214,7 +214,7 @@ func (c *KubeSphereClient) DescribeGroup(name string) (*models.Group, error) { return &group, nil } -func (c *KubeSphereClient) ListUsers() (*models.PageableResponse, error) { +func (c *Client) ListUsers() (*models.PageableResponse, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/kapis/iam.kubesphere.io/v1alpha2/users", c.accountServer), nil) if err != nil { @@ -250,7 +250,7 @@ func (c *KubeSphereClient) ListUsers() (*models.PageableResponse, error) { return &result, nil } -func (c *KubeSphereClient) ListWorkspaceDevOpsProjects(workspace string) (*v1alpha2.PageableDevOpsProject, error) { +func (c *Client) ListWorkspaceDevOpsProjects(workspace string) (*v1alpha2.PageableDevOpsProject, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/kapis/tenant.kubesphere.io/v1alpha2/workspaces/%s/devops", c.apiServer, workspace), nil) if err != nil { @@ -290,7 +290,7 @@ func (c *KubeSphereClient) ListWorkspaceDevOpsProjects(workspace string) (*v1alp } -func (c *KubeSphereClient) DeleteWorkspaceDevOpsProjects(workspace, devops string) error { +func (c *Client) DeleteWorkspaceDevOpsProjects(workspace, devops string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/kapis/tenant.kubesphere.io/v1alpha2/workspaces/%s/devops/%s", c.apiServer, workspace, devops), nil) if err != nil { diff --git a/pkg/simple/client/kubesphere/options.go b/pkg/simple/client/kubesphere/options.go index 442e44ed9..c4e134c7f 100644 --- a/pkg/simple/client/kubesphere/options.go +++ b/pkg/simple/client/kubesphere/options.go @@ -2,20 +2,20 @@ package kubesphere import "github.com/spf13/pflag" -type KubeSphereOptions struct { +type Options struct { APIServer string `json:"apiServer" yaml:"apiServer"` AccountServer string `json:"accountServer" yaml:"accountServer"` } // NewKubeSphereOptions create a default options -func NewKubeSphereOptions() *KubeSphereOptions { - return &KubeSphereOptions{ +func NewKubeSphereOptions() *Options { + return &Options{ APIServer: "http://ks-apiserver.kubesphere-system.svc", AccountServer: "http://ks-account.kubesphere-system.svc", } } -func (s *KubeSphereOptions) ApplyTo(options *KubeSphereOptions) { +func (s *Options) ApplyTo(options *Options) { if s.AccountServer != "" { options.AccountServer = s.AccountServer } @@ -25,13 +25,13 @@ func (s *KubeSphereOptions) ApplyTo(options *KubeSphereOptions) { } } -func (s *KubeSphereOptions) Validate() []error { +func (s *Options) Validate() []error { errs := []error{} return errs } -func (s *KubeSphereOptions) AddFlags(fs *pflag.FlagSet) { +func (s *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.APIServer, "kubesphere-apiserver-host", s.APIServer, ""+ "KubeSphere apiserver host address.") diff --git a/pkg/simple/client/ldap/ldap.go b/pkg/simple/client/ldap/ldap.go index 7c0e15814..7a9d29c0c 100644 --- a/pkg/simple/client/ldap/ldap.go +++ b/pkg/simple/client/ldap/ldap.go @@ -23,13 +23,13 @@ import ( "k8s.io/klog" ) -type LdapClient struct { +type Client struct { pool Pool - options *LdapOptions + options *Options } // panic if cannot connect to ldap service -func NewLdapClient(options *LdapOptions, stopCh <-chan struct{}) (*LdapClient, error) { +func NewLdapClient(options *Options, stopCh <-chan struct{}) (*Client, error) { pool, err := NewChannelPool(8, 64, "kubesphere", func(s string) (ldap.Client, error) { conn, err := ldap.Dial("tcp", options.Host) if err != nil { @@ -44,7 +44,7 @@ func NewLdapClient(options *LdapOptions, stopCh <-chan struct{}) (*LdapClient, e return nil, err } - client := &LdapClient{ + client := &Client{ pool: pool, options: options, } @@ -59,7 +59,7 @@ func NewLdapClient(options *LdapOptions, stopCh <-chan struct{}) (*LdapClient, e return client, nil } -func (l *LdapClient) NewConn() (ldap.Client, error) { +func (l *Client) NewConn() (ldap.Client, error) { if l.pool == nil { err := fmt.Errorf("ldap connection pool is not initialized") klog.Errorln(err) @@ -81,10 +81,10 @@ func (l *LdapClient) NewConn() (ldap.Client, error) { return conn, nil } -func (l *LdapClient) GroupSearchBase() string { +func (l *Client) GroupSearchBase() string { return l.options.GroupSearchBase } -func (l *LdapClient) UserSearchBase() string { +func (l *Client) UserSearchBase() string { return l.options.UserSearchBase } diff --git a/pkg/simple/client/ldap/options.go b/pkg/simple/client/ldap/options.go index 7f9408eac..9f2b9ed0c 100644 --- a/pkg/simple/client/ldap/options.go +++ b/pkg/simple/client/ldap/options.go @@ -5,7 +5,7 @@ import ( "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -type LdapOptions struct { +type Options struct { Host string `json:"host,omitempty" yaml:"host"` ManagerDN string `json:"managerDN,omitempty" yaml:"managerDN"` ManagerPassword string `json:"managerPassword,omitempty" yaml:"managerPassword"` @@ -15,8 +15,8 @@ type LdapOptions struct { // NewLdapOptions return a default option // which host field point to nowhere. -func NewLdapOptions() *LdapOptions { - return &LdapOptions{ +func NewLdapOptions() *Options { + return &Options{ Host: "", ManagerDN: "cn=admin,dc=example,dc=org", UserSearchBase: "ou=Users,dc=example,dc=org", @@ -24,32 +24,32 @@ func NewLdapOptions() *LdapOptions { } } -func (l *LdapOptions) Validate() []error { +func (l *Options) Validate() []error { errors := []error{} return errors } -func (l *LdapOptions) ApplyTo(options *LdapOptions) { +func (l *Options) ApplyTo(options *Options) { if l.Host != "" { reflectutils.Override(options, l) } } -func (l *LdapOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&l.Host, "ldap-host", l.Host, ""+ +func (l *Options) AddFlags(fs *pflag.FlagSet, s *Options) { + fs.StringVar(&l.Host, "ldap-host", s.Host, ""+ "Ldap service host, if left blank, all of the following ldap options will "+ "be ignored and ldap will be disabled.") - fs.StringVar(&l.ManagerDN, "ldap-manager-dn", l.ManagerDN, ""+ + fs.StringVar(&l.ManagerDN, "ldap-manager-dn", s.ManagerDN, ""+ "Ldap manager account domain name.") - fs.StringVar(&l.ManagerPassword, "ldap-manager-password", l.ManagerPassword, ""+ + fs.StringVar(&l.ManagerPassword, "ldap-manager-password", s.ManagerPassword, ""+ "Ldap manager account password.") - fs.StringVar(&l.UserSearchBase, "ldap-user-search-base", l.UserSearchBase, ""+ + fs.StringVar(&l.UserSearchBase, "ldap-user-search-base", s.UserSearchBase, ""+ "Ldap user search base.") - fs.StringVar(&l.GroupSearchBase, "ldap-group-search-base", l.GroupSearchBase, ""+ + fs.StringVar(&l.GroupSearchBase, "ldap-group-search-base", s.GroupSearchBase, ""+ "Ldap group search base.") } diff --git a/pkg/simple/client/logging/logging.go b/pkg/simple/client/logging/logging.go new file mode 100644 index 000000000..03313b969 --- /dev/null +++ b/pkg/simple/client/logging/logging.go @@ -0,0 +1,4 @@ +package logging + +type Interface interface { +} diff --git a/pkg/simple/client/logging/query.go b/pkg/simple/client/logging/query.go new file mode 100644 index 000000000..01e11471f --- /dev/null +++ b/pkg/simple/client/logging/query.go @@ -0,0 +1,4 @@ +package logging + +type Query struct { +} diff --git a/pkg/simple/client/monitoring/monitoring.go b/pkg/simple/client/monitoring/monitoring.go new file mode 100644 index 000000000..aa090bd3d --- /dev/null +++ b/pkg/simple/client/monitoring/monitoring.go @@ -0,0 +1,4 @@ +package monitoring + +type Interface interface { +} diff --git a/pkg/simple/client/mysql/mysql.go b/pkg/simple/client/mysql/mysql.go index dfedf2beb..1a68d50b7 100644 --- a/pkg/simple/client/mysql/mysql.go +++ b/pkg/simple/client/mysql/mysql.go @@ -19,12 +19,12 @@ import ( "k8s.io/klog" ) -type MySQLClient struct { +type Client struct { database *Database } -func NewMySQLClient(options *MySQLOptions, stopCh <-chan struct{}) (*MySQLClient, error) { - var m MySQLClient +func NewMySQLClient(options *Options, stopCh <-chan struct{}) (*Client, error) { + var m Client conn, err := dbr.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/devops?parseTime=1&multiStatements=1&charset=utf8mb4&collation=utf8mb4_unicode_ci", options.Username, options.Password, options.Host), nil) if err != nil { @@ -50,8 +50,8 @@ func NewMySQLClient(options *MySQLOptions, stopCh <-chan struct{}) (*MySQLClient return &m, nil } -func NewMySQLClientOrDie(options *MySQLOptions, stopCh <-chan struct{}) *MySQLClient { - var m MySQLClient +func NewMySQLClientOrDie(options *Options, stopCh <-chan struct{}) *Client { + var m Client conn, err := dbr.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/devops?parseTime=1&multiStatements=1&charset=utf8mb4&collation=utf8mb4_unicode_ci", options.Username, options.Password, options.Host), nil) if err != nil { @@ -77,6 +77,6 @@ func NewMySQLClientOrDie(options *MySQLOptions, stopCh <-chan struct{}) *MySQLCl return &m } -func (m *MySQLClient) Database() *Database { +func (m *Client) Database() *Database { return m.database } diff --git a/pkg/simple/client/mysql/options.go b/pkg/simple/client/mysql/options.go index 359b6ad9d..dc0d545d6 100644 --- a/pkg/simple/client/mysql/options.go +++ b/pkg/simple/client/mysql/options.go @@ -6,7 +6,7 @@ import ( "time" ) -type MySQLOptions struct { +type Options struct { Host string `json:"host,omitempty" yaml:"host" description:"MySQL service host address"` Username string `json:"username,omitempty" yaml:"username"` Password string `json:"-" yaml:"password"` @@ -16,8 +16,8 @@ type MySQLOptions struct { } // NewMySQLOptions create a `zero` value instance -func NewMySQLOptions() *MySQLOptions { - return &MySQLOptions{ +func NewMySQLOptions() *Options { + return &Options{ Host: "", Username: "", Password: "", @@ -27,33 +27,33 @@ func NewMySQLOptions() *MySQLOptions { } } -func (m *MySQLOptions) Validate() []error { - errors := []error{} +func (m *Options) Validate() []error { + var errors []error return errors } -func (m *MySQLOptions) ApplyTo(options *MySQLOptions) { +func (m *Options) ApplyTo(options *Options) { reflectutils.Override(options, m) } -func (m *MySQLOptions) AddFlags(fs *pflag.FlagSet) { +func (m *Options) AddFlags(fs *pflag.FlagSet, c *Options) { - fs.StringVar(&m.Host, "mysql-host", m.Host, ""+ + fs.StringVar(&m.Host, "mysql-host", c.Host, ""+ "MySQL service host address. If left blank, the following related mysql options will be ignored.") - fs.StringVar(&m.Username, "mysql-username", m.Username, ""+ + fs.StringVar(&m.Username, "mysql-username", c.Username, ""+ "Username for access to mysql service.") - fs.StringVar(&m.Password, "mysql-password", m.Password, ""+ + fs.StringVar(&m.Password, "mysql-password", c.Password, ""+ "Password for access to mysql, should be used pair with password.") - fs.IntVar(&m.MaxIdleConnections, "mysql-max-idle-connections", m.MaxOpenConnections, ""+ + fs.IntVar(&m.MaxIdleConnections, "mysql-max-idle-connections", c.MaxOpenConnections, ""+ "Maximum idle connections allowed to connect to mysql.") - fs.IntVar(&m.MaxOpenConnections, "mysql-max-open-connections", m.MaxOpenConnections, ""+ + fs.IntVar(&m.MaxOpenConnections, "mysql-max-open-connections", c.MaxOpenConnections, ""+ "Maximum open connections allowed to connect to mysql.") - fs.DurationVar(&m.MaxConnectionLifeTime, "mysql-max-connection-life-time", m.MaxConnectionLifeTime, ""+ + fs.DurationVar(&m.MaxConnectionLifeTime, "mysql-max-connection-life-time", c.MaxConnectionLifeTime, ""+ "Maximum connection life time allowed to connecto to mysql.") } diff --git a/pkg/simple/client/notification/options.go b/pkg/simple/client/notification/options.go index 29c97906a..e4df715f9 100644 --- a/pkg/simple/client/notification/options.go +++ b/pkg/simple/client/notification/options.go @@ -1,16 +1,16 @@ package notification -type NotificationOptions struct { +type Options struct { Endpoint string } -func NewNotificationOptions() *NotificationOptions { - return &NotificationOptions{ +func NewNotificationOptions() *Options { + return &Options{ Endpoint: "", } } -func (s *NotificationOptions) ApplyTo(options *NotificationOptions) { +func (s *Options) ApplyTo(options *Options) { if options == nil { options = s return diff --git a/pkg/simple/client/openpitrix/openpitrixclient.go b/pkg/simple/client/openpitrix/openpitrixclient.go index 0e8f4a32c..3c8e7226e 100644 --- a/pkg/simple/client/openpitrix/openpitrixclient.go +++ b/pkg/simple/client/openpitrix/openpitrixclient.go @@ -39,7 +39,17 @@ const ( SystemUserPath = ":system" ) -type OpenPitrixClient struct { +type Interface interface { + pb.RuntimeManagerClient + pb.ClusterManagerClient + pb.AppManagerClient + pb.RepoManagerClient + pb.CategoryManagerClient + pb.AttachmentManagerClient + pb.RepoIndexerClient +} + +type Client struct { runtime pb.RuntimeManagerClient cluster pb.ClusterManagerClient app pb.AppManagerClient @@ -123,7 +133,7 @@ func newAppManagerClient(endpoint string) (pb.AppManagerClient, error) { return pb.NewAppManagerClient(conn), nil } -func NewOpenPitrixClient(options *OpenPitrixOptions) (*OpenPitrixClient, error) { +func NewOpenPitrixClient(options *Options) (*Client, error) { runtimeMangerClient, err := newRuntimeManagerClient(options.RuntimeManagerEndpoint) @@ -174,7 +184,7 @@ func NewOpenPitrixClient(options *OpenPitrixOptions) (*OpenPitrixClient, error) return nil, err } - client := OpenPitrixClient{ + client := Client{ runtime: runtimeMangerClient, cluster: clusterManagerClient, repo: repoManagerClient, @@ -186,28 +196,28 @@ func NewOpenPitrixClient(options *OpenPitrixOptions) (*OpenPitrixClient, error) return &client, nil } -func (c *OpenPitrixClient) Runtime() pb.RuntimeManagerClient { +func (c *Client) Runtime() pb.RuntimeManagerClient { return c.runtime } -func (c *OpenPitrixClient) App() pb.AppManagerClient { +func (c *Client) App() pb.AppManagerClient { return c.app } -func (c *OpenPitrixClient) Cluster() pb.ClusterManagerClient { +func (c *Client) Cluster() pb.ClusterManagerClient { return c.cluster } -func (c *OpenPitrixClient) Category() pb.CategoryManagerClient { +func (c *Client) Category() pb.CategoryManagerClient { return c.category } -func (c *OpenPitrixClient) Repo() pb.RepoManagerClient { +func (c *Client) Repo() pb.RepoManagerClient { return c.repo } -func (c *OpenPitrixClient) RepoIndexer() pb.RepoIndexerClient { +func (c *Client) RepoIndexer() pb.RepoIndexerClient { return c.repoIndexer } -func (c *OpenPitrixClient) Attachment() pb.AttachmentManagerClient { +func (c *Client) Attachment() pb.AttachmentManagerClient { return c.attachment } diff --git a/pkg/simple/client/openpitrix/options.go b/pkg/simple/client/openpitrix/options.go index d577bd5f4..ca18c2e36 100644 --- a/pkg/simple/client/openpitrix/options.go +++ b/pkg/simple/client/openpitrix/options.go @@ -6,7 +6,7 @@ import ( "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -type OpenPitrixOptions struct { +type Options struct { RuntimeManagerEndpoint string `json:"runtimeManagerEndpoint,omitempty" yaml:"runtimeManagerEndpoint,omitempty"` ClusterManagerEndpoint string `json:"clusterManagerEndpoint,omitempty" yaml:"clusterManagerEndpoint,omitempty"` RepoManagerEndpoint string `json:"repoManagerEndpoint,omitempty" yaml:"repoManagerEndpoint,omitempty"` @@ -16,11 +16,11 @@ type OpenPitrixOptions struct { RepoIndexerEndpoint string `json:"repoIndexerEndpoint,omitempty" yaml:"repoIndexerEndpoint,omitempty"` } -func NewOpenPitrixOptions() *OpenPitrixOptions { - return &OpenPitrixOptions{} +func NewOpenPitrixOptions() *Options { + return &Options{} } -func (s *OpenPitrixOptions) ApplyTo(options *OpenPitrixOptions) { +func (s *Options) ApplyTo(options *Options) { if options == nil { options = s return @@ -30,7 +30,7 @@ func (s *OpenPitrixOptions) ApplyTo(options *OpenPitrixOptions) { } } -func (s *OpenPitrixOptions) IsEmpty() bool { +func (s *Options) IsEmpty() bool { return s.RuntimeManagerEndpoint == "" && s.ClusterManagerEndpoint == "" && s.RepoManagerEndpoint == "" && @@ -40,7 +40,7 @@ func (s *OpenPitrixOptions) IsEmpty() bool { s.RepoIndexerEndpoint == "" } -func (s *OpenPitrixOptions) Validate() []error { +func (s *Options) Validate() []error { var errs []error if s.RuntimeManagerEndpoint != "" { @@ -89,25 +89,25 @@ func (s *OpenPitrixOptions) Validate() []error { return errs } -func (s *OpenPitrixOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.RuntimeManagerEndpoint, "openpitrix-runtime-manager-endpoint", s.RuntimeManagerEndpoint, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.RuntimeManagerEndpoint, "openpitrix-runtime-manager-endpoint", c.RuntimeManagerEndpoint, ""+ "OpenPitrix runtime manager endpoint") - fs.StringVar(&s.AppManagerEndpoint, "openpitrix-app-manager-endpoint", s.AppManagerEndpoint, ""+ + fs.StringVar(&s.AppManagerEndpoint, "openpitrix-app-manager-endpoint", c.AppManagerEndpoint, ""+ "OpenPitrix app manager endpoint") - fs.StringVar(&s.ClusterManagerEndpoint, "openpitrix-cluster-manager-endpoint", s.ClusterManagerEndpoint, ""+ + fs.StringVar(&s.ClusterManagerEndpoint, "openpitrix-cluster-manager-endpoint", c.ClusterManagerEndpoint, ""+ "OpenPitrix cluster manager endpoint") - fs.StringVar(&s.CategoryManagerEndpoint, "openpitrix-category-manager-endpoint", s.CategoryManagerEndpoint, ""+ + fs.StringVar(&s.CategoryManagerEndpoint, "openpitrix-category-manager-endpoint", c.CategoryManagerEndpoint, ""+ "OpenPitrix category manager endpoint") - fs.StringVar(&s.RepoManagerEndpoint, "openpitrix-repo-manager-endpoint", s.RepoManagerEndpoint, ""+ + fs.StringVar(&s.RepoManagerEndpoint, "openpitrix-repo-manager-endpoint", c.RepoManagerEndpoint, ""+ "OpenPitrix repo manager endpoint") - fs.StringVar(&s.RepoIndexerEndpoint, "openpitrix-repo-indexer-endpoint", s.RepoIndexerEndpoint, ""+ + fs.StringVar(&s.RepoIndexerEndpoint, "openpitrix-repo-indexer-endpoint", c.RepoIndexerEndpoint, ""+ "OpenPitrix repo indexer endpoint") - fs.StringVar(&s.AttachmentManagerEndpoint, "openpitrix-attachment-manager-endpoint", s.AttachmentManagerEndpoint, ""+ + fs.StringVar(&s.AttachmentManagerEndpoint, "openpitrix-attachment-manager-endpoint", c.AttachmentManagerEndpoint, ""+ "OpenPitrix attachment manager endpoint") } diff --git a/pkg/simple/client/prometheus/options.go b/pkg/simple/client/prometheus/options.go index 6ade8c720..8b46fbff5 100644 --- a/pkg/simple/client/prometheus/options.go +++ b/pkg/simple/client/prometheus/options.go @@ -4,25 +4,24 @@ import ( "github.com/spf13/pflag" ) -type PrometheusOptions struct { +type Options struct { Endpoint string `json:"endpoint,omitempty" yaml:"endpoint"` SecondaryEndpoint string `json:"secondaryEndpoint,omitempty" yaml:"secondaryEndpoint"` } -func NewPrometheusOptions() *PrometheusOptions { - return &PrometheusOptions{ +func NewPrometheusOptions() *Options { + return &Options{ Endpoint: "", SecondaryEndpoint: "", } } -func (s *PrometheusOptions) Validate() []error { - errs := []error{} - +func (s *Options) Validate() []error { + var errs []error return errs } -func (s *PrometheusOptions) ApplyTo(options *PrometheusOptions) { +func (s *Options) ApplyTo(options *Options) { if s.Endpoint != "" { options.Endpoint = s.Endpoint } @@ -32,11 +31,11 @@ func (s *PrometheusOptions) ApplyTo(options *PrometheusOptions) { } } -func (s *PrometheusOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Endpoint, "prometheus-endpoint", s.Endpoint, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.Endpoint, "prometheus-endpoint", c.Endpoint, ""+ "Prometheus service endpoint which stores KubeSphere monitoring data, if left "+ "blank, will use builtin metrics-server as data source.") - fs.StringVar(&s.SecondaryEndpoint, "prometheus-secondary-endpoint", s.SecondaryEndpoint, ""+ + fs.StringVar(&s.SecondaryEndpoint, "prometheus-secondary-endpoint", c.SecondaryEndpoint, ""+ "Prometheus secondary service endpoint, if left empty and endpoint is set, will use endpoint instead.") } diff --git a/pkg/simple/client/prometheus/prometheus.go b/pkg/simple/client/prometheus/prometheus.go index 5309caa30..cb614ad1a 100644 --- a/pkg/simple/client/prometheus/prometheus.go +++ b/pkg/simple/client/prometheus/prometheus.go @@ -27,14 +27,17 @@ import ( "time" ) -type PrometheusClient struct { +type Interface interface { +} + +type Client struct { client *http.Client endpoint string secondaryEndpoint string } -func NewPrometheusClient(options *PrometheusOptions) (*PrometheusClient, error) { - return &PrometheusClient{ +func NewPrometheusClient(options *Options) (*Client, error) { + return &Client{ client: &http.Client{ Timeout: 10 * time.Second, }, @@ -43,17 +46,17 @@ func NewPrometheusClient(options *PrometheusOptions) (*PrometheusClient, error) }, nil } -func (c *PrometheusClient) QueryToK8SPrometheus(queryType string, params string) (apiResponse v1alpha2.APIResponse) { +func (c *Client) QueryToK8SPrometheus(queryType string, params string) (apiResponse v1alpha2.APIResponse) { return c.query(c.endpoint, queryType, params) } -func (c *PrometheusClient) QueryToK8SSystemPrometheus(queryType string, params string) (apiResponse v1alpha2.APIResponse) { +func (c *Client) QueryToK8SSystemPrometheus(queryType string, params string) (apiResponse v1alpha2.APIResponse) { return c.query(c.secondaryEndpoint, queryType, params) } var jsonIter = jsoniter.ConfigCompatibleWithStandardLibrary -func (c *PrometheusClient) query(endpoint string, queryType string, params string) (apiResponse v1alpha2.APIResponse) { +func (c *Client) query(endpoint string, queryType string, params string) (apiResponse v1alpha2.APIResponse) { url := fmt.Sprintf("%s/api/v1/%s?%s", endpoint, queryType, params) response, err := c.client.Get(url) diff --git a/pkg/simple/client/s3/interface.go b/pkg/simple/client/s3/interface.go new file mode 100644 index 000000000..594b8438d --- /dev/null +++ b/pkg/simple/client/s3/interface.go @@ -0,0 +1,17 @@ +package s3 + +import ( + "io" + "time" +) + +type Interface interface { + // Upload uploads a object to storage and returns object location if succeeded + Upload(key string, body io.Reader) (string, error) + + // Get retrieves and object's downloadable location if succeeded + Get(key string, fileName string, expire time.Duration) (string, error) + + // Delete deletes an object by its key + Delete(key string) error +} diff --git a/pkg/simple/client/s2is3/options.go b/pkg/simple/client/s3/options.go similarity index 64% rename from pkg/simple/client/s2is3/options.go rename to pkg/simple/client/s3/options.go index 32b676bc4..68c37ad09 100644 --- a/pkg/simple/client/s2is3/options.go +++ b/pkg/simple/client/s3/options.go @@ -1,12 +1,12 @@ -package s2is3 +package s3 import ( "github.com/spf13/pflag" "kubesphere.io/kubesphere/pkg/utils/reflectutils" ) -// S3Options contains configuration to access a s3 service -type S3Options struct { +// Options contains configuration to access a s3 service +type Options struct { Endpoint string `json:"endpoint,omitempty" yaml:"endpoint"` Region string `json:"region,omitempty" yaml:"region"` DisableSSL bool `json:"disableSSL" yaml:"disableSSL"` @@ -17,9 +17,9 @@ type S3Options struct { Bucket string `json:"bucket,omitempty" yaml:"bucket"` } -// NewS3Options creates a default disabled S3Options(empty endpoint) -func NewS3Options() *S3Options { - return &S3Options{ +// NewS3Options creates a default disabled Options(empty endpoint) +func NewS3Options() *Options { + return &Options{ Endpoint: "", Region: "us-east-1", DisableSSL: true, @@ -32,14 +32,14 @@ func NewS3Options() *S3Options { } // Validate check options values -func (s *S3Options) Validate() []error { - errors := []error{} +func (s *Options) Validate() []error { + var errors []error return errors } // ApplyTo overrides options if it's valid, which endpoint is not empty -func (s *S3Options) ApplyTo(options *S3Options) { +func (s *Options) ApplyTo(options *Options) { if s.Endpoint != "" { reflectutils.Override(options, s) } @@ -47,23 +47,23 @@ func (s *S3Options) ApplyTo(options *S3Options) { // AddFlags add options flags to command line flags, // if s3-endpoint if left empty, following options will be ignored -func (s *S3Options) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Endpoint, "s3-endpoint", s.Endpoint, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.Endpoint, "s3-endpoint", c.Endpoint, ""+ "Endpoint to access to s3 object storage service, if left blank, the following options "+ "will be ignored.") - fs.StringVar(&s.Region, "s3-region", s.Region, ""+ + fs.StringVar(&s.Region, "s3-region", c.Region, ""+ "Region of s3 that will access to, like us-east-1.") - fs.StringVar(&s.AccessKeyID, "s3-access-key-id", s.AccessKeyID, "access key of s2i s3") + fs.StringVar(&s.AccessKeyID, "s3-access-key-id", c.AccessKeyID, "access key of s2i s3") - fs.StringVar(&s.SecretAccessKey, "s3-secret-access-key", s.SecretAccessKey, "secret access key of s2i s3") + fs.StringVar(&s.SecretAccessKey, "s3-secret-access-key", c.SecretAccessKey, "secret access key of s2i s3") - fs.StringVar(&s.SessionToken, "s3-session-token", s.SessionToken, "session token of s2i s3") + fs.StringVar(&s.SessionToken, "s3-session-token", c.SessionToken, "session token of s2i s3") - fs.StringVar(&s.Bucket, "s3-bucket", s.Bucket, "bucket name of s2i s3") + fs.StringVar(&s.Bucket, "s3-bucket", c.Bucket, "bucket name of s2i s3") - fs.BoolVar(&s.DisableSSL, "s3-disable-SSL", s.DisableSSL, "disable ssl") + fs.BoolVar(&s.DisableSSL, "s3-disable-SSL", c.DisableSSL, "disable ssl") - fs.BoolVar(&s.ForcePathStyle, "s3-force-path-style", s.ForcePathStyle, "force path style") + fs.BoolVar(&s.ForcePathStyle, "s3-force-path-style", c.ForcePathStyle, "force path style") } diff --git a/pkg/simple/client/s2is3/s3.go b/pkg/simple/client/s3/s3.go similarity index 68% rename from pkg/simple/client/s2is3/s3.go rename to pkg/simple/client/s3/s3.go index e9f7ec09f..4666d0a23 100644 --- a/pkg/simple/client/s2is3/s3.go +++ b/pkg/simple/client/s3/s3.go @@ -1,20 +1,34 @@ -package s2is3 +package s3 import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" + "io" "k8s.io/klog" + "time" ) -type S3Client struct { +type Client struct { s3Client *s3.S3 s3Session *session.Session bucket string } -func NewS3Client(options *S3Options) (*S3Client, error) { +func (s *Client) Upload(key string, body io.Reader) (string, error) { + panic("implement me") +} + +func (s *Client) Get(key string, fileName string, expire time.Duration) (string, error) { + panic("implement me") +} + +func (s *Client) Delete(key string) error { + panic("implement me") +} + +func NewS3Client(options *Options) (Interface, error) { cred := credentials.NewStaticCredentials(options.AccessKeyID, options.SecretAccessKey, options.SessionToken) config := aws.Config{ @@ -31,7 +45,7 @@ func NewS3Client(options *S3Options) (*S3Client, error) { return nil, err } - var c S3Client + var c Client c.s3Client = s3.New(s) c.s3Session = s @@ -40,8 +54,8 @@ func NewS3Client(options *S3Options) (*S3Client, error) { return &c, nil } -// NewS3ClientOrDie creates S3Client and panics if there is an error -func NewS3ClientOrDie(options *S3Options) *S3Client { +// NewS3ClientOrDie creates Client and panics if there is an error +func NewS3ClientOrDie(options *Options) Interface { cred := credentials.NewStaticCredentials(options.AccessKeyID, options.SecretAccessKey, options.SessionToken) config := aws.Config{ @@ -59,21 +73,21 @@ func NewS3ClientOrDie(options *S3Options) *S3Client { client := s3.New(s) - return &S3Client{ + return &Client{ s3Client: client, s3Session: s, bucket: options.Bucket, } } -func (s *S3Client) Client() *s3.S3 { +func (s *Client) Client() *s3.S3 { return s.s3Client } -func (s *S3Client) Session() *session.Session { +func (s *Client) Session() *session.Session { return s.s3Session } -func (s *S3Client) Bucket() *string { +func (s *Client) Bucket() *string { return aws.String(s.bucket) } diff --git a/pkg/simple/client/servicemesh/options.go b/pkg/simple/client/servicemesh/options.go index 7056228e8..fb3bb4d76 100644 --- a/pkg/simple/client/servicemesh/options.go +++ b/pkg/simple/client/servicemesh/options.go @@ -2,7 +2,7 @@ package servicemesh import "github.com/spf13/pflag" -type ServiceMeshOptions struct { +type Options struct { // istio pilot discovery service url IstioPilotHost string `json:"istioPilotHost,omitempty" yaml:"istioPilotHost"` @@ -15,21 +15,21 @@ type ServiceMeshOptions struct { } // NewServiceMeshOptions returns a `zero` instance -func NewServiceMeshOptions() *ServiceMeshOptions { - return &ServiceMeshOptions{ +func NewServiceMeshOptions() *Options { + return &Options{ IstioPilotHost: "", JaegerQueryHost: "", ServicemeshPrometheusHost: "", } } -func (s *ServiceMeshOptions) Validate() []error { +func (s *Options) Validate() []error { errors := []error{} return errors } -func (s *ServiceMeshOptions) ApplyTo(options *ServiceMeshOptions) { +func (s *Options) ApplyTo(options *Options) { if s.ServicemeshPrometheusHost != "" { options.ServicemeshPrometheusHost = s.ServicemeshPrometheusHost } @@ -43,13 +43,13 @@ func (s *ServiceMeshOptions) ApplyTo(options *ServiceMeshOptions) { } } -func (s *ServiceMeshOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.IstioPilotHost, "istio-pilot-host", s.IstioPilotHost, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.IstioPilotHost, "istio-pilot-host", c.IstioPilotHost, ""+ "istio pilot discovery service url") - fs.StringVar(&s.JaegerQueryHost, "jaeger-query-host", s.JaegerQueryHost, ""+ + fs.StringVar(&s.JaegerQueryHost, "jaeger-query-host", c.JaegerQueryHost, ""+ "jaeger query service url") - fs.StringVar(&s.ServicemeshPrometheusHost, "servicemesh-prometheus-host", s.ServicemeshPrometheusHost, ""+ + fs.StringVar(&s.ServicemeshPrometheusHost, "servicemesh-prometheus-host", c.ServicemeshPrometheusHost, ""+ "prometheus service for servicemesh") } diff --git a/pkg/simple/client/sonarqube/interface.go b/pkg/simple/client/sonarqube/interface.go new file mode 100644 index 000000000..9873cf9ff --- /dev/null +++ b/pkg/simple/client/sonarqube/interface.go @@ -0,0 +1,8 @@ +package sonarqube + +type Interface interface { + // + GetIssues() + + // +} diff --git a/pkg/simple/client/sonarqube/options.go b/pkg/simple/client/sonarqube/options.go index 92343c7a1..821d02f56 100644 --- a/pkg/simple/client/sonarqube/options.go +++ b/pkg/simple/client/sonarqube/options.go @@ -4,39 +4,35 @@ import ( "github.com/spf13/pflag" ) -type SonarQubeOptions struct { +type Options struct { Host string `json:",omitempty" yaml:"host" description:"SonarQube service host address"` Token string `json:",omitempty" yaml:"token" description:"SonarQube service token"` } -func NewSonarQubeOptions() *SonarQubeOptions { - return &SonarQubeOptions{ +func NewSonarQubeOptions() *Options { + return &Options{ Host: "", Token: "", } } -func NewDefaultSonarQubeOptions() *SonarQubeOptions { - return NewSonarQubeOptions() -} - -func (s *SonarQubeOptions) Validate() []error { - errors := []error{} +func (s *Options) Validate() []error { + var errors []error return errors } -func (s *SonarQubeOptions) ApplyTo(options *SonarQubeOptions) { +func (s *Options) ApplyTo(options *Options) { if s.Host != "" { options.Host = s.Host options.Token = s.Token } } -func (s *SonarQubeOptions) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&s.Host, "sonarqube-host", s.Host, ""+ +func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) { + fs.StringVar(&s.Host, "sonarqube-host", c.Host, ""+ "Sonarqube service address, if left empty, following sonarqube options will be ignored.") - fs.StringVar(&s.Token, "sonarqube-token", s.Token, ""+ + fs.StringVar(&s.Token, "sonarqube-token", c.Token, ""+ "Sonarqube service access token.") } diff --git a/pkg/simple/client/sonarqube/sonarqube.go b/pkg/simple/client/sonarqube/sonarqube.go index a6453fe8a..a622d9607 100644 --- a/pkg/simple/client/sonarqube/sonarqube.go +++ b/pkg/simple/client/sonarqube/sonarqube.go @@ -7,11 +7,11 @@ import ( "strings" ) -type SonarQubeClient struct { +type Client struct { client *sonargo.Client } -func NewSonarQubeClient(options *SonarQubeOptions) (*SonarQubeClient, error) { +func NewSonarQubeClient(options *Options) (*Client, error) { var endpoint string if strings.HasSuffix(options.Host, "/") { @@ -26,10 +26,10 @@ func NewSonarQubeClient(options *SonarQubeOptions) (*SonarQubeClient, error) { return nil, err } - return &SonarQubeClient{client: sonar}, err + return &Client{client: sonar}, err } -func NewSonarQubeClientOrDie(options *SonarQubeOptions) *SonarQubeClient { +func NewSonarQubeClientOrDie(options *Options) *Client { var endpoint string if strings.HasSuffix(options.Host, "/") { @@ -44,11 +44,11 @@ func NewSonarQubeClientOrDie(options *SonarQubeOptions) *SonarQubeClient { panic(err) } - return &SonarQubeClient{client: sonar} + return &Client{client: sonar} } // return sonarqube client // Also we can wrap some methods to avoid direct use sonar client -func (s *SonarQubeClient) SonarQube() *sonargo.Client { +func (s *Client) SonarQube() *sonargo.Client { return s.client } diff --git a/vendor/github.com/MakeNowJust/heredoc/LICENSE b/vendor/github.com/MakeNowJust/heredoc/LICENSE new file mode 100644 index 000000000..8a58c2220 --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017 TSUYUSATO Kitsune + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/MakeNowJust/heredoc/README.md b/vendor/github.com/MakeNowJust/heredoc/README.md new file mode 100644 index 000000000..a3a65faba --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/README.md @@ -0,0 +1,53 @@ +# heredoc [![CircleCI](https://circleci.com/gh/MakeNowJust/heredoc.svg?style=svg)](https://circleci.com/gh/MakeNowJust/heredoc) [![Go Walker](http://gowalker.org/api/v1/badge)](https://gowalker.org/github.com/MakeNowJust/heredoc) + +## About + +Package heredoc provides the here-document with keeping indent. + +## Install + +```console +$ go get github.com/MakeNowJust/heredoc +``` + +## Import + +```go +// usual +import "github.com/MakeNowJust/heredoc" +// shortcuts +import . "github.com/MakeNowJust/heredoc/dot" +``` + +## Example + +```go +package main + +import ( + "fmt" + . "github.com/MakeNowJust/heredoc/dot" +) + +func main() { + fmt.Println(D(` + Lorem ipsum dolor sit amet, consectetur adipisicing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, ... + `)) + // Output: + // Lorem ipsum dolor sit amet, consectetur adipisicing elit, + // sed do eiusmod tempor incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, ... + // +} +``` + +## API Document + + - [Go Walker - github.com/MakeNowJust/heredoc](https://gowalker.org/github.com/MakeNowJust/heredoc) + - [Go Walker - github.com/MakeNowJust/heredoc/dot](https://gowalker.org/github.com/MakeNowJust/heredoc/dot) + +## License + +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/MakeNowJust/heredoc/heredoc.go b/vendor/github.com/MakeNowJust/heredoc/heredoc.go new file mode 100644 index 000000000..fea12e622 --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/heredoc.go @@ -0,0 +1,98 @@ +// Copyright (c) 2014-2017 TSUYUSATO Kitsune +// This software is released under the MIT License. +// http://opensource.org/licenses/mit-license.php + +// Package heredoc provides creation of here-documents from raw strings. +// +// Golang supports raw-string syntax. +// doc := ` +// Foo +// Bar +// ` +// But raw-string cannot recognize indentation. Thus such content is an indented string, equivalent to +// "\n\tFoo\n\tBar\n" +// I dont't want this! +// +// However this problem is solved by package heredoc. +// doc := heredoc.Doc(` +// Foo +// Bar +// `) +// Is equivalent to +// "Foo\nBar\n" +package heredoc + +import ( + "fmt" + "strings" + "unicode" +) + +const maxInt = int(^uint(0) >> 1) + +// Doc returns un-indented string as here-document. +func Doc(raw string) string { + skipFirstLine := false + if raw[0] == '\n' { + raw = raw[1:] + } else { + skipFirstLine = true + } + + lines := strings.Split(raw, "\n") + + minIndentSize := getMinIndent(lines, skipFirstLine) + lines = removeIndentation(lines, minIndentSize, skipFirstLine) + + return strings.Join(lines, "\n") +} + +// getMinIndent calculates the minimum indentation in lines, excluding empty lines. +func getMinIndent(lines []string, skipFirstLine bool) int { + minIndentSize := maxInt + + for i, line := range lines { + if i == 0 && skipFirstLine { + continue + } + + indentSize := 0 + for _, r := range []rune(line) { + if unicode.IsSpace(r) { + indentSize += 1 + } else { + break + } + } + + if len(line) == indentSize { + if i == len(lines)-1 && indentSize < minIndentSize { + lines[i] = "" + } + } else if indentSize < minIndentSize { + minIndentSize = indentSize + } + } + return minIndentSize +} + +// removeIndentation removes n characters from the front of each line in lines. +// Skips first line if skipFirstLine is true, skips empty lines. +func removeIndentation(lines []string, n int, skipFirstLine bool) []string { + for i, line := range lines { + if i == 0 && skipFirstLine { + continue + } + + if len(lines[i]) >= n { + lines[i] = line[n:] + } + } + return lines +} + +// Docf returns unindented and formatted string as here-document. +// Formatting is done as for fmt.Printf(). +func Docf(raw string, args ...interface{}) string { + return fmt.Sprintf(Doc(raw), args...) +} diff --git a/vendor/github.com/chai2010/gettext-go/LICENSE b/vendor/github.com/chai2010/gettext-go/LICENSE new file mode 100644 index 000000000..8f3940825 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/LICENSE @@ -0,0 +1,27 @@ +Copyright 2013 ChaiShushan . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/chai2010/gettext-go/gettext/caller.go b/vendor/github.com/chai2010/gettext-go/gettext/caller.go new file mode 100644 index 000000000..e24aab375 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/caller.go @@ -0,0 +1,39 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "regexp" + "runtime" +) + +var ( + reInit = regexp.MustCompile(`init·\d+$`) // main.init·1 + reClosure = regexp.MustCompile(`func·\d+$`) // main.func·001 +) + +// caller types: +// runtime.goexit +// runtime.main +// main.init +// main.main +// main.init·1 -> main.init +// main.func·001 -> main.func +// code.google.com/p/gettext-go/gettext.TestCallerName +// ... +func callerName(skip int) string { + pc, _, _, ok := runtime.Caller(skip) + if !ok { + return "" + } + name := runtime.FuncForPC(pc).Name() + if reInit.MatchString(name) { + return reInit.ReplaceAllString(name, "init") + } + if reClosure.MatchString(name) { + return reClosure.ReplaceAllString(name, "func") + } + return name +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/doc.go new file mode 100644 index 000000000..422bf2c6d --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/doc.go @@ -0,0 +1,66 @@ +// Copyright 2013 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package gettext implements a basic GNU's gettext library. + +Example: + import ( + "github.com/chai2010/gettext-go/gettext" + ) + + func main() { + gettext.SetLocale("zh_CN") + gettext.Textdomain("hello") + + // gettext.BindTextdomain("hello", "local", nil) // from local dir + // gettext.BindTextdomain("hello", "local.zip", nil) // from local zip file + // gettext.BindTextdomain("hello", "local.zip", zipData) // from embedded zip data + + gettext.BindTextdomain("hello", "local", nil) + + // translate source text + fmt.Println(gettext.Gettext("Hello, world!")) + // Output: 你好, 世界! + + // translate resource + fmt.Println(string(gettext.Getdata("poems.txt"))) + // Output: ... + } + +Translate directory struct("../examples/local.zip"): + + Root: "path" or "file.zip/zipBaseName" + +-default # local: $(LC_MESSAGES) or $(LANG) or "default" + | +-LC_MESSAGES # just for `gettext.Gettext` + | | +-hello.mo # $(Root)/$(local)/LC_MESSAGES/$(domain).mo + | | \-hello.po # $(Root)/$(local)/LC_MESSAGES/$(domain).mo + | | + | \-LC_RESOURCE # just for `gettext.Getdata` + | +-hello # domain map a dir in resource translate + | +-favicon.ico # $(Root)/$(local)/LC_RESOURCE/$(domain)/$(filename) + | \-poems.txt + | + \-zh_CN # simple chinese translate + +-LC_MESSAGES + | +-hello.mo # try "$(domain).mo" first + | \-hello.po # try "$(domain).po" second + | + \-LC_RESOURCE + +-hello + +-favicon.ico # try "$(local)/$(domain)/file" first + \-poems.txt # try "default/$(domain)/file" second + +See: + http://en.wikipedia.org/wiki/Gettext + http://www.gnu.org/software/gettext/manual/html_node + http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html + http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html + http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html + http://www.poedit.net/ + +Please report bugs to . +Thanks! +*/ +package gettext diff --git a/vendor/github.com/chai2010/gettext-go/gettext/domain.go b/vendor/github.com/chai2010/gettext-go/gettext/domain.go new file mode 100644 index 000000000..f860b27b6 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/domain.go @@ -0,0 +1,119 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "sync" +) + +type domainManager struct { + mutex sync.Mutex + locale string + domain string + domainMap map[string]*fileSystem + trTextMap map[string]*translator +} + +func newDomainManager() *domainManager { + return &domainManager{ + locale: DefaultLocale, + domainMap: make(map[string]*fileSystem), + trTextMap: make(map[string]*translator), + } +} + +func (p *domainManager) makeTrMapKey(domain, locale string) string { + return domain + "_$$$_" + locale +} + +func (p *domainManager) Bind(domain, path string, data []byte) (domains, paths []string) { + p.mutex.Lock() + defer p.mutex.Unlock() + + switch { + case domain != "" && path != "": // bind new domain + p.bindDomainTranslators(domain, path, data) + case domain != "" && path == "": // delete domain + p.deleteDomain(domain) + } + + // return all bind domain + for k, fs := range p.domainMap { + domains = append(domains, k) + paths = append(paths, fs.FsName) + } + return +} + +func (p *domainManager) SetLocale(locale string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + if locale != "" { + p.locale = locale + } + return p.locale +} + +func (p *domainManager) SetDomain(domain string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + if domain != "" { + p.domain = domain + } + return p.domain +} + +func (p *domainManager) Getdata(name string) []byte { + return p.getdata(p.domain, name) +} + +func (p *domainManager) DGetdata(domain, name string) []byte { + return p.getdata(domain, name) +} + +func (p *domainManager) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(p.domain, msgctxt, msgid, msgidPlural, n) +} + +func (p *domainManager) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(domain, msgctxt, msgid, msgidPlural, n) +} + +func (p *domainManager) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + if p.locale == "" || p.domain == "" { + return msgid + } + if _, ok := p.domainMap[domain]; !ok { + return msgid + } + if f, ok := p.trTextMap[p.makeTrMapKey(domain, p.locale)]; ok { + return f.PNGettext(msgctxt, msgid, msgidPlural, n) + } + return msgid +} + +func (p *domainManager) getdata(domain, name string) []byte { + if p.locale == "" || p.domain == "" { + return nil + } + if _, ok := p.domainMap[domain]; !ok { + return nil + } + if fs, ok := p.domainMap[domain]; ok { + if data, err := fs.LoadResourceFile(domain, p.locale, name); err == nil { + return data + } + if p.locale != "default" { + if data, err := fs.LoadResourceFile(domain, "default", name); err == nil { + return data + } + } + } + return nil +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go b/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go new file mode 100644 index 000000000..8dce58e65 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go @@ -0,0 +1,50 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "fmt" + "strings" +) + +func (p *domainManager) bindDomainTranslators(domain, path string, data []byte) { + if _, ok := p.domainMap[domain]; ok { + p.deleteDomain(domain) // delete old domain + } + fs := newFileSystem(path, data) + for locale, _ := range fs.LocaleMap { + trMapKey := p.makeTrMapKey(domain, locale) + if data, err := fs.LoadMessagesFile(domain, locale, ".mo"); err == nil { + p.trTextMap[trMapKey], _ = newMoTranslator( + fmt.Sprintf("%s_%s.mo", domain, locale), + data, + ) + continue + } + if data, err := fs.LoadMessagesFile(domain, locale, ".po"); err == nil { + p.trTextMap[trMapKey], _ = newPoTranslator( + fmt.Sprintf("%s_%s.po", domain, locale), + data, + ) + continue + } + p.trTextMap[p.makeTrMapKey(domain, locale)] = nilTranslator + } + p.domainMap[domain] = fs +} + +func (p *domainManager) deleteDomain(domain string) { + if _, ok := p.domainMap[domain]; !ok { + return + } + // delete all mo files + trMapKeyPrefix := p.makeTrMapKey(domain, "") + for k, _ := range p.trTextMap { + if strings.HasPrefix(k, trMapKeyPrefix) { + delete(p.trTextMap, k) + } + } + delete(p.domainMap, domain) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/fs.go b/vendor/github.com/chai2010/gettext-go/gettext/fs.go new file mode 100644 index 000000000..1c2e23c1d --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/fs.go @@ -0,0 +1,187 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "archive/zip" + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "strings" +) + +type fileSystem struct { + FsName string + FsRoot string + FsZipData []byte + LocaleMap map[string]bool +} + +func newFileSystem(path string, data []byte) *fileSystem { + fs := &fileSystem{ + FsName: path, + FsZipData: data, + } + if err := fs.init(); err != nil { + log.Printf("gettext-go: invalid domain, err = %v", err) + } + return fs +} + +func (p *fileSystem) init() error { + zipName := func(name string) string { + if x := strings.LastIndexAny(name, `\/`); x != -1 { + name = name[x+1:] + } + name = strings.TrimSuffix(name, ".zip") + return name + } + + // zip data + if len(p.FsZipData) != 0 { + p.FsRoot = zipName(p.FsName) + p.LocaleMap = p.lsZip(p.FsZipData) + return nil + } + + // local dir or zip file + fi, err := os.Stat(p.FsName) + if err != nil { + return err + } + + // local dir + if fi.IsDir() { + p.FsRoot = p.FsName + p.LocaleMap = p.lsDir(p.FsName) + return nil + } + + // local zip file + p.FsZipData, err = ioutil.ReadFile(p.FsName) + if err != nil { + return err + } + p.FsRoot = zipName(p.FsName) + p.LocaleMap = p.lsZip(p.FsZipData) + return nil +} + +func (p *fileSystem) LoadMessagesFile(domain, local, ext string) ([]byte, error) { + if len(p.FsZipData) == 0 { + trName := p.makeMessagesFileName(domain, local, ext) + rcData, err := ioutil.ReadFile(trName) + if err != nil { + return nil, err + } + return rcData, nil + } else { + r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) + if err != nil { + return nil, err + } + + trName := p.makeMessagesFileName(domain, local, ext) + for _, f := range r.File { + if f.Name != trName { + continue + } + rc, err := f.Open() + if err != nil { + return nil, err + } + rcData, err := ioutil.ReadAll(rc) + rc.Close() + return rcData, err + } + return nil, fmt.Errorf("not found") + } +} + +func (p *fileSystem) LoadResourceFile(domain, local, name string) ([]byte, error) { + if len(p.FsZipData) == 0 { + rcName := p.makeResourceFileName(domain, local, name) + rcData, err := ioutil.ReadFile(rcName) + if err != nil { + return nil, err + } + return rcData, nil + } else { + r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) + if err != nil { + return nil, err + } + + rcName := p.makeResourceFileName(domain, local, name) + for _, f := range r.File { + if f.Name != rcName { + continue + } + rc, err := f.Open() + if err != nil { + return nil, err + } + rcData, err := ioutil.ReadAll(rc) + rc.Close() + return rcData, err + } + return nil, fmt.Errorf("not found") + } +} + +func (p *fileSystem) makeMessagesFileName(domain, local, ext string) string { + return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.FsRoot, local, domain, ext) +} + +func (p *fileSystem) makeResourceFileName(domain, local, name string) string { + return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.FsRoot, local, domain, name) +} + +func (p *fileSystem) lsZip(data []byte) map[string]bool { + r, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + return nil + } + ssMap := make(map[string]bool) + for _, f := range r.File { + if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { + s := strings.TrimRight(f.Name[:x], `\/`) + if x = strings.LastIndexAny(s, `\/`); x != -1 { + s = s[x+1:] + } + if s != "" { + ssMap[s] = true + } + continue + } + if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { + s := strings.TrimRight(f.Name[:x], `\/`) + if x = strings.LastIndexAny(s, `\/`); x != -1 { + s = s[x+1:] + } + if s != "" { + ssMap[s] = true + } + continue + } + } + return ssMap +} + +func (p *fileSystem) lsDir(path string) map[string]bool { + list, err := ioutil.ReadDir(path) + if err != nil { + return nil + } + ssMap := make(map[string]bool) + for _, dir := range list { + if dir.IsDir() { + ssMap[dir.Name()] = true + } + } + return ssMap +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/gettext.go b/vendor/github.com/chai2010/gettext-go/gettext/gettext.go new file mode 100644 index 000000000..ca14065b2 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/gettext.go @@ -0,0 +1,184 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +var ( + defaultManager = newDomainManager() +) + +var ( + DefaultLocale = getDefaultLocale() // use $(LC_MESSAGES) or $(LANG) or "default" +) + +// SetLocale sets and queries the program's current locale. +// +// If the locale is not empty string, set the new local. +// +// If the locale is empty string, don't change anything. +// +// Returns is the current locale. +// +// Examples: +// SetLocale("") // get locale: return DefaultLocale +// SetLocale("zh_CN") // set locale: return zh_CN +// SetLocale("") // get locale: return zh_CN +func SetLocale(locale string) string { + return defaultManager.SetLocale(locale) +} + +// BindTextdomain sets and queries program's domains. +// +// If the domain and path are all not empty string, bind the new domain. +// If the domain already exists, return error. +// +// If the domain is not empty string, but the path is the empty string, +// delete the domain. +// If the domain don't exists, return error. +// +// If the domain and the path are all empty string, don't change anything. +// +// Returns is the all bind domains. +// +// Examples: +// BindTextdomain("poedit", "local", nil) // bind "poedit" domain +// BindTextdomain("", "", nil) // return all domains +// BindTextdomain("poedit", "", nil) // delete "poedit" domain +// BindTextdomain("", "", nil) // return all domains +// +// Use zip file: +// BindTextdomain("poedit", "local.zip", nil) // bind "poedit" domain +// BindTextdomain("poedit", "local.zip", zipData) // bind "poedit" domain +// +func BindTextdomain(domain, path string, zipData []byte) (domains, paths []string) { + return defaultManager.Bind(domain, path, zipData) +} + +// Textdomain sets and retrieves the current message domain. +// +// If the domain is not empty string, set the new domains. +// +// If the domain is empty string, don't change anything. +// +// Returns is the all used domains. +// +// Examples: +// Textdomain("poedit") // set domain: poedit +// Textdomain("") // get domain: return poedit +func Textdomain(domain string) string { + return defaultManager.SetDomain(domain) +} + +// Gettext attempt to translate a text string into the user's native language, +// by looking up the translation in a message catalog. +// +// It use the caller's function name as the msgctxt. +// +// Examples: +// func Foo() { +// msg := gettext.Gettext("Hello") // msgctxt is "some/package/name.Foo" +// } +func Gettext(msgid string) string { + return PGettext(callerName(2), msgid) +} + +// Getdata attempt to translate a resource file into the user's native language, +// by looking up the translation in a message catalog. +// +// Examples: +// func Foo() { +// Textdomain("hello") +// BindTextdomain("hello", "local.zip", nilOrZipData) +// poems := gettext.Getdata("poems.txt") +// } +func Getdata(name string) []byte { + return defaultManager.Getdata(name) +} + +// NGettext attempt to translate a text string into the user's native language, +// by looking up the appropriate plural form of the translation in a message +// catalog. +// +// It use the caller's function name as the msgctxt. +// +// Examples: +// func Foo() { +// msg := gettext.NGettext("%d people", "%d peoples", 2) +// } +func NGettext(msgid, msgidPlural string, n int) string { + return PNGettext(callerName(2), msgid, msgidPlural, n) +} + +// PGettext attempt to translate a text string into the user's native language, +// by looking up the translation in a message catalog. +// +// Examples: +// func Foo() { +// msg := gettext.PGettext("gettext-go.example", "Hello") // msgctxt is "gettext-go.example" +// } +func PGettext(msgctxt, msgid string) string { + return PNGettext(msgctxt, msgid, "", 0) +} + +// PNGettext attempt to translate a text string into the user's native language, +// by looking up the appropriate plural form of the translation in a message +// catalog. +// +// Examples: +// func Foo() { +// msg := gettext.PNGettext("gettext-go.example", "%d people", "%d peoples", 2) +// } +func PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + return defaultManager.PNGettext(msgctxt, msgid, msgidPlural, n) +} + +// DGettext like Gettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DGettext("poedit", "Hello") +// } +func DGettext(domain, msgid string) string { + return DPGettext(domain, callerName(2), msgid) +} + +// DNGettext like NGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.PNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) +// } +func DNGettext(domain, msgid, msgidPlural string, n int) string { + return DPNGettext(domain, callerName(2), msgid, msgidPlural, n) +} + +// DPGettext like PGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DPGettext("poedit", "gettext-go.example", "Hello") +// } +func DPGettext(domain, msgctxt, msgid string) string { + return DPNGettext(domain, msgctxt, msgid, "", 0) +} + +// DPNGettext like PNGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DPNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) +// } +func DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + return defaultManager.DPNGettext(domain, msgctxt, msgid, msgidPlural, n) +} + +// DGetdata like Getdata(), but looking up the resource in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DGetdata("hello", "poems.txt") +// } +func DGetdata(domain, name string) []byte { + return defaultManager.DGetdata(domain, name) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/local.go b/vendor/github.com/chai2010/gettext-go/gettext/local.go new file mode 100644 index 000000000..179a392fe --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/local.go @@ -0,0 +1,34 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "os" + "strings" +) + +func getDefaultLocale() string { + if v := os.Getenv("LC_MESSAGES"); v != "" { + return simplifiedLocale(v) + } + if v := os.Getenv("LANG"); v != "" { + return simplifiedLocale(v) + } + return "default" +} + +func simplifiedLocale(lang string) string { + // en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/... + if idx := strings.Index(lang, ":"); idx != -1 { + lang = lang[:idx] + } + if idx := strings.Index(lang, "@"); idx != -1 { + lang = lang[:idx] + } + if idx := strings.Index(lang, "."); idx != -1 { + lang = lang[:idx] + } + return strings.TrimSpace(lang) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go new file mode 100644 index 000000000..967768063 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go @@ -0,0 +1,74 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package mo provides support for reading and writing GNU MO file. + +Examples: + import ( + "github.com/chai2010/gettext-go/gettext/mo" + ) + + func main() { + moFile, err := mo.Load("test.mo") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%v", moFile) + } + +GNU MO file struct: + + byte + +------------------------------------------+ + 0 | magic number = 0x950412de | + | | + 4 | file format revision = 0 | + | | + 8 | number of strings | == N + | | + 12 | offset of table with original strings | == O + | | + 16 | offset of table with translation strings | == T + | | + 20 | size of hashing table | == S + | | + 24 | offset of hashing table | == H + | | + . . + . (possibly more entries later) . + . . + | | + O | length & offset 0th string ----------------. + O + 8 | length & offset 1st string ------------------. + ... ... | | + O + ((N-1)*8)| length & offset (N-1)th string | | | + | | | | + T | length & offset 0th translation ---------------. + T + 8 | length & offset 1st translation -----------------. + ... ... | | | | + T + ((N-1)*8)| length & offset (N-1)th translation | | | | | + | | | | | | + H | start hash table | | | | | + ... ... | | | | + H + S * 4 | end hash table | | | | | + | | | | | | + | NUL terminated 0th string <----------------' | | | + | | | | | + | NUL terminated 1st string <------------------' | | + | | | | + ... ... | | + | | | | + | NUL terminated 0th translation <---------------' | + | | | + | NUL terminated 1st translation <-----------------' + | | + ... ... + | | + +------------------------------------------+ + +The GNU MO file specification is at +http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html. +*/ +package mo diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go new file mode 100644 index 000000000..9b1c240b4 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go @@ -0,0 +1,124 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "encoding/binary" + "sort" + "strings" +) + +type moHeader struct { + MagicNumber uint32 + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 +} + +type moStrPos struct { + Size uint32 // must keep fields order + Addr uint32 +} + +func encodeFile(f *File) []byte { + hdr := &moHeader{ + MagicNumber: MoMagicLittleEndian, + } + data := encodeData(hdr, f) + data = append(encodeHeader(hdr), data...) + return data +} + +// encode data and init moHeader +func encodeData(hdr *moHeader, f *File) []byte { + msgList := []Message{f.MimeHeader.toMessage()} + for _, v := range f.Messages { + if len(v.MsgId) == 0 { + continue + } + if len(v.MsgStr) == 0 && len(v.MsgStrPlural) == 0 { + continue + } + msgList = append(msgList, v) + } + sort.Sort(byMessages(msgList)) + + var buf bytes.Buffer + var msgIdPosList = make([]moStrPos, len(msgList)) + var msgStrPosList = make([]moStrPos, len(msgList)) + for i, v := range msgList { + // write msgid + msgId := encodeMsgId(v) + msgIdPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) + msgIdPosList[i].Size = uint32(len(msgId)) + buf.WriteString(msgId) + // write msgstr + msgStr := encodeMsgStr(v) + msgStrPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) + msgStrPosList[i].Size = uint32(len(msgStr)) + buf.WriteString(msgStr) + } + + hdr.MsgIdOffset = uint32(buf.Len() + MoHeaderSize) + binary.Write(&buf, binary.LittleEndian, msgIdPosList) + hdr.MsgStrOffset = uint32(buf.Len() + MoHeaderSize) + binary.Write(&buf, binary.LittleEndian, msgStrPosList) + + hdr.MsgIdCount = uint32(len(msgList)) + return buf.Bytes() +} + +// must called after encodeData +func encodeHeader(hdr *moHeader) []byte { + var buf bytes.Buffer + binary.Write(&buf, binary.LittleEndian, hdr) + return buf.Bytes() +} + +func encodeMsgId(v Message) string { + if v.MsgContext != "" && v.MsgIdPlural != "" { + return v.MsgContext + EotSeparator + v.MsgId + NulSeparator + v.MsgIdPlural + } + if v.MsgContext != "" && v.MsgIdPlural == "" { + return v.MsgContext + EotSeparator + v.MsgId + } + if v.MsgContext == "" && v.MsgIdPlural != "" { + return v.MsgId + NulSeparator + v.MsgIdPlural + } + return v.MsgId +} + +func encodeMsgStr(v Message) string { + if v.MsgIdPlural != "" { + return strings.Join(v.MsgStrPlural, NulSeparator) + } + return v.MsgStr +} + +type byMessages []Message + +func (d byMessages) Len() int { + return len(d) +} +func (d byMessages) Less(i, j int) bool { + if a, b := d[i].MsgContext, d[j].MsgContext; a != b { + return a < b + } + if a, b := d[i].MsgId, d[j].MsgId; a != b { + return a < b + } + if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { + return a < b + } + return false +} +func (d byMessages) Swap(i, j int) { + d[i], d[j] = d[j], d[i] +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go new file mode 100644 index 000000000..b49a77b42 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go @@ -0,0 +1,193 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "strings" +) + +const ( + MoHeaderSize = 28 + MoMagicLittleEndian = 0x950412de + MoMagicBigEndian = 0xde120495 + + EotSeparator = "\x04" // msgctxt and msgid separator + NulSeparator = "\x00" // msgid and msgstr separator +) + +// File represents an MO File. +// +// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html +type File struct { + MagicNumber uint32 + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 + MimeHeader Header + Messages []Message +} + +// Load loads a named mo file. +func Load(name string) (*File, error) { + data, err := ioutil.ReadFile(name) + if err != nil { + return nil, err + } + return LoadData(data) +} + +// LoadData loads mo file format data. +func LoadData(data []byte) (*File, error) { + r := bytes.NewReader(data) + + var magicNumber uint32 + if err := binary.Read(r, binary.LittleEndian, &magicNumber); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + var bo binary.ByteOrder + switch magicNumber { + case MoMagicLittleEndian: + bo = binary.LittleEndian + case MoMagicBigEndian: + bo = binary.BigEndian + default: + return nil, fmt.Errorf("gettext: %v", "invalid magic number") + } + + var header struct { + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 + } + if err := binary.Read(r, bo, &header); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if v := header.MajorVersion; v != 0 && v != 1 { + return nil, fmt.Errorf("gettext: %v", "invalid version number") + } + if v := header.MinorVersion; v != 0 && v != 1 { + return nil, fmt.Errorf("gettext: %v", "invalid version number") + } + + msgIdStart := make([]uint32, header.MsgIdCount) + msgIdLen := make([]uint32, header.MsgIdCount) + if _, err := r.Seek(int64(header.MsgIdOffset), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + for i := 0; i < int(header.MsgIdCount); i++ { + if err := binary.Read(r, bo, &msgIdLen[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if err := binary.Read(r, bo, &msgIdStart[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + } + + msgStrStart := make([]int32, header.MsgIdCount) + msgStrLen := make([]int32, header.MsgIdCount) + if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + for i := 0; i < int(header.MsgIdCount); i++ { + if err := binary.Read(r, bo, &msgStrLen[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if err := binary.Read(r, bo, &msgStrStart[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + } + + file := &File{ + MagicNumber: magicNumber, + MajorVersion: header.MajorVersion, + MinorVersion: header.MinorVersion, + MsgIdCount: header.MsgIdCount, + MsgIdOffset: header.MsgIdOffset, + MsgStrOffset: header.MsgStrOffset, + HashSize: header.HashSize, + HashOffset: header.HashOffset, + } + for i := 0; i < int(header.MsgIdCount); i++ { + if _, err := r.Seek(int64(msgIdStart[i]), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + msgIdData := make([]byte, msgIdLen[i]) + if _, err := r.Read(msgIdData); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + + if _, err := r.Seek(int64(msgStrStart[i]), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + msgStrData := make([]byte, msgStrLen[i]) + if _, err := r.Read(msgStrData); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + + if len(msgIdData) == 0 { + var msg = Message{ + MsgId: string(msgIdData), + MsgStr: string(msgStrData), + } + file.MimeHeader.fromMessage(&msg) + } else { + var msg = Message{ + MsgId: string(msgIdData), + MsgStr: string(msgStrData), + } + // Is this a context message? + if idx := strings.Index(msg.MsgId, EotSeparator); idx != -1 { + msg.MsgContext, msg.MsgId = msg.MsgId[:idx], msg.MsgId[idx+1:] + } + // Is this a plural message? + if idx := strings.Index(msg.MsgId, NulSeparator); idx != -1 { + msg.MsgId, msg.MsgIdPlural = msg.MsgId[:idx], msg.MsgId[idx+1:] + msg.MsgStrPlural = strings.Split(msg.MsgStr, NulSeparator) + msg.MsgStr = "" + } + file.Messages = append(file.Messages, msg) + } + } + + return file, nil +} + +// Save saves a mo file. +func (f *File) Save(name string) error { + return ioutil.WriteFile(name, f.Data(), 0666) +} + +// Save returns a mo file format data. +func (f *File) Data() []byte { + return encodeFile(f) +} + +// String returns the po format file string. +func (f *File) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "# version: %d.%d\n", f.MajorVersion, f.MinorVersion) + fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) + fmt.Fprintf(&buf, "\n") + + for k, v := range f.Messages { + fmt.Fprintf(&buf, `msgid "%v"`+"\n", k) + fmt.Fprintf(&buf, `msgstr "%s"`+"\n", v.MsgStr) + fmt.Fprintf(&buf, "\n") + } + + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/header.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/header.go new file mode 100644 index 000000000..d8c7a5e3a --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/header.go @@ -0,0 +1,109 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "fmt" + "strings" +) + +// Header is the initial comments "SOME DESCRIPTIVE TITLE", "YEAR" +// and "FIRST AUTHOR , YEAR" ought to be replaced by sensible information. +// +// See http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#Header-Entry +type Header struct { + ProjectIdVersion string // Project-Id-Version: PACKAGE VERSION + ReportMsgidBugsTo string // Report-Msgid-Bugs-To: FIRST AUTHOR + POTCreationDate string // POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE + PORevisionDate string // PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE + LastTranslator string // Last-Translator: FIRST AUTHOR + LanguageTeam string // Language-Team: golang-china + Language string // Language: zh_CN + MimeVersion string // MIME-Version: 1.0 + ContentType string // Content-Type: text/plain; charset=UTF-8 + ContentTransferEncoding string // Content-Transfer-Encoding: 8bit + PluralForms string // Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1; + XGenerator string // X-Generator: Poedit 1.5.5 + UnknowFields map[string]string +} + +func (p *Header) fromMessage(msg *Message) { + if msg.MsgId != "" || msg.MsgStr == "" { + return + } + lines := strings.Split(msg.MsgStr, "\n") + for i := 0; i < len(lines); i++ { + idx := strings.Index(lines[i], ":") + if idx < 0 { + continue + } + key := strings.TrimSpace(lines[i][:idx]) + val := strings.TrimSpace(lines[i][idx+1:]) + switch strings.ToUpper(key) { + case strings.ToUpper("Project-Id-Version"): + p.ProjectIdVersion = val + case strings.ToUpper("Report-Msgid-Bugs-To"): + p.ReportMsgidBugsTo = val + case strings.ToUpper("POT-Creation-Date"): + p.POTCreationDate = val + case strings.ToUpper("PO-Revision-Date"): + p.PORevisionDate = val + case strings.ToUpper("Last-Translator"): + p.LastTranslator = val + case strings.ToUpper("Language-Team"): + p.LanguageTeam = val + case strings.ToUpper("Language"): + p.Language = val + case strings.ToUpper("MIME-Version"): + p.MimeVersion = val + case strings.ToUpper("Content-Type"): + p.ContentType = val + case strings.ToUpper("Content-Transfer-Encoding"): + p.ContentTransferEncoding = val + case strings.ToUpper("Plural-Forms"): + p.PluralForms = val + case strings.ToUpper("X-Generator"): + p.XGenerator = val + default: + if p.UnknowFields == nil { + p.UnknowFields = make(map[string]string) + } + p.UnknowFields[key] = val + } + } +} + +func (p *Header) toMessage() Message { + return Message{ + MsgStr: p.String(), + } +} + +// String returns the po format header string. +func (p Header) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, `msgid ""`+"\n") + fmt.Fprintf(&buf, `msgstr ""`+"\n") + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Project-Id-Version", p.ProjectIdVersion) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Report-Msgid-Bugs-To", p.ReportMsgidBugsTo) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "POT-Creation-Date", p.POTCreationDate) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "PO-Revision-Date", p.PORevisionDate) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Last-Translator", p.LastTranslator) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language-Team", p.LanguageTeam) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language", p.Language) + if p.MimeVersion != "" { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "MIME-Version", p.MimeVersion) + } + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Type", p.ContentType) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Transfer-Encoding", p.ContentTransferEncoding) + if p.XGenerator != "" { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "X-Generator", p.XGenerator) + } + for k, v := range p.UnknowFields { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", k, v) + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go new file mode 100644 index 000000000..91ad79bec --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go @@ -0,0 +1,39 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "fmt" +) + +// A MO file is made up of many entries, +// each entry holding the relation between an original untranslated string +// and its corresponding translation. +// +// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html +type Message struct { + MsgContext string // msgctxt context + MsgId string // msgid untranslated-string + MsgIdPlural string // msgid_plural untranslated-string-plural + MsgStr string // msgstr translated-string + MsgStrPlural []string // msgstr[0] translated-string-case-0 +} + +// String returns the po format entry string. +func (p Message) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) + if p.MsgIdPlural != "" { + fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) + } + if p.MsgStr != "" { + fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) + } + for i := 0; i < len(p.MsgStrPlural); i++ { + fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/util.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/util.go new file mode 100644 index 000000000..380451105 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/mo/util.go @@ -0,0 +1,110 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "strings" +) + +func decodePoString(text string) string { + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + left := strings.Index(lines[i], `"`) + right := strings.LastIndex(lines[i], `"`) + if left < 0 || right < 0 || left == right { + lines[i] = "" + continue + } + line := lines[i][left+1 : right] + data := make([]byte, 0, len(line)) + for i := 0; i < len(line); i++ { + if line[i] != '\\' { + data = append(data, line[i]) + continue + } + if i+1 >= len(line) { + break + } + switch line[i+1] { + case 'n': // \\n -> \n + data = append(data, '\n') + i++ + case 't': // \\t -> \n + data = append(data, '\t') + i++ + case '\\': // \\\ -> ? + data = append(data, '\\') + i++ + } + } + lines[i] = string(data) + } + return strings.Join(lines, "") +} + +func encodePoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + if lines[i] == "" { + if i != len(lines)-1 { + buf.WriteString(`"\n"` + "\n") + } + continue + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + buf.WriteString(`\n"` + "\n") + } + return buf.String() +} + +func encodeCommentPoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + if len(lines) > 1 { + buf.WriteString(`""` + "\n") + } + for i := 0; i < len(lines); i++ { + if len(lines) > 0 { + buf.WriteString("#| ") + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + if i < len(lines)-1 { + buf.WriteString(`\n"` + "\n") + } else { + buf.WriteString(`"`) + } + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go new file mode 100644 index 000000000..5641e2c3e --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go @@ -0,0 +1,36 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package plural provides standard plural formulas. + +Examples: + import ( + "code.google.com/p/gettext-go/gettext/plural" + ) + + func main() { + enFormula := plural.Formula("en_US") + xxFormula := plural.Formula("zh_CN") + + fmt.Printf("%s: %d\n", "en", enFormula(0)) + fmt.Printf("%s: %d\n", "en", enFormula(1)) + fmt.Printf("%s: %d\n", "en", enFormula(2)) + fmt.Printf("%s: %d\n", "??", xxFormula(0)) + fmt.Printf("%s: %d\n", "??", xxFormula(1)) + fmt.Printf("%s: %d\n", "??", xxFormula(2)) + fmt.Printf("%s: %d\n", "??", xxFormula(9)) + // Output: + // en: 0 + // en: 0 + // en: 1 + // ??: 0 + // ??: 0 + // ??: 1 + // ??: 8 + } + +See http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html +*/ +package plural diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go b/vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go new file mode 100644 index 000000000..679a1cd50 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go @@ -0,0 +1,181 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package plural + +import ( + "strings" +) + +// Formula provides the language's standard plural formula. +func Formula(lang string) func(n int) int { + if idx := index(lang); idx != -1 { + return formulaTable[fmtForms(FormsTable[idx].Value)] + } + if idx := index("??"); idx != -1 { + return formulaTable[fmtForms(FormsTable[idx].Value)] + } + return func(n int) int { + return n + } +} + +func index(lang string) int { + for i := 0; i < len(FormsTable); i++ { + if strings.HasPrefix(lang, FormsTable[i].Lang) { + return i + } + } + return -1 +} + +func fmtForms(forms string) string { + forms = strings.TrimSpace(forms) + forms = strings.Replace(forms, " ", "", -1) + return forms +} + +var formulaTable = map[string]func(n int) int{ + fmtForms("nplurals=n; plural=n-1;"): func(n int) int { + if n > 0 { + return n - 1 + } + return 0 + }, + fmtForms("nplurals=1; plural=0;"): func(n int) int { + return 0 + }, + fmtForms("nplurals=2; plural=(n != 1);"): func(n int) int { + if n <= 1 { + return 0 + } + return 1 + }, + fmtForms("nplurals=2; plural=(n > 1);"): func(n int) int { + if n <= 1 { + return 0 + } + return 1 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n != 0 { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"): func(n int) int { + if n == 1 { + return 0 + } + if n == 2 { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;"): func(n int) int { + if n == 1 { + return 0 + } + if n == 0 || (n%100 > 0 && n%100 < 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n%10 == 1 && n%100 != 11 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"): func(n int) int { + if n == 1 { + return 0 + } + if n >= 2 && n <= 4 { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"): func(n int) int { + if n == 1 { + return 0 + } + if n >= 2 && n <= 4 { + return 1 + } + return 2 + }, + fmtForms("nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"): func(n int) int { + if n == 1 { + return 0 + } + if n%10 >= 2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20) { + return 1 + } + return 2 + }, + fmtForms("nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"): func(n int) int { + if n%100 == 1 { + return 0 + } + if n%100 == 2 { + return 1 + } + if n%100 == 3 || n%100 == 4 { + return 2 + } + return 3 + }, +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/table.go b/vendor/github.com/chai2010/gettext-go/gettext/plural/table.go new file mode 100644 index 000000000..cdc50d211 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/plural/table.go @@ -0,0 +1,55 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package plural + +// FormsTable are standard hard-coded plural rules. +// The application developers and the translators need to understand them. +// +// See GNU's gettext library source code: gettext/gettext-tools/src/plural-table.c +var FormsTable = []struct { + Lang string + Language string + Value string +}{ + {"??", "Unknown", "nplurals=1; plural=0;"}, + {"ja", "Japanese", "nplurals=1; plural=0;"}, + {"vi", "Vietnamese", "nplurals=1; plural=0;"}, + {"ko", "Korean", "nplurals=1; plural=0;"}, + {"en", "English", "nplurals=2; plural=(n != 1);"}, + {"de", "German", "nplurals=2; plural=(n != 1);"}, + {"nl", "Dutch", "nplurals=2; plural=(n != 1);"}, + {"sv", "Swedish", "nplurals=2; plural=(n != 1);"}, + {"da", "Danish", "nplurals=2; plural=(n != 1);"}, + {"no", "Norwegian", "nplurals=2; plural=(n != 1);"}, + {"nb", "Norwegian Bokmal", "nplurals=2; plural=(n != 1);"}, + {"nn", "Norwegian Nynorsk", "nplurals=2; plural=(n != 1);"}, + {"fo", "Faroese", "nplurals=2; plural=(n != 1);"}, + {"es", "Spanish", "nplurals=2; plural=(n != 1);"}, + {"pt", "Portuguese", "nplurals=2; plural=(n != 1);"}, + {"it", "Italian", "nplurals=2; plural=(n != 1);"}, + {"bg", "Bulgarian", "nplurals=2; plural=(n != 1);"}, + {"el", "Greek", "nplurals=2; plural=(n != 1);"}, + {"fi", "Finnish", "nplurals=2; plural=(n != 1);"}, + {"et", "Estonian", "nplurals=2; plural=(n != 1);"}, + {"he", "Hebrew", "nplurals=2; plural=(n != 1);"}, + {"eo", "Esperanto", "nplurals=2; plural=(n != 1);"}, + {"hu", "Hungarian", "nplurals=2; plural=(n != 1);"}, + {"tr", "Turkish", "nplurals=2; plural=(n != 1);"}, + {"pt_BR", "Brazilian", "nplurals=2; plural=(n > 1);"}, + {"fr", "French", "nplurals=2; plural=(n > 1);"}, + {"lv", "Latvian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"}, + {"ga", "Irish", "nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"}, + {"ro", "Romanian", "nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;"}, + {"lt", "Lithuanian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"ru", "Russian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"uk", "Ukrainian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"be", "Belarusian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"sr", "Serbian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"hr", "Croatian", "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"cs", "Czech", "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"}, + {"sk", "Slovak", "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"}, + {"pl", "Polish", "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"}, + {"sl", "Slovenian", "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"}, +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/comment.go b/vendor/github.com/chai2010/gettext-go/gettext/po/comment.go new file mode 100644 index 000000000..d4abe7c10 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/comment.go @@ -0,0 +1,270 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "io" + "strconv" + "strings" +) + +// Comment represents every message's comments. +type Comment struct { + StartLine int // comment start line + TranslatorComment string // # translator-comments // TrimSpace + ExtractedComment string // #. extracted-comments + ReferenceFile []string // #: src/msgcmp.c:338 src/po-lex.c:699 + ReferenceLine []int // #: src/msgcmp.c:338 src/po-lex.c:699 + Flags []string // #, fuzzy,c-format,range:0..10 + PrevMsgContext string // #| msgctxt previous-context + PrevMsgId string // #| msgid previous-untranslated-string +} + +func (p *Comment) less(q *Comment) bool { + if p.StartLine != 0 || q.StartLine != 0 { + return p.StartLine < q.StartLine + } + if a, b := len(p.ReferenceFile), len(q.ReferenceFile); a != b { + return a < b + } + for i := 0; i < len(p.ReferenceFile); i++ { + if a, b := p.ReferenceFile[i], q.ReferenceFile[i]; a != b { + return a < b + } + if a, b := p.ReferenceLine[i], q.ReferenceLine[i]; a != b { + return a < b + } + } + return false +} + +func (p *Comment) readPoComment(r *lineReader) (err error) { + *p = Comment{} + if err = r.skipBlankLine(); err != nil { + return err + } + defer func(oldPos int) { + newPos := r.currentPos() + if newPos != oldPos && err == io.EOF { + err = nil + } + }(r.currentPos()) + + p.StartLine = r.currentPos() + 1 + for { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if len(s) == 0 || s[0] != '#' { + return + } + + if err = p.readTranslatorComment(r); err != nil { + return + } + if err = p.readExtractedComment(r); err != nil { + return + } + if err = p.readReferenceComment(r); err != nil { + return + } + if err = p.readFlagsComment(r); err != nil { + return + } + if err = p.readPrevMsgContext(r); err != nil { + return + } + if err = p.readPrevMsgId(r); err != nil { + return + } + } +} + +func (p *Comment) readTranslatorComment(r *lineReader) (err error) { + const prefix = "# " // .,:| + for { + var s string + if s, _, err = r.readLine(); err != nil { + return err + } + if len(s) < 1 || s[0] != '#' { + r.unreadLine() + return nil + } + if len(s) >= 2 { + switch s[1] { + case '.', ',', ':', '|': + r.unreadLine() + return nil + } + } + if p.TranslatorComment != "" { + p.TranslatorComment += "\n" + } + p.TranslatorComment += strings.TrimSpace(s[1:]) + } +} + +func (p *Comment) readExtractedComment(r *lineReader) (err error) { + const prefix = "#." + for { + var s string + if s, _, err = r.readLine(); err != nil { + return err + } + if len(s) < len(prefix) || s[:len(prefix)] != prefix { + r.unreadLine() + return nil + } + if p.ExtractedComment != "" { + p.ExtractedComment += "\n" + } + p.ExtractedComment += strings.TrimSpace(s[len(prefix):]) + } +} + +func (p *Comment) readReferenceComment(r *lineReader) (err error) { + const prefix = "#:" + for { + var s string + if s, _, err = r.readLine(); err != nil { + return err + } + if len(s) < len(prefix) || s[:len(prefix)] != prefix { + r.unreadLine() + return nil + } + ss := strings.Split(strings.TrimSpace(s[len(prefix):]), " ") + for i := 0; i < len(ss); i++ { + idx := strings.Index(ss[i], ":") + if idx <= 0 { + continue + } + name := strings.TrimSpace(ss[i][:idx]) + line, _ := strconv.Atoi(strings.TrimSpace(ss[i][idx+1:])) + p.ReferenceFile = append(p.ReferenceFile, name) + p.ReferenceLine = append(p.ReferenceLine, line) + } + } +} + +func (p *Comment) readFlagsComment(r *lineReader) (err error) { + const prefix = "#," + for { + var s string + if s, _, err = r.readLine(); err != nil { + return err + } + if len(s) < len(prefix) || s[:len(prefix)] != prefix { + r.unreadLine() + return nil + } + ss := strings.Split(strings.TrimSpace(s[len(prefix):]), ",") + for i := 0; i < len(ss); i++ { + p.Flags = append(p.Flags, strings.TrimSpace(ss[i])) + } + } +} + +func (p *Comment) readPrevMsgContext(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !rePrevMsgContextComments.MatchString(s) { + return + } + p.PrevMsgContext, err = p.readString(r) + return +} + +func (p *Comment) readPrevMsgId(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !rePrevMsgIdComments.MatchString(s) { + return + } + p.PrevMsgId, err = p.readString(r) + return +} + +func (p *Comment) readString(r *lineReader) (msg string, err error) { + var s string + if s, _, err = r.readLine(); err != nil { + return + } + msg += decodePoString(s) + for { + if s, _, err = r.readLine(); err != nil { + return + } + if !reStringLineComments.MatchString(s) { + r.unreadLine() + break + } + msg += decodePoString(s) + } + return +} + +// GetFuzzy gets the fuzzy flag. +func (p *Comment) GetFuzzy() bool { + for _, s := range p.Flags { + if s == "fuzzy" { + return true + } + } + return false +} + +// SetFuzzy sets the fuzzy flag. +func (p *Comment) SetFuzzy(fuzzy bool) { + // +} + +// String returns the po format comment string. +func (p Comment) String() string { + var buf bytes.Buffer + if p.TranslatorComment != "" { + ss := strings.Split(p.TranslatorComment, "\n") + for i := 0; i < len(ss); i++ { + fmt.Fprintf(&buf, "# %s\n", ss[i]) + } + } + if p.ExtractedComment != "" { + ss := strings.Split(p.ExtractedComment, "\n") + for i := 0; i < len(ss); i++ { + fmt.Fprintf(&buf, "#. %s\n", ss[i]) + } + } + if a, b := len(p.ReferenceFile), len(p.ReferenceLine); a != 0 && a == b { + fmt.Fprintf(&buf, "#:") + for i := 0; i < len(p.ReferenceFile); i++ { + fmt.Fprintf(&buf, " %s:%d", p.ReferenceFile[i], p.ReferenceLine[i]) + } + fmt.Fprintf(&buf, "\n") + } + if len(p.Flags) != 0 { + fmt.Fprintf(&buf, "#, %s", p.Flags[0]) + for i := 1; i < len(p.Flags); i++ { + fmt.Fprintf(&buf, ", %s", p.Flags[i]) + } + fmt.Fprintf(&buf, "\n") + } + if p.PrevMsgContext != "" { + s := encodeCommentPoString(p.PrevMsgContext) + fmt.Fprintf(&buf, "#| msgctxt %s\n", s) + } + if p.PrevMsgId != "" { + s := encodeCommentPoString(p.PrevMsgId) + fmt.Fprintf(&buf, "#| msgid %s\n", s) + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go new file mode 100644 index 000000000..12bac8f2a --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go @@ -0,0 +1,24 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package po provides support for reading and writing GNU PO file. + +Examples: + import ( + "github.com/chai2010/gettext-go/gettext/po" + ) + + func main() { + poFile, err := po.Load("test.po") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%v", poFile) + } + +The GNU PO file specification is at +http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html. +*/ +package po diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/file.go b/vendor/github.com/chai2010/gettext-go/gettext/po/file.go new file mode 100644 index 000000000..a9b7abf94 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/file.go @@ -0,0 +1,75 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "sort" +) + +// File represents an PO File. +// +// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html +type File struct { + MimeHeader Header + Messages []Message +} + +// Load loads a named po file. +func Load(name string) (*File, error) { + data, err := ioutil.ReadFile(name) + if err != nil { + return nil, err + } + return LoadData(data) +} + +// LoadData loads po file format data. +func LoadData(data []byte) (*File, error) { + r := newLineReader(string(data)) + var file File + for { + var msg Message + if err := msg.readPoEntry(r); err != nil { + if err == io.EOF { + return &file, nil + } + return nil, err + } + if msg.MsgId == "" { + file.MimeHeader.parseHeader(&msg) + continue + } + file.Messages = append(file.Messages, msg) + } +} + +// Save saves a po file. +func (f *File) Save(name string) error { + return ioutil.WriteFile(name, []byte(f.String()), 0666) +} + +// Save returns a po file format data. +func (f *File) Data() []byte { + // sort the massge as ReferenceFile/ReferenceLine field + var messages []Message + messages = append(messages, f.Messages...) + sort.Sort(byMessages(messages)) + + var buf bytes.Buffer + fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) + for i := 0; i < len(messages); i++ { + fmt.Fprintf(&buf, "%s\n", messages[i].String()) + } + return buf.Bytes() +} + +// String returns the po format file string. +func (f *File) String() string { + return string(f.Data()) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/header.go b/vendor/github.com/chai2010/gettext-go/gettext/po/header.go new file mode 100644 index 000000000..a9b5b6671 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/header.go @@ -0,0 +1,106 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "strings" +) + +// Header is the initial comments "SOME DESCRIPTIVE TITLE", "YEAR" +// and "FIRST AUTHOR , YEAR" ought to be replaced by sensible information. +// +// See http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#Header-Entry +type Header struct { + Comment // Header Comments + ProjectIdVersion string // Project-Id-Version: PACKAGE VERSION + ReportMsgidBugsTo string // Report-Msgid-Bugs-To: FIRST AUTHOR + POTCreationDate string // POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE + PORevisionDate string // PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE + LastTranslator string // Last-Translator: FIRST AUTHOR + LanguageTeam string // Language-Team: golang-china + Language string // Language: zh_CN + MimeVersion string // MIME-Version: 1.0 + ContentType string // Content-Type: text/plain; charset=UTF-8 + ContentTransferEncoding string // Content-Transfer-Encoding: 8bit + PluralForms string // Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1; + XGenerator string // X-Generator: Poedit 1.5.5 + UnknowFields map[string]string +} + +func (p *Header) parseHeader(msg *Message) { + if msg.MsgId != "" || msg.MsgStr == "" { + return + } + lines := strings.Split(msg.MsgStr, "\n") + for i := 0; i < len(lines); i++ { + idx := strings.Index(lines[i], ":") + if idx < 0 { + continue + } + key := strings.TrimSpace(lines[i][:idx]) + val := strings.TrimSpace(lines[i][idx+1:]) + switch strings.ToUpper(key) { + case strings.ToUpper("Project-Id-Version"): + p.ProjectIdVersion = val + case strings.ToUpper("Report-Msgid-Bugs-To"): + p.ReportMsgidBugsTo = val + case strings.ToUpper("POT-Creation-Date"): + p.POTCreationDate = val + case strings.ToUpper("PO-Revision-Date"): + p.PORevisionDate = val + case strings.ToUpper("Last-Translator"): + p.LastTranslator = val + case strings.ToUpper("Language-Team"): + p.LanguageTeam = val + case strings.ToUpper("Language"): + p.Language = val + case strings.ToUpper("MIME-Version"): + p.MimeVersion = val + case strings.ToUpper("Content-Type"): + p.ContentType = val + case strings.ToUpper("Content-Transfer-Encoding"): + p.ContentTransferEncoding = val + case strings.ToUpper("Plural-Forms"): + p.PluralForms = val + case strings.ToUpper("X-Generator"): + p.XGenerator = val + default: + if p.UnknowFields == nil { + p.UnknowFields = make(map[string]string) + } + p.UnknowFields[key] = val + } + } + p.Comment = msg.Comment +} + +// String returns the po format header string. +func (p Header) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%s", p.Comment.String()) + fmt.Fprintf(&buf, `msgid ""`+"\n") + fmt.Fprintf(&buf, `msgstr ""`+"\n") + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Project-Id-Version", p.ProjectIdVersion) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Report-Msgid-Bugs-To", p.ReportMsgidBugsTo) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "POT-Creation-Date", p.POTCreationDate) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "PO-Revision-Date", p.PORevisionDate) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Last-Translator", p.LastTranslator) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language-Team", p.LanguageTeam) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language", p.Language) + if p.MimeVersion != "" { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "MIME-Version", p.MimeVersion) + } + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Type", p.ContentType) + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Transfer-Encoding", p.ContentTransferEncoding) + if p.XGenerator != "" { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "X-Generator", p.XGenerator) + } + for k, v := range p.UnknowFields { + fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", k, v) + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go b/vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go new file mode 100644 index 000000000..8597273a2 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go @@ -0,0 +1,62 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "io" + "strings" +) + +type lineReader struct { + lines []string + pos int +} + +func newLineReader(data string) *lineReader { + data = strings.Replace(data, "\r", "", -1) + lines := strings.Split(data, "\n") + return &lineReader{lines: lines} +} + +func (r *lineReader) skipBlankLine() error { + for ; r.pos < len(r.lines); r.pos++ { + if strings.TrimSpace(r.lines[r.pos]) != "" { + break + } + } + if r.pos >= len(r.lines) { + return io.EOF + } + return nil +} + +func (r *lineReader) currentPos() int { + return r.pos +} + +func (r *lineReader) currentLine() (s string, pos int, err error) { + if r.pos >= len(r.lines) { + err = io.EOF + return + } + s, pos = r.lines[r.pos], r.pos + return +} + +func (r *lineReader) readLine() (s string, pos int, err error) { + if r.pos >= len(r.lines) { + err = io.EOF + return + } + s, pos = r.lines[r.pos], r.pos + r.pos++ + return +} + +func (r *lineReader) unreadLine() { + if r.pos >= 0 { + r.pos-- + } +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/message.go b/vendor/github.com/chai2010/gettext-go/gettext/po/message.go new file mode 100644 index 000000000..a2cf2512c --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/message.go @@ -0,0 +1,189 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "io" + "strconv" + "strings" +) + +// A PO file is made up of many entries, +// each entry holding the relation between an original untranslated string +// and its corresponding translation. +// +// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html +type Message struct { + Comment // Coments + MsgContext string // msgctxt context + MsgId string // msgid untranslated-string + MsgIdPlural string // msgid_plural untranslated-string-plural + MsgStr string // msgstr translated-string + MsgStrPlural []string // msgstr[0] translated-string-case-0 +} + +type byMessages []Message + +func (d byMessages) Len() int { + return len(d) +} +func (d byMessages) Less(i, j int) bool { + if d[i].Comment.less(&d[j].Comment) { + return true + } + if a, b := d[i].MsgContext, d[j].MsgContext; a != b { + return a < b + } + if a, b := d[i].MsgId, d[j].MsgId; a != b { + return a < b + } + if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { + return a < b + } + return false +} +func (d byMessages) Swap(i, j int) { + d[i], d[j] = d[j], d[i] +} + +func (p *Message) readPoEntry(r *lineReader) (err error) { + *p = Message{} + if err = r.skipBlankLine(); err != nil { + return + } + defer func(oldPos int) { + newPos := r.currentPos() + if newPos != oldPos && err == io.EOF { + err = nil + } + }(r.currentPos()) + + if err = p.Comment.readPoComment(r); err != nil { + return + } + for { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + + if p.isInvalidLine(s) { + err = fmt.Errorf("gettext: line %d, %v", r.currentPos(), "invalid line") + return + } + if reComment.MatchString(s) || reBlankLine.MatchString(s) { + return + } + + if err = p.readMsgContext(r); err != nil { + return + } + if err = p.readMsgId(r); err != nil { + return + } + if err = p.readMsgIdPlural(r); err != nil { + return + } + if err = p.readMsgStrOrPlural(r); err != nil { + return + } + } +} + +func (p *Message) readMsgContext(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgContext.MatchString(s) { + return + } + p.MsgContext, err = p.readString(r) + return +} + +func (p *Message) readMsgId(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgId.MatchString(s) { + return + } + p.MsgId, err = p.readString(r) + return +} + +func (p *Message) readMsgIdPlural(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgIdPlural.MatchString(s) { + return + } + p.MsgIdPlural, err = p.readString(r) + return nil +} + +func (p *Message) readMsgStrOrPlural(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgStr.MatchString(s) && !reMsgStrPlural.MatchString(s) { + return + } + if reMsgStrPlural.MatchString(s) { + left, right := strings.Index(s, `[`), strings.LastIndex(s, `]`) + idx, _ := strconv.Atoi(s[left+1 : right]) + s, err = p.readString(r) + if n := len(p.MsgStrPlural); (idx + 1) > n { + p.MsgStrPlural = append(p.MsgStrPlural, make([]string, (idx+1)-n)...) + } + p.MsgStrPlural[idx] = s + } else { + p.MsgStr, err = p.readString(r) + } + return nil +} + +func (p *Message) readString(r *lineReader) (msg string, err error) { + var s string + if s, _, err = r.readLine(); err != nil { + return + } + msg += decodePoString(s) + for { + if s, _, err = r.readLine(); err != nil { + return + } + if !reStringLine.MatchString(s) { + r.unreadLine() + break + } + msg += decodePoString(s) + } + return +} + +// String returns the po format entry string. +func (p Message) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%s", p.Comment.String()) + fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) + if p.MsgIdPlural != "" { + fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) + } + if p.MsgStr != "" { + fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) + } + for i := 0; i < len(p.MsgStrPlural); i++ { + fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/re.go b/vendor/github.com/chai2010/gettext-go/gettext/po/re.go new file mode 100644 index 000000000..67c240a57 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/re.go @@ -0,0 +1,58 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "regexp" +) + +var ( + reComment = regexp.MustCompile(`^#`) // # + reExtractedComments = regexp.MustCompile(`^#\.`) // #. + reReferenceComments = regexp.MustCompile(`^#:`) // #: + reFlagsComments = regexp.MustCompile(`^#,`) // #, fuzzy,c-format + rePrevMsgContextComments = regexp.MustCompile(`^#\|\s+msgctxt`) // #| msgctxt + rePrevMsgIdComments = regexp.MustCompile(`^#\|\s+msgid`) // #| msgid + reStringLineComments = regexp.MustCompile(`^#\|\s+".*"\s*$`) // #| "message" + + reMsgContext = regexp.MustCompile(`^msgctxt\s+".*"\s*$`) // msgctxt + reMsgId = regexp.MustCompile(`^msgid\s+".*"\s*$`) // msgid + reMsgIdPlural = regexp.MustCompile(`^msgid_plural\s+".*"\s*$`) // msgid_plural + reMsgStr = regexp.MustCompile(`^msgstr\s*".*"\s*$`) // msgstr + reMsgStrPlural = regexp.MustCompile(`^msgstr\s*(\[\d+\])\s*".*"\s*$`) // msgstr[0] + reStringLine = regexp.MustCompile(`^\s*".*"\s*$`) // "message" + reBlankLine = regexp.MustCompile(`^\s*$`) // +) + +func (p *Message) isInvalidLine(s string) bool { + if reComment.MatchString(s) { + return false + } + if reBlankLine.MatchString(s) { + return false + } + + if reMsgContext.MatchString(s) { + return false + } + if reMsgId.MatchString(s) { + return false + } + if reMsgIdPlural.MatchString(s) { + return false + } + if reMsgStr.MatchString(s) { + return false + } + if reMsgStrPlural.MatchString(s) { + return false + } + + if reStringLine.MatchString(s) { + return false + } + + return true +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/util.go b/vendor/github.com/chai2010/gettext-go/gettext/po/util.go new file mode 100644 index 000000000..52544832c --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/po/util.go @@ -0,0 +1,110 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "strings" +) + +func decodePoString(text string) string { + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + left := strings.Index(lines[i], `"`) + right := strings.LastIndex(lines[i], `"`) + if left < 0 || right < 0 || left == right { + lines[i] = "" + continue + } + line := lines[i][left+1 : right] + data := make([]byte, 0, len(line)) + for i := 0; i < len(line); i++ { + if line[i] != '\\' { + data = append(data, line[i]) + continue + } + if i+1 >= len(line) { + break + } + switch line[i+1] { + case 'n': // \\n -> \n + data = append(data, '\n') + i++ + case 't': // \\t -> \n + data = append(data, '\t') + i++ + case '\\': // \\\ -> ? + data = append(data, '\\') + i++ + } + } + lines[i] = string(data) + } + return strings.Join(lines, "") +} + +func encodePoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + if lines[i] == "" { + if i != len(lines)-1 { + buf.WriteString(`"\n"` + "\n") + } + continue + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + buf.WriteString(`\n"` + "\n") + } + return buf.String() +} + +func encodeCommentPoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + if len(lines) > 1 { + buf.WriteString(`""` + "\n") + } + for i := 0; i < len(lines); i++ { + if len(lines) > 0 { + buf.WriteString("#| ") + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + if i < len(lines)-1 { + buf.WriteString(`\n"` + "\n") + } else { + buf.WriteString(`"`) + } + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/tr.go b/vendor/github.com/chai2010/gettext-go/gettext/tr.go new file mode 100644 index 000000000..fedfbc301 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext/tr.go @@ -0,0 +1,128 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "github.com/chai2010/gettext-go/gettext/mo" + "github.com/chai2010/gettext-go/gettext/plural" + "github.com/chai2010/gettext-go/gettext/po" +) + +var nilTranslator = &translator{ + MessageMap: make(map[string]mo.Message), + PluralFormula: plural.Formula("??"), +} + +type translator struct { + MessageMap map[string]mo.Message + PluralFormula func(n int) int +} + +func newMoTranslator(name string, data []byte) (*translator, error) { + var ( + f *mo.File + err error + ) + if len(data) != 0 { + f, err = mo.LoadData(data) + } else { + f, err = mo.Load(name) + } + if err != nil { + return nil, err + } + var tr = &translator{ + MessageMap: make(map[string]mo.Message), + } + for _, v := range f.Messages { + tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = v + } + if lang := f.MimeHeader.Language; lang != "" { + tr.PluralFormula = plural.Formula(lang) + } else { + tr.PluralFormula = plural.Formula("??") + } + return tr, nil +} + +func newPoTranslator(name string, data []byte) (*translator, error) { + var ( + f *po.File + err error + ) + if len(data) != 0 { + f, err = po.LoadData(data) + } else { + f, err = po.Load(name) + } + if err != nil { + return nil, err + } + var tr = &translator{ + MessageMap: make(map[string]mo.Message), + } + for _, v := range f.Messages { + tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{ + MsgContext: v.MsgContext, + MsgId: v.MsgId, + MsgIdPlural: v.MsgIdPlural, + MsgStr: v.MsgStr, + MsgStrPlural: v.MsgStrPlural, + } + } + if lang := f.MimeHeader.Language; lang != "" { + tr.PluralFormula = plural.Formula(lang) + } else { + tr.PluralFormula = plural.Formula("??") + } + return tr, nil +} + +func (p *translator) PGettext(msgctxt, msgid string) string { + return p.PNGettext(msgctxt, msgid, "", 0) +} + +func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + n = p.PluralFormula(n) + if ss := p.findMsgStrPlural(msgctxt, msgid, msgidPlural); len(ss) != 0 { + if n >= len(ss) { + n = len(ss) - 1 + } + if ss[n] != "" { + return ss[n] + } + } + if msgidPlural != "" && n > 0 { + return msgidPlural + } + return msgid +} + +func (p *translator) findMsgStrPlural(msgctxt, msgid, msgidPlural string) []string { + key := p.makeMapKey(msgctxt, msgid) + if v, ok := p.MessageMap[key]; ok { + if len(v.MsgIdPlural) != 0 { + if len(v.MsgStrPlural) != 0 { + return v.MsgStrPlural + } else { + return nil + } + } else { + if len(v.MsgStr) != 0 { + return []string{v.MsgStr} + } else { + return nil + } + } + } + return nil +} + +func (p *translator) makeMapKey(msgctxt, msgid string) string { + if msgctxt != "" { + return msgctxt + mo.EotSeparator + msgid + } + return msgid +} diff --git a/vendor/github.com/exponent-io/jsonpath/.gitignore b/vendor/github.com/exponent-io/jsonpath/.gitignore new file mode 100644 index 000000000..daf913b1b --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/exponent-io/jsonpath/.travis.yml b/vendor/github.com/exponent-io/jsonpath/.travis.yml new file mode 100644 index 000000000..f4f458a41 --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/.travis.yml @@ -0,0 +1,5 @@ +language: go + +go: + - 1.5 + - tip diff --git a/vendor/github.com/exponent-io/jsonpath/LICENSE b/vendor/github.com/exponent-io/jsonpath/LICENSE new file mode 100644 index 000000000..541977250 --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Exponent Labs LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/exponent-io/jsonpath/README.md b/vendor/github.com/exponent-io/jsonpath/README.md new file mode 100644 index 000000000..382fb3138 --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/README.md @@ -0,0 +1,66 @@ +[![GoDoc](https://godoc.org/github.com/exponent-io/jsonpath?status.svg)](https://godoc.org/github.com/exponent-io/jsonpath) +[![Build Status](https://travis-ci.org/exponent-io/jsonpath.svg?branch=master)](https://travis-ci.org/exponent-io/jsonpath) + +# jsonpath + +This package extends the [json.Decoder](https://golang.org/pkg/encoding/json/#Decoder) to support navigating a stream of JSON tokens. You should be able to use this extended Decoder places where a json.Decoder would have been used. + +This Decoder has the following enhancements... + * The [Scan](https://godoc.org/github.com/exponent-io/jsonpath/#Decoder.Scan) method supports scanning a JSON stream while extracting particular values along the way using [PathActions](https://godoc.org/github.com/exponent-io/jsonpath#PathActions). + * The [SeekTo](https://godoc.org/github.com/exponent-io/jsonpath#Decoder.SeekTo) method supports seeking forward in a JSON token stream to a particular path. + * The [Path](https://godoc.org/github.com/exponent-io/jsonpath#Decoder.Path) method returns the path of the most recently parsed token. + * The [Token](https://godoc.org/github.com/exponent-io/jsonpath#Decoder.Token) method has been modified to distinguish between strings that are object keys and strings that are values. Object key strings are returned as the [KeyString](https://godoc.org/github.com/exponent-io/jsonpath#KeyString) type rather than a native string. + +## Installation + + go get -u github.com/exponent-io/jsonpath + +## Example Usage + +#### SeekTo + +```go +import "github.com/exponent-io/jsonpath" + +var j = []byte(`[ + {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}}, + {"Space": "RGB", "Point": {"R": 98, "G": 218, "B": 255}} +]`) + +w := json.NewDecoder(bytes.NewReader(j)) +var v interface{} + +w.SeekTo(1, "Point", "G") +w.Decode(&v) // v is 218 +``` + +#### Scan with PathActions + +```go +var j = []byte(`{"colors":[ + {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10, "A": 58}}, + {"Space": "RGB", "Point": {"R": 98, "G": 218, "B": 255, "A": 231}} +]}`) + +var actions PathActions + +// Extract the value at Point.A +actions.Add(func(d *Decoder) error { + var alpha int + err := d.Decode(&alpha) + fmt.Printf("Alpha: %v\n", alpha) + return err +}, "Point", "A") + +w := NewDecoder(bytes.NewReader(j)) +w.SeekTo("colors", 0) + +var ok = true +var err error +for ok { + ok, err = w.Scan(&actions) + if err != nil && err != io.EOF { + panic(err) + } +} +``` diff --git a/vendor/github.com/exponent-io/jsonpath/decoder.go b/vendor/github.com/exponent-io/jsonpath/decoder.go new file mode 100644 index 000000000..31de46c73 --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/decoder.go @@ -0,0 +1,210 @@ +package jsonpath + +import ( + "encoding/json" + "io" +) + +// KeyString is returned from Decoder.Token to represent each key in a JSON object value. +type KeyString string + +// Decoder extends the Go runtime's encoding/json.Decoder to support navigating in a stream of JSON tokens. +type Decoder struct { + json.Decoder + + path JsonPath + context jsonContext +} + +// NewDecoder creates a new instance of the extended JSON Decoder. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{Decoder: *json.NewDecoder(r)} +} + +// SeekTo causes the Decoder to move forward to a given path in the JSON structure. +// +// The path argument must consist of strings or integers. Each string specifies an JSON object key, and +// each integer specifies an index into a JSON array. +// +// Consider the JSON structure +// +// { "a": [0,"s",12e4,{"b":0,"v":35} ] } +// +// SeekTo("a",3,"v") will move to the value referenced by the "a" key in the current object, +// followed by a move to the 4th value (index 3) in the array, followed by a move to the value at key "v". +// In this example, a subsequent call to the decoder's Decode() would unmarshal the value 35. +// +// SeekTo returns a boolean value indicating whether a match was found. +// +// Decoder is intended to be used with a stream of tokens. As a result it navigates forward only. +func (d *Decoder) SeekTo(path ...interface{}) (bool, error) { + + if len(path) == 0 { + return len(d.path) == 0, nil + } + last := len(path) - 1 + if i, ok := path[last].(int); ok { + path[last] = i - 1 + } + + for { + if d.path.Equal(path) { + return true, nil + } + _, err := d.Token() + if err == io.EOF { + return false, nil + } else if err != nil { + return false, err + } + } +} + +// Decode reads the next JSON-encoded value from its input and stores it in the value pointed to by v. This is +// equivalent to encoding/json.Decode(). +func (d *Decoder) Decode(v interface{}) error { + switch d.context { + case objValue: + d.context = objKey + break + case arrValue: + d.path.incTop() + break + } + return d.Decoder.Decode(v) +} + +// Path returns a slice of string and/or int values representing the path from the root of the JSON object to the +// position of the most-recently parsed token. +func (d *Decoder) Path() JsonPath { + p := make(JsonPath, len(d.path)) + copy(p, d.path) + return p +} + +// Token is equivalent to the Token() method on json.Decoder. The primary difference is that it distinguishes +// between strings that are keys and and strings that are values. String tokens that are object keys are returned as a +// KeyString rather than as a native string. +func (d *Decoder) Token() (json.Token, error) { + t, err := d.Decoder.Token() + if err != nil { + return t, err + } + + if t == nil { + switch d.context { + case objValue: + d.context = objKey + break + case arrValue: + d.path.incTop() + break + } + return t, err + } + + switch t := t.(type) { + case json.Delim: + switch t { + case json.Delim('{'): + if d.context == arrValue { + d.path.incTop() + } + d.path.push("") + d.context = objKey + break + case json.Delim('}'): + d.path.pop() + d.context = d.path.inferContext() + break + case json.Delim('['): + if d.context == arrValue { + d.path.incTop() + } + d.path.push(-1) + d.context = arrValue + break + case json.Delim(']'): + d.path.pop() + d.context = d.path.inferContext() + break + } + case float64, json.Number, bool: + switch d.context { + case objValue: + d.context = objKey + break + case arrValue: + d.path.incTop() + break + } + break + case string: + switch d.context { + case objKey: + d.path.nameTop(t) + d.context = objValue + return KeyString(t), err + case objValue: + d.context = objKey + case arrValue: + d.path.incTop() + } + break + } + + return t, err +} + +// Scan moves forward over the JSON stream consuming all the tokens at the current level (current object, current array) +// invoking each matching PathAction along the way. +// +// Scan returns true if there are more contiguous values to scan (for example in an array). +func (d *Decoder) Scan(ext *PathActions) (bool, error) { + + rootPath := d.Path() + + // If this is an array path, increment the root path in our local copy. + if rootPath.inferContext() == arrValue { + rootPath.incTop() + } + + for { + // advance the token position + _, err := d.Token() + if err != nil { + return false, err + } + + match: + var relPath JsonPath + + // capture the new JSON path + path := d.Path() + + if len(path) > len(rootPath) { + // capture the path relative to where the scan started + relPath = path[len(rootPath):] + } else { + // if the path is not longer than the root, then we are done with this scan + // return boolean flag indicating if there are more items to scan at the same level + return d.Decoder.More(), nil + } + + // match the relative path against the path actions + if node := ext.node.match(relPath); node != nil { + if node.action != nil { + // we have a match so execute the action + err = node.action(d) + if err != nil { + return d.Decoder.More(), err + } + // The action may have advanced the decoder. If we are in an array, advancing it further would + // skip tokens. So, if we are scanning an array, jump to the top without advancing the token. + if d.path.inferContext() == arrValue && d.Decoder.More() { + goto match + } + } + } + } +} diff --git a/vendor/github.com/exponent-io/jsonpath/path.go b/vendor/github.com/exponent-io/jsonpath/path.go new file mode 100644 index 000000000..d7db2ad33 --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/path.go @@ -0,0 +1,67 @@ +// Extends the Go runtime's json.Decoder enabling navigation of a stream of json tokens. +package jsonpath + +import "fmt" + +type jsonContext int + +const ( + none jsonContext = iota + objKey + objValue + arrValue +) + +// AnyIndex can be used in a pattern to match any array index. +const AnyIndex = -2 + +// JsonPath is a slice of strings and/or integers. Each string specifies an JSON object key, and +// each integer specifies an index into a JSON array. +type JsonPath []interface{} + +func (p *JsonPath) push(n interface{}) { *p = append(*p, n) } +func (p *JsonPath) pop() { *p = (*p)[:len(*p)-1] } + +// increment the index at the top of the stack (must be an array index) +func (p *JsonPath) incTop() { (*p)[len(*p)-1] = (*p)[len(*p)-1].(int) + 1 } + +// name the key at the top of the stack (must be an object key) +func (p *JsonPath) nameTop(n string) { (*p)[len(*p)-1] = n } + +// infer the context from the item at the top of the stack +func (p *JsonPath) inferContext() jsonContext { + if len(*p) == 0 { + return none + } + t := (*p)[len(*p)-1] + switch t.(type) { + case string: + return objKey + case int: + return arrValue + default: + panic(fmt.Sprintf("Invalid stack type %T", t)) + } +} + +// Equal tests for equality between two JsonPath types. +func (p *JsonPath) Equal(o JsonPath) bool { + if len(*p) != len(o) { + return false + } + for i, v := range *p { + if v != o[i] { + return false + } + } + return true +} + +func (p *JsonPath) HasPrefix(o JsonPath) bool { + for i, v := range o { + if v != (*p)[i] { + return false + } + } + return true +} diff --git a/vendor/github.com/exponent-io/jsonpath/pathaction.go b/vendor/github.com/exponent-io/jsonpath/pathaction.go new file mode 100644 index 000000000..497ed686c --- /dev/null +++ b/vendor/github.com/exponent-io/jsonpath/pathaction.go @@ -0,0 +1,61 @@ +package jsonpath + +// pathNode is used to construct a trie of paths to be matched +type pathNode struct { + matchOn interface{} // string, or integer + childNodes []pathNode + action DecodeAction +} + +// match climbs the trie to find a node that matches the given JSON path. +func (n *pathNode) match(path JsonPath) *pathNode { + var node *pathNode = n + for _, ps := range path { + found := false + for i, n := range node.childNodes { + if n.matchOn == ps { + node = &node.childNodes[i] + found = true + break + } else if _, ok := ps.(int); ok && n.matchOn == AnyIndex { + node = &node.childNodes[i] + found = true + break + } + } + if !found { + return nil + } + } + return node +} + +// PathActions represents a collection of DecodeAction functions that should be called at certain path positions +// when scanning the JSON stream. PathActions can be created once and used many times in one or more JSON streams. +type PathActions struct { + node pathNode +} + +// DecodeAction handlers are called by the Decoder when scanning objects. See PathActions.Add for more detail. +type DecodeAction func(d *Decoder) error + +// Add specifies an action to call on the Decoder when the specified path is encountered. +func (je *PathActions) Add(action DecodeAction, path ...interface{}) { + + var node *pathNode = &je.node + for _, ps := range path { + found := false + for i, n := range node.childNodes { + if n.matchOn == ps { + node = &node.childNodes[i] + found = true + break + } + } + if !found { + node.childNodes = append(node.childNodes, pathNode{matchOn: ps}) + node = &node.childNodes[len(node.childNodes)-1] + } + } + node.action = action +} diff --git a/vendor/github.com/google/btree/.travis.yml b/vendor/github.com/google/btree/.travis.yml new file mode 100644 index 000000000..4f2ee4d97 --- /dev/null +++ b/vendor/github.com/google/btree/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/google/btree/LICENSE b/vendor/github.com/google/btree/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/google/btree/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/google/btree/README.md b/vendor/github.com/google/btree/README.md new file mode 100644 index 000000000..6062a4dac --- /dev/null +++ b/vendor/github.com/google/btree/README.md @@ -0,0 +1,12 @@ +# BTree implementation for Go + +![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) + +This package provides an in-memory B-Tree implementation for Go, useful as +an ordered, mutable data structure. + +The API is based off of the wonderful +http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to +act as a drop-in replacement for gollrb trees. + +See http://godoc.org/github.com/google/btree for documentation. diff --git a/vendor/github.com/google/btree/btree.go b/vendor/github.com/google/btree/btree.go new file mode 100644 index 000000000..6ff062f9b --- /dev/null +++ b/vendor/github.com/google/btree/btree.go @@ -0,0 +1,890 @@ +// Copyright 2014 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package btree implements in-memory B-Trees of arbitrary degree. +// +// btree implements an in-memory B-Tree for use as an ordered data structure. +// It is not meant for persistent storage solutions. +// +// It has a flatter structure than an equivalent red-black or other binary tree, +// which in some cases yields better memory usage and/or performance. +// See some discussion on the matter here: +// http://google-opensource.blogspot.com/2013/01/c-containers-that-save-memory-and-time.html +// Note, though, that this project is in no way related to the C++ B-Tree +// implementation written about there. +// +// Within this tree, each node contains a slice of items and a (possibly nil) +// slice of children. For basic numeric values or raw structs, this can cause +// efficiency differences when compared to equivalent C++ template code that +// stores values in arrays within the node: +// * Due to the overhead of storing values as interfaces (each +// value needs to be stored as the value itself, then 2 words for the +// interface pointing to that value and its type), resulting in higher +// memory use. +// * Since interfaces can point to values anywhere in memory, values are +// most likely not stored in contiguous blocks, resulting in a higher +// number of cache misses. +// These issues don't tend to matter, though, when working with strings or other +// heap-allocated structures, since C++-equivalent structures also must store +// pointers and also distribute their values across the heap. +// +// This implementation is designed to be a drop-in replacement to gollrb.LLRB +// trees, (http://github.com/petar/gollrb), an excellent and probably the most +// widely used ordered tree implementation in the Go ecosystem currently. +// Its functions, therefore, exactly mirror those of +// llrb.LLRB where possible. Unlike gollrb, though, we currently don't +// support storing multiple equivalent values. +package btree + +import ( + "fmt" + "io" + "sort" + "strings" + "sync" +) + +// Item represents a single object in the tree. +type Item interface { + // Less tests whether the current item is less than the given argument. + // + // This must provide a strict weak ordering. + // If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only + // hold one of either a or b in the tree). + Less(than Item) bool +} + +const ( + DefaultFreeListSize = 32 +) + +var ( + nilItems = make(items, 16) + nilChildren = make(children, 16) +) + +// FreeList represents a free list of btree nodes. By default each +// BTree has its own FreeList, but multiple BTrees can share the same +// FreeList. +// Two Btrees using the same freelist are safe for concurrent write access. +type FreeList struct { + mu sync.Mutex + freelist []*node +} + +// NewFreeList creates a new free list. +// size is the maximum size of the returned free list. +func NewFreeList(size int) *FreeList { + return &FreeList{freelist: make([]*node, 0, size)} +} + +func (f *FreeList) newNode() (n *node) { + f.mu.Lock() + index := len(f.freelist) - 1 + if index < 0 { + f.mu.Unlock() + return new(node) + } + n = f.freelist[index] + f.freelist[index] = nil + f.freelist = f.freelist[:index] + f.mu.Unlock() + return +} + +// freeNode adds the given node to the list, returning true if it was added +// and false if it was discarded. +func (f *FreeList) freeNode(n *node) (out bool) { + f.mu.Lock() + if len(f.freelist) < cap(f.freelist) { + f.freelist = append(f.freelist, n) + out = true + } + f.mu.Unlock() + return +} + +// ItemIterator allows callers of Ascend* to iterate in-order over portions of +// the tree. When this function returns false, iteration will stop and the +// associated Ascend* function will immediately return. +type ItemIterator func(i Item) bool + +// New creates a new B-Tree with the given degree. +// +// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items +// and 2-4 children). +func New(degree int) *BTree { + return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize)) +} + +// NewWithFreeList creates a new B-Tree that uses the given node free list. +func NewWithFreeList(degree int, f *FreeList) *BTree { + if degree <= 1 { + panic("bad degree") + } + return &BTree{ + degree: degree, + cow: ©OnWriteContext{freelist: f}, + } +} + +// items stores items in a node. +type items []Item + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *items) insertAt(index int, item Item) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = item +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *items) removeAt(index int) Item { + item := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return item +} + +// pop removes and returns the last element in the list. +func (s *items) pop() (out Item) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index items. index must be less than or equal to length. +func (s *items) truncate(index int) { + var toClear items + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilItems):] + } +} + +// find returns the index where the given item should be inserted into this +// list. 'found' is true if the item already exists in the list at the given +// index. +func (s items) find(item Item) (index int, found bool) { + i := sort.Search(len(s), func(i int) bool { + return item.Less(s[i]) + }) + if i > 0 && !s[i-1].Less(item) { + return i - 1, true + } + return i, false +} + +// children stores child nodes in a node. +type children []*node + +// insertAt inserts a value into the given index, pushing all subsequent values +// forward. +func (s *children) insertAt(index int, n *node) { + *s = append(*s, nil) + if index < len(*s) { + copy((*s)[index+1:], (*s)[index:]) + } + (*s)[index] = n +} + +// removeAt removes a value at a given index, pulling all subsequent values +// back. +func (s *children) removeAt(index int) *node { + n := (*s)[index] + copy((*s)[index:], (*s)[index+1:]) + (*s)[len(*s)-1] = nil + *s = (*s)[:len(*s)-1] + return n +} + +// pop removes and returns the last element in the list. +func (s *children) pop() (out *node) { + index := len(*s) - 1 + out = (*s)[index] + (*s)[index] = nil + *s = (*s)[:index] + return +} + +// truncate truncates this instance at index so that it contains only the +// first index children. index must be less than or equal to length. +func (s *children) truncate(index int) { + var toClear children + *s, toClear = (*s)[:index], (*s)[index:] + for len(toClear) > 0 { + toClear = toClear[copy(toClear, nilChildren):] + } +} + +// node is an internal node in a tree. +// +// It must at all times maintain the invariant that either +// * len(children) == 0, len(items) unconstrained +// * len(children) == len(items) + 1 +type node struct { + items items + children children + cow *copyOnWriteContext +} + +func (n *node) mutableFor(cow *copyOnWriteContext) *node { + if n.cow == cow { + return n + } + out := cow.newNode() + if cap(out.items) >= len(n.items) { + out.items = out.items[:len(n.items)] + } else { + out.items = make(items, len(n.items), cap(n.items)) + } + copy(out.items, n.items) + // Copy children + if cap(out.children) >= len(n.children) { + out.children = out.children[:len(n.children)] + } else { + out.children = make(children, len(n.children), cap(n.children)) + } + copy(out.children, n.children) + return out +} + +func (n *node) mutableChild(i int) *node { + c := n.children[i].mutableFor(n.cow) + n.children[i] = c + return c +} + +// split splits the given node at the given index. The current node shrinks, +// and this function returns the item that existed at that index and a new node +// containing all items/children after it. +func (n *node) split(i int) (Item, *node) { + item := n.items[i] + next := n.cow.newNode() + next.items = append(next.items, n.items[i+1:]...) + n.items.truncate(i) + if len(n.children) > 0 { + next.children = append(next.children, n.children[i+1:]...) + n.children.truncate(i + 1) + } + return item, next +} + +// maybeSplitChild checks if a child should be split, and if so splits it. +// Returns whether or not a split occurred. +func (n *node) maybeSplitChild(i, maxItems int) bool { + if len(n.children[i].items) < maxItems { + return false + } + first := n.mutableChild(i) + item, second := first.split(maxItems / 2) + n.items.insertAt(i, item) + n.children.insertAt(i+1, second) + return true +} + +// insert inserts an item into the subtree rooted at this node, making sure +// no nodes in the subtree exceed maxItems items. Should an equivalent item be +// be found/replaced by insert, it will be returned. +func (n *node) insert(item Item, maxItems int) Item { + i, found := n.items.find(item) + if found { + out := n.items[i] + n.items[i] = item + return out + } + if len(n.children) == 0 { + n.items.insertAt(i, item) + return nil + } + if n.maybeSplitChild(i, maxItems) { + inTree := n.items[i] + switch { + case item.Less(inTree): + // no change, we want first split node + case inTree.Less(item): + i++ // we want second split node + default: + out := n.items[i] + n.items[i] = item + return out + } + } + return n.mutableChild(i).insert(item, maxItems) +} + +// get finds the given key in the subtree and returns it. +func (n *node) get(key Item) Item { + i, found := n.items.find(key) + if found { + return n.items[i] + } else if len(n.children) > 0 { + return n.children[i].get(key) + } + return nil +} + +// min returns the first item in the subtree. +func min(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[0] + } + if len(n.items) == 0 { + return nil + } + return n.items[0] +} + +// max returns the last item in the subtree. +func max(n *node) Item { + if n == nil { + return nil + } + for len(n.children) > 0 { + n = n.children[len(n.children)-1] + } + if len(n.items) == 0 { + return nil + } + return n.items[len(n.items)-1] +} + +// toRemove details what item to remove in a node.remove call. +type toRemove int + +const ( + removeItem toRemove = iota // removes the given item + removeMin // removes smallest item in the subtree + removeMax // removes largest item in the subtree +) + +// remove removes an item from the subtree rooted at this node. +func (n *node) remove(item Item, minItems int, typ toRemove) Item { + var i int + var found bool + switch typ { + case removeMax: + if len(n.children) == 0 { + return n.items.pop() + } + i = len(n.items) + case removeMin: + if len(n.children) == 0 { + return n.items.removeAt(0) + } + i = 0 + case removeItem: + i, found = n.items.find(item) + if len(n.children) == 0 { + if found { + return n.items.removeAt(i) + } + return nil + } + default: + panic("invalid type") + } + // If we get to here, we have children. + if len(n.children[i].items) <= minItems { + return n.growChildAndRemove(i, item, minItems, typ) + } + child := n.mutableChild(i) + // Either we had enough items to begin with, or we've done some + // merging/stealing, because we've got enough now and we're ready to return + // stuff. + if found { + // The item exists at index 'i', and the child we've selected can give us a + // predecessor, since if we've gotten here it's got > minItems items in it. + out := n.items[i] + // We use our special-case 'remove' call with typ=maxItem to pull the + // predecessor of item i (the rightmost leaf of our immediate left child) + // and set it into where we pulled the item from. + n.items[i] = child.remove(nil, minItems, removeMax) + return out + } + // Final recursive call. Once we're here, we know that the item isn't in this + // node and that the child is big enough to remove from. + return child.remove(item, minItems, typ) +} + +// growChildAndRemove grows child 'i' to make sure it's possible to remove an +// item from it while keeping it at minItems, then calls remove to actually +// remove it. +// +// Most documentation says we have to do two sets of special casing: +// 1) item is in this node +// 2) item is in child +// In both cases, we need to handle the two subcases: +// A) node has enough values that it can spare one +// B) node doesn't have enough values +// For the latter, we have to check: +// a) left sibling has node to spare +// b) right sibling has node to spare +// c) we must merge +// To simplify our code here, we handle cases #1 and #2 the same: +// If a node doesn't have enough items, we make sure it does (using a,b,c). +// We then simply redo our remove call, and the second time (regardless of +// whether we're in case 1 or 2), we'll have enough items and can guarantee +// that we hit case A. +func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item { + if i > 0 && len(n.children[i-1].items) > minItems { + // Steal from left child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i - 1) + stolenItem := stealFrom.items.pop() + child.items.insertAt(0, n.items[i-1]) + n.items[i-1] = stolenItem + if len(stealFrom.children) > 0 { + child.children.insertAt(0, stealFrom.children.pop()) + } + } else if i < len(n.items) && len(n.children[i+1].items) > minItems { + // steal from right child + child := n.mutableChild(i) + stealFrom := n.mutableChild(i + 1) + stolenItem := stealFrom.items.removeAt(0) + child.items = append(child.items, n.items[i]) + n.items[i] = stolenItem + if len(stealFrom.children) > 0 { + child.children = append(child.children, stealFrom.children.removeAt(0)) + } + } else { + if i >= len(n.items) { + i-- + } + child := n.mutableChild(i) + // merge with right child + mergeItem := n.items.removeAt(i) + mergeChild := n.children.removeAt(i + 1) + child.items = append(child.items, mergeItem) + child.items = append(child.items, mergeChild.items...) + child.children = append(child.children, mergeChild.children...) + n.cow.freeNode(mergeChild) + } + return n.remove(item, minItems, typ) +} + +type direction int + +const ( + descend = direction(-1) + ascend = direction(+1) +) + +// iterate provides a simple method for iterating over elements in the tree. +// +// When ascending, the 'start' should be less than 'stop' and when descending, +// the 'start' should be greater than 'stop'. Setting 'includeStart' to true +// will force the iterator to include the first item when it equals 'start', +// thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a +// "greaterThan" or "lessThan" queries. +func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator) (bool, bool) { + var ok, found bool + var index int + switch dir { + case ascend: + if start != nil { + index, _ = n.items.find(start) + } + for i := index; i < len(n.items); i++ { + if len(n.children) > 0 { + if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if !includeStart && !hit && start != nil && !start.Less(n.items[i]) { + hit = true + continue + } + hit = true + if stop != nil && !n.items[i].Less(stop) { + return hit, false + } + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + case descend: + if start != nil { + index, found = n.items.find(start) + if !found { + index = index - 1 + } + } else { + index = len(n.items) - 1 + } + for i := index; i >= 0; i-- { + if start != nil && !n.items[i].Less(start) { + if !includeStart || hit || start.Less(n.items[i]) { + continue + } + } + if len(n.children) > 0 { + if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + if stop != nil && !stop.Less(n.items[i]) { + return hit, false // continue + } + hit = true + if !iter(n.items[i]) { + return hit, false + } + } + if len(n.children) > 0 { + if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok { + return hit, false + } + } + } + return hit, true +} + +// Used for testing/debugging purposes. +func (n *node) print(w io.Writer, level int) { + fmt.Fprintf(w, "%sNODE:%v\n", strings.Repeat(" ", level), n.items) + for _, c := range n.children { + c.print(w, level+1) + } +} + +// BTree is an implementation of a B-Tree. +// +// BTree stores Item instances in an ordered structure, allowing easy insertion, +// removal, and iteration. +// +// Write operations are not safe for concurrent mutation by multiple +// goroutines, but Read operations are. +type BTree struct { + degree int + length int + root *node + cow *copyOnWriteContext +} + +// copyOnWriteContext pointers determine node ownership... a tree with a write +// context equivalent to a node's write context is allowed to modify that node. +// A tree whose write context does not match a node's is not allowed to modify +// it, and must create a new, writable copy (IE: it's a Clone). +// +// When doing any write operation, we maintain the invariant that the current +// node's context is equal to the context of the tree that requested the write. +// We do this by, before we descend into any node, creating a copy with the +// correct context if the contexts don't match. +// +// Since the node we're currently visiting on any write has the requesting +// tree's context, that node is modifiable in place. Children of that node may +// not share context, but before we descend into them, we'll make a mutable +// copy. +type copyOnWriteContext struct { + freelist *FreeList +} + +// Clone clones the btree, lazily. Clone should not be called concurrently, +// but the original tree (t) and the new tree (t2) can be used concurrently +// once the Clone call completes. +// +// The internal tree structure of b is marked read-only and shared between t and +// t2. Writes to both t and t2 use copy-on-write logic, creating new nodes +// whenever one of b's original nodes would have been modified. Read operations +// should have no performance degredation. Write operations for both t and t2 +// will initially experience minor slow-downs caused by additional allocs and +// copies due to the aforementioned copy-on-write logic, but should converge to +// the original performance characteristics of the original tree. +func (t *BTree) Clone() (t2 *BTree) { + // Create two entirely new copy-on-write contexts. + // This operation effectively creates three trees: + // the original, shared nodes (old b.cow) + // the new b.cow nodes + // the new out.cow nodes + cow1, cow2 := *t.cow, *t.cow + out := *t + t.cow = &cow1 + out.cow = &cow2 + return &out +} + +// maxItems returns the max number of items to allow per node. +func (t *BTree) maxItems() int { + return t.degree*2 - 1 +} + +// minItems returns the min number of items to allow per node (ignored for the +// root node). +func (t *BTree) minItems() int { + return t.degree - 1 +} + +func (c *copyOnWriteContext) newNode() (n *node) { + n = c.freelist.newNode() + n.cow = c + return +} + +type freeType int + +const ( + ftFreelistFull freeType = iota // node was freed (available for GC, not stored in freelist) + ftStored // node was stored in the freelist for later use + ftNotOwned // node was ignored by COW, since it's owned by another one +) + +// freeNode frees a node within a given COW context, if it's owned by that +// context. It returns what happened to the node (see freeType const +// documentation). +func (c *copyOnWriteContext) freeNode(n *node) freeType { + if n.cow == c { + // clear to allow GC + n.items.truncate(0) + n.children.truncate(0) + n.cow = nil + if c.freelist.freeNode(n) { + return ftStored + } else { + return ftFreelistFull + } + } else { + return ftNotOwned + } +} + +// ReplaceOrInsert adds the given item to the tree. If an item in the tree +// already equals the given one, it is removed from the tree and returned. +// Otherwise, nil is returned. +// +// nil cannot be added to the tree (will panic). +func (t *BTree) ReplaceOrInsert(item Item) Item { + if item == nil { + panic("nil item being added to BTree") + } + if t.root == nil { + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item) + t.length++ + return nil + } else { + t.root = t.root.mutableFor(t.cow) + if len(t.root.items) >= t.maxItems() { + item2, second := t.root.split(t.maxItems() / 2) + oldroot := t.root + t.root = t.cow.newNode() + t.root.items = append(t.root.items, item2) + t.root.children = append(t.root.children, oldroot, second) + } + } + out := t.root.insert(item, t.maxItems()) + if out == nil { + t.length++ + } + return out +} + +// Delete removes an item equal to the passed in item from the tree, returning +// it. If no such item exists, returns nil. +func (t *BTree) Delete(item Item) Item { + return t.deleteItem(item, removeItem) +} + +// DeleteMin removes the smallest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMin() Item { + return t.deleteItem(nil, removeMin) +} + +// DeleteMax removes the largest item in the tree and returns it. +// If no such item exists, returns nil. +func (t *BTree) DeleteMax() Item { + return t.deleteItem(nil, removeMax) +} + +func (t *BTree) deleteItem(item Item, typ toRemove) Item { + if t.root == nil || len(t.root.items) == 0 { + return nil + } + t.root = t.root.mutableFor(t.cow) + out := t.root.remove(item, t.minItems(), typ) + if len(t.root.items) == 0 && len(t.root.children) > 0 { + oldroot := t.root + t.root = t.root.children[0] + t.cow.freeNode(oldroot) + } + if out != nil { + t.length-- + } + return out +} + +// AscendRange calls the iterator for every value in the tree within the range +// [greaterOrEqual, lessThan), until iterator returns false. +func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator) +} + +// AscendLessThan calls the iterator for every value in the tree within the range +// [first, pivot), until iterator returns false. +func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, pivot, false, false, iterator) +} + +// AscendGreaterOrEqual calls the iterator for every value in the tree within +// the range [pivot, last], until iterator returns false. +func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, pivot, nil, true, false, iterator) +} + +// Ascend calls the iterator for every value in the tree within the range +// [first, last], until iterator returns false. +func (t *BTree) Ascend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(ascend, nil, nil, false, false, iterator) +} + +// DescendRange calls the iterator for every value in the tree within the range +// [lessOrEqual, greaterThan), until iterator returns false. +func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator) +} + +// DescendLessOrEqual calls the iterator for every value in the tree within the range +// [pivot, first], until iterator returns false. +func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, pivot, nil, true, false, iterator) +} + +// DescendGreaterThan calls the iterator for every value in the tree within +// the range (pivot, last], until iterator returns false. +func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, pivot, false, false, iterator) +} + +// Descend calls the iterator for every value in the tree within the range +// [last, first], until iterator returns false. +func (t *BTree) Descend(iterator ItemIterator) { + if t.root == nil { + return + } + t.root.iterate(descend, nil, nil, false, false, iterator) +} + +// Get looks for the key item in the tree, returning it. It returns nil if +// unable to find that item. +func (t *BTree) Get(key Item) Item { + if t.root == nil { + return nil + } + return t.root.get(key) +} + +// Min returns the smallest item in the tree, or nil if the tree is empty. +func (t *BTree) Min() Item { + return min(t.root) +} + +// Max returns the largest item in the tree, or nil if the tree is empty. +func (t *BTree) Max() Item { + return max(t.root) +} + +// Has returns true if the given key is in the tree. +func (t *BTree) Has(key Item) bool { + return t.Get(key) != nil +} + +// Len returns the number of items currently in the tree. +func (t *BTree) Len() int { + return t.length +} + +// Clear removes all items from the btree. If addNodesToFreelist is true, +// t's nodes are added to its freelist as part of this call, until the freelist +// is full. Otherwise, the root node is simply dereferenced and the subtree +// left to Go's normal GC processes. +// +// This can be much faster +// than calling Delete on all elements, because that requires finding/removing +// each element in the tree and updating the tree accordingly. It also is +// somewhat faster than creating a new tree to replace the old one, because +// nodes from the old tree are reclaimed into the freelist for use by the new +// one, instead of being lost to the garbage collector. +// +// This call takes: +// O(1): when addNodesToFreelist is false, this is a single operation. +// O(1): when the freelist is already full, it breaks out immediately +// O(freelist size): when the freelist is empty and the nodes are all owned +// by this tree, nodes are added to the freelist until full. +// O(tree size): when all nodes are owned by another tree, all nodes are +// iterated over looking for nodes to add to the freelist, and due to +// ownership, none are. +func (t *BTree) Clear(addNodesToFreelist bool) { + if t.root != nil && addNodesToFreelist { + t.root.reset(t.cow) + } + t.root, t.length = nil, 0 +} + +// reset returns a subtree to the freelist. It breaks out immediately if the +// freelist is full, since the only benefit of iterating is to fill that +// freelist up. Returns true if parent reset call should continue. +func (n *node) reset(c *copyOnWriteContext) bool { + for _, child := range n.children { + if !child.reset(c) { + return false + } + } + return c.freeNode(n) != ftFreelistFull +} + +// Int implements the Item interface for integers. +type Int int + +// Less returns true if int(a) < int(b). +func (a Int) Less(b Item) bool { + return a < b.(Int) +} diff --git a/vendor/github.com/gregjones/httpcache/.travis.yml b/vendor/github.com/gregjones/httpcache/.travis.yml new file mode 100644 index 000000000..2bca4c599 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/.travis.yml @@ -0,0 +1,18 @@ +sudo: false +language: go +go: + - 1.6.x + - 1.7.x + - 1.8.x + - master +matrix: + allow_failures: + - go: master + fast_finish: true +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d .) + - go tool vet . + - go test -v -race ./... diff --git a/vendor/github.com/gregjones/httpcache/LICENSE.txt b/vendor/github.com/gregjones/httpcache/LICENSE.txt new file mode 100644 index 000000000..81316beb0 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright © 2012 Greg Jones (greg.jones@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/gregjones/httpcache/README.md b/vendor/github.com/gregjones/httpcache/README.md new file mode 100644 index 000000000..61bd830e5 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/README.md @@ -0,0 +1,24 @@ +httpcache +========= + +[![Build Status](https://travis-ci.org/gregjones/httpcache.svg?branch=master)](https://travis-ci.org/gregjones/httpcache) [![GoDoc](https://godoc.org/github.com/gregjones/httpcache?status.svg)](https://godoc.org/github.com/gregjones/httpcache) + +Package httpcache provides a http.RoundTripper implementation that works as a mostly RFC-compliant cache for http responses. + +It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy). + +Cache Backends +-------------- + +- The built-in 'memory' cache stores responses in an in-memory map. +- [`github.com/gregjones/httpcache/diskcache`](https://github.com/gregjones/httpcache/tree/master/diskcache) provides a filesystem-backed cache using the [diskv](https://github.com/peterbourgon/diskv) library. +- [`github.com/gregjones/httpcache/memcache`](https://github.com/gregjones/httpcache/tree/master/memcache) provides memcache implementations, for both App Engine and 'normal' memcache servers. +- [`sourcegraph.com/sourcegraph/s3cache`](https://sourcegraph.com/github.com/sourcegraph/s3cache) uses Amazon S3 for storage. +- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb). +- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries. +- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache. + +License +------- + +- [MIT License](LICENSE.txt) diff --git a/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go b/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go new file mode 100644 index 000000000..42e3129d8 --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go @@ -0,0 +1,61 @@ +// Package diskcache provides an implementation of httpcache.Cache that uses the diskv package +// to supplement an in-memory map with persistent storage +// +package diskcache + +import ( + "bytes" + "crypto/md5" + "encoding/hex" + "github.com/peterbourgon/diskv" + "io" +) + +// Cache is an implementation of httpcache.Cache that supplements the in-memory map with persistent storage +type Cache struct { + d *diskv.Diskv +} + +// Get returns the response corresponding to key if present +func (c *Cache) Get(key string) (resp []byte, ok bool) { + key = keyToFilename(key) + resp, err := c.d.Read(key) + if err != nil { + return []byte{}, false + } + return resp, true +} + +// Set saves a response to the cache as key +func (c *Cache) Set(key string, resp []byte) { + key = keyToFilename(key) + c.d.WriteStream(key, bytes.NewReader(resp), true) +} + +// Delete removes the response with key from the cache +func (c *Cache) Delete(key string) { + key = keyToFilename(key) + c.d.Erase(key) +} + +func keyToFilename(key string) string { + h := md5.New() + io.WriteString(h, key) + return hex.EncodeToString(h.Sum(nil)) +} + +// New returns a new Cache that will store files in basePath +func New(basePath string) *Cache { + return &Cache{ + d: diskv.New(diskv.Options{ + BasePath: basePath, + CacheSizeMax: 100 * 1024 * 1024, // 100MB + }), + } +} + +// NewWithDiskv returns a new Cache using the provided Diskv as underlying +// storage. +func NewWithDiskv(d *diskv.Diskv) *Cache { + return &Cache{d} +} diff --git a/vendor/github.com/gregjones/httpcache/httpcache.go b/vendor/github.com/gregjones/httpcache/httpcache.go new file mode 100644 index 000000000..8239edc2c --- /dev/null +++ b/vendor/github.com/gregjones/httpcache/httpcache.go @@ -0,0 +1,553 @@ +// Package httpcache provides a http.RoundTripper implementation that works as a +// mostly RFC-compliant cache for http responses. +// +// It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client +// and not for a shared proxy). +// +package httpcache + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/http/httputil" + "strings" + "sync" + "time" +) + +const ( + stale = iota + fresh + transparent + // XFromCache is the header added to responses that are returned from the cache + XFromCache = "X-From-Cache" +) + +// A Cache interface is used by the Transport to store and retrieve responses. +type Cache interface { + // Get returns the []byte representation of a cached response and a bool + // set to true if the value isn't empty + Get(key string) (responseBytes []byte, ok bool) + // Set stores the []byte representation of a response against a key + Set(key string, responseBytes []byte) + // Delete removes the value associated with the key + Delete(key string) +} + +// cacheKey returns the cache key for req. +func cacheKey(req *http.Request) string { + return req.URL.String() +} + +// CachedResponse returns the cached http.Response for req if present, and nil +// otherwise. +func CachedResponse(c Cache, req *http.Request) (resp *http.Response, err error) { + cachedVal, ok := c.Get(cacheKey(req)) + if !ok { + return + } + + b := bytes.NewBuffer(cachedVal) + return http.ReadResponse(bufio.NewReader(b), req) +} + +// MemoryCache is an implemtation of Cache that stores responses in an in-memory map. +type MemoryCache struct { + mu sync.RWMutex + items map[string][]byte +} + +// Get returns the []byte representation of the response and true if present, false if not +func (c *MemoryCache) Get(key string) (resp []byte, ok bool) { + c.mu.RLock() + resp, ok = c.items[key] + c.mu.RUnlock() + return resp, ok +} + +// Set saves response resp to the cache with key +func (c *MemoryCache) Set(key string, resp []byte) { + c.mu.Lock() + c.items[key] = resp + c.mu.Unlock() +} + +// Delete removes key from the cache +func (c *MemoryCache) Delete(key string) { + c.mu.Lock() + delete(c.items, key) + c.mu.Unlock() +} + +// NewMemoryCache returns a new Cache that will store items in an in-memory map +func NewMemoryCache() *MemoryCache { + c := &MemoryCache{items: map[string][]byte{}} + return c +} + +// Transport is an implementation of http.RoundTripper that will return values from a cache +// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since) +// to repeated requests allowing servers to return 304 / Not Modified +type Transport struct { + // The RoundTripper interface actually used to make requests + // If nil, http.DefaultTransport is used + Transport http.RoundTripper + Cache Cache + // If true, responses returned from the cache will be given an extra header, X-From-Cache + MarkCachedResponses bool +} + +// NewTransport returns a new Transport with the +// provided Cache implementation and MarkCachedResponses set to true +func NewTransport(c Cache) *Transport { + return &Transport{Cache: c, MarkCachedResponses: true} +} + +// Client returns an *http.Client that caches responses. +func (t *Transport) Client() *http.Client { + return &http.Client{Transport: t} +} + +// varyMatches will return false unless all of the cached values for the headers listed in Vary +// match the new request +func varyMatches(cachedResp *http.Response, req *http.Request) bool { + for _, header := range headerAllCommaSepValues(cachedResp.Header, "vary") { + header = http.CanonicalHeaderKey(header) + if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) { + return false + } + } + return true +} + +// RoundTrip takes a Request and returns a Response +// +// If there is a fresh Response already in cache, then it will be returned without connecting to +// the server. +// +// If there is a stale Response, then any validators it contains will be set on the new request +// to give the server a chance to respond with NotModified. If this happens, then the cached Response +// will be returned. +func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) { + cacheKey := cacheKey(req) + cacheable := (req.Method == "GET" || req.Method == "HEAD") && req.Header.Get("range") == "" + var cachedResp *http.Response + if cacheable { + cachedResp, err = CachedResponse(t.Cache, req) + } else { + // Need to invalidate an existing value + t.Cache.Delete(cacheKey) + } + + transport := t.Transport + if transport == nil { + transport = http.DefaultTransport + } + + if cacheable && cachedResp != nil && err == nil { + if t.MarkCachedResponses { + cachedResp.Header.Set(XFromCache, "1") + } + + if varyMatches(cachedResp, req) { + // Can only use cached value if the new request doesn't Vary significantly + freshness := getFreshness(cachedResp.Header, req.Header) + if freshness == fresh { + return cachedResp, nil + } + + if freshness == stale { + var req2 *http.Request + // Add validators if caller hasn't already done so + etag := cachedResp.Header.Get("etag") + if etag != "" && req.Header.Get("etag") == "" { + req2 = cloneRequest(req) + req2.Header.Set("if-none-match", etag) + } + lastModified := cachedResp.Header.Get("last-modified") + if lastModified != "" && req.Header.Get("last-modified") == "" { + if req2 == nil { + req2 = cloneRequest(req) + } + req2.Header.Set("if-modified-since", lastModified) + } + if req2 != nil { + req = req2 + } + } + } + + resp, err = transport.RoundTrip(req) + if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified { + // Replace the 304 response with the one from cache, but update with some new headers + endToEndHeaders := getEndToEndHeaders(resp.Header) + for _, header := range endToEndHeaders { + cachedResp.Header[header] = resp.Header[header] + } + cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) + cachedResp.StatusCode = http.StatusOK + + resp = cachedResp + } else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) && + req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) { + // In case of transport failure and stale-if-error activated, returns cached content + // when available + cachedResp.Status = fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)) + cachedResp.StatusCode = http.StatusOK + return cachedResp, nil + } else { + if err != nil || resp.StatusCode != http.StatusOK { + t.Cache.Delete(cacheKey) + } + if err != nil { + return nil, err + } + } + } else { + reqCacheControl := parseCacheControl(req.Header) + if _, ok := reqCacheControl["only-if-cached"]; ok { + resp = newGatewayTimeoutResponse(req) + } else { + resp, err = transport.RoundTrip(req) + if err != nil { + return nil, err + } + } + } + + if cacheable && canStore(parseCacheControl(req.Header), parseCacheControl(resp.Header)) { + for _, varyKey := range headerAllCommaSepValues(resp.Header, "vary") { + varyKey = http.CanonicalHeaderKey(varyKey) + fakeHeader := "X-Varied-" + varyKey + reqValue := req.Header.Get(varyKey) + if reqValue != "" { + resp.Header.Set(fakeHeader, reqValue) + } + } + switch req.Method { + case "GET": + // Delay caching until EOF is reached. + resp.Body = &cachingReadCloser{ + R: resp.Body, + OnEOF: func(r io.Reader) { + resp := *resp + resp.Body = ioutil.NopCloser(r) + respBytes, err := httputil.DumpResponse(&resp, true) + if err == nil { + t.Cache.Set(cacheKey, respBytes) + } + }, + } + default: + respBytes, err := httputil.DumpResponse(resp, true) + if err == nil { + t.Cache.Set(cacheKey, respBytes) + } + } + } else { + t.Cache.Delete(cacheKey) + } + return resp, nil +} + +// ErrNoDateHeader indicates that the HTTP headers contained no Date header. +var ErrNoDateHeader = errors.New("no Date header") + +// Date parses and returns the value of the Date header. +func Date(respHeaders http.Header) (date time.Time, err error) { + dateHeader := respHeaders.Get("date") + if dateHeader == "" { + err = ErrNoDateHeader + return + } + + return time.Parse(time.RFC1123, dateHeader) +} + +type realClock struct{} + +func (c *realClock) since(d time.Time) time.Duration { + return time.Since(d) +} + +type timer interface { + since(d time.Time) time.Duration +} + +var clock timer = &realClock{} + +// getFreshness will return one of fresh/stale/transparent based on the cache-control +// values of the request and the response +// +// fresh indicates the response can be returned +// stale indicates that the response needs validating before it is returned +// transparent indicates the response should not be used to fulfil the request +// +// Because this is only a private cache, 'public' and 'private' in cache-control aren't +// signficant. Similarly, smax-age isn't used. +func getFreshness(respHeaders, reqHeaders http.Header) (freshness int) { + respCacheControl := parseCacheControl(respHeaders) + reqCacheControl := parseCacheControl(reqHeaders) + if _, ok := reqCacheControl["no-cache"]; ok { + return transparent + } + if _, ok := respCacheControl["no-cache"]; ok { + return stale + } + if _, ok := reqCacheControl["only-if-cached"]; ok { + return fresh + } + + date, err := Date(respHeaders) + if err != nil { + return stale + } + currentAge := clock.since(date) + + var lifetime time.Duration + var zeroDuration time.Duration + + // If a response includes both an Expires header and a max-age directive, + // the max-age directive overrides the Expires header, even if the Expires header is more restrictive. + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err = time.ParseDuration(maxAge + "s") + if err != nil { + lifetime = zeroDuration + } + } else { + expiresHeader := respHeaders.Get("Expires") + if expiresHeader != "" { + expires, err := time.Parse(time.RFC1123, expiresHeader) + if err != nil { + lifetime = zeroDuration + } else { + lifetime = expires.Sub(date) + } + } + } + + if maxAge, ok := reqCacheControl["max-age"]; ok { + // the client is willing to accept a response whose age is no greater than the specified time in seconds + lifetime, err = time.ParseDuration(maxAge + "s") + if err != nil { + lifetime = zeroDuration + } + } + if minfresh, ok := reqCacheControl["min-fresh"]; ok { + // the client wants a response that will still be fresh for at least the specified number of seconds. + minfreshDuration, err := time.ParseDuration(minfresh + "s") + if err == nil { + currentAge = time.Duration(currentAge + minfreshDuration) + } + } + + if maxstale, ok := reqCacheControl["max-stale"]; ok { + // Indicates that the client is willing to accept a response that has exceeded its expiration time. + // If max-stale is assigned a value, then the client is willing to accept a response that has exceeded + // its expiration time by no more than the specified number of seconds. + // If no value is assigned to max-stale, then the client is willing to accept a stale response of any age. + // + // Responses served only because of a max-stale value are supposed to have a Warning header added to them, + // but that seems like a hassle, and is it actually useful? If so, then there needs to be a different + // return-value available here. + if maxstale == "" { + return fresh + } + maxstaleDuration, err := time.ParseDuration(maxstale + "s") + if err == nil { + currentAge = time.Duration(currentAge - maxstaleDuration) + } + } + + if lifetime > currentAge { + return fresh + } + + return stale +} + +// Returns true if either the request or the response includes the stale-if-error +// cache control extension: https://tools.ietf.org/html/rfc5861 +func canStaleOnError(respHeaders, reqHeaders http.Header) bool { + respCacheControl := parseCacheControl(respHeaders) + reqCacheControl := parseCacheControl(reqHeaders) + + var err error + lifetime := time.Duration(-1) + + if staleMaxAge, ok := respCacheControl["stale-if-error"]; ok { + if staleMaxAge != "" { + lifetime, err = time.ParseDuration(staleMaxAge + "s") + if err != nil { + return false + } + } else { + return true + } + } + if staleMaxAge, ok := reqCacheControl["stale-if-error"]; ok { + if staleMaxAge != "" { + lifetime, err = time.ParseDuration(staleMaxAge + "s") + if err != nil { + return false + } + } else { + return true + } + } + + if lifetime >= 0 { + date, err := Date(respHeaders) + if err != nil { + return false + } + currentAge := clock.since(date) + if lifetime > currentAge { + return true + } + } + + return false +} + +func getEndToEndHeaders(respHeaders http.Header) []string { + // These headers are always hop-by-hop + hopByHopHeaders := map[string]struct{}{ + "Connection": struct{}{}, + "Keep-Alive": struct{}{}, + "Proxy-Authenticate": struct{}{}, + "Proxy-Authorization": struct{}{}, + "Te": struct{}{}, + "Trailers": struct{}{}, + "Transfer-Encoding": struct{}{}, + "Upgrade": struct{}{}, + } + + for _, extra := range strings.Split(respHeaders.Get("connection"), ",") { + // any header listed in connection, if present, is also considered hop-by-hop + if strings.Trim(extra, " ") != "" { + hopByHopHeaders[http.CanonicalHeaderKey(extra)] = struct{}{} + } + } + endToEndHeaders := []string{} + for respHeader, _ := range respHeaders { + if _, ok := hopByHopHeaders[respHeader]; !ok { + endToEndHeaders = append(endToEndHeaders, respHeader) + } + } + return endToEndHeaders +} + +func canStore(reqCacheControl, respCacheControl cacheControl) (canStore bool) { + if _, ok := respCacheControl["no-store"]; ok { + return false + } + if _, ok := reqCacheControl["no-store"]; ok { + return false + } + return true +} + +func newGatewayTimeoutResponse(req *http.Request) *http.Response { + var braw bytes.Buffer + braw.WriteString("HTTP/1.1 504 Gateway Timeout\r\n\r\n") + resp, err := http.ReadResponse(bufio.NewReader(&braw), req) + if err != nil { + panic(err) + } + return resp +} + +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +// (This function copyright goauth2 authors: https://code.google.com/p/goauth2) +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header) + for k, s := range r.Header { + r2.Header[k] = s + } + return r2 +} + +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// headerAllCommaSepValues returns all comma-separated values (each +// with whitespace trimmed) for header name in headers. According to +// Section 4.2 of the HTTP/1.1 spec +// (http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2), +// values from multiple occurrences of a header should be concatenated, if +// the header's value is a comma-separated list. +func headerAllCommaSepValues(headers http.Header, name string) []string { + var vals []string + for _, val := range headers[http.CanonicalHeaderKey(name)] { + fields := strings.Split(val, ",") + for i, f := range fields { + fields[i] = strings.TrimSpace(f) + } + vals = append(vals, fields...) + } + return vals +} + +// cachingReadCloser is a wrapper around ReadCloser R that calls OnEOF +// handler with a full copy of the content read from R when EOF is +// reached. +type cachingReadCloser struct { + // Underlying ReadCloser. + R io.ReadCloser + // OnEOF is called with a copy of the content of R when EOF is reached. + OnEOF func(io.Reader) + + buf bytes.Buffer // buf stores a copy of the content of R. +} + +// Read reads the next len(p) bytes from R or until R is drained. The +// return value n is the number of bytes read. If R has no data to +// return, err is io.EOF and OnEOF is called with a full copy of what +// has been read so far. +func (r *cachingReadCloser) Read(p []byte) (n int, err error) { + n, err = r.R.Read(p) + r.buf.Write(p[:n]) + if err == io.EOF { + r.OnEOF(bytes.NewReader(r.buf.Bytes())) + } + return n, err +} + +func (r *cachingReadCloser) Close() error { + return r.R.Close() +} + +// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation +func NewMemoryCacheTransport() *Transport { + c := NewMemoryCache() + t := NewTransport(c) + return t +} diff --git a/vendor/github.com/liggitt/tabwriter/.travis.yml b/vendor/github.com/liggitt/tabwriter/.travis.yml new file mode 100644 index 000000000..2768dc072 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - "1.8" + - "1.9" + - "1.10" + - "1.11" + - "1.12" + - master + +script: go test -v ./... diff --git a/vendor/github.com/liggitt/tabwriter/LICENSE b/vendor/github.com/liggitt/tabwriter/LICENSE new file mode 100644 index 000000000..6a66aea5e --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/liggitt/tabwriter/README.md b/vendor/github.com/liggitt/tabwriter/README.md new file mode 100644 index 000000000..e75d35672 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/README.md @@ -0,0 +1,7 @@ +This repo is a drop-in replacement for the golang [text/tabwriter](https://golang.org/pkg/text/tabwriter/) package. + +It is based on that package at [cf2c2ea8](https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a/src/text/tabwriter) and inherits its license. + +The following additional features are supported: +* `RememberWidths` flag allows remembering maximum widths seen per column even after Flush() is called. +* `RememberedWidths() []int` and `SetRememberedWidths([]int) *Writer` allows obtaining and transferring remembered column width between writers. diff --git a/vendor/github.com/liggitt/tabwriter/tabwriter.go b/vendor/github.com/liggitt/tabwriter/tabwriter.go new file mode 100644 index 000000000..fd3431fb0 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/tabwriter.go @@ -0,0 +1,637 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tabwriter implements a write filter (tabwriter.Writer) that +// translates tabbed columns in input into properly aligned text. +// +// It is a drop-in replacement for the golang text/tabwriter package (https://golang.org/pkg/text/tabwriter), +// based on that package at https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a +// with support for additional features. +// +// The package is using the Elastic Tabstops algorithm described at +// http://nickgravgaard.com/elastictabstops/index.html. +package tabwriter + +import ( + "io" + "unicode/utf8" +) + +// ---------------------------------------------------------------------------- +// Filter implementation + +// A cell represents a segment of text terminated by tabs or line breaks. +// The text itself is stored in a separate buffer; cell only describes the +// segment's size in bytes, its width in runes, and whether it's an htab +// ('\t') terminated cell. +// +type cell struct { + size int // cell size in bytes + width int // cell width in runes + htab bool // true if the cell is terminated by an htab ('\t') +} + +// A Writer is a filter that inserts padding around tab-delimited +// columns in its input to align them in the output. +// +// The Writer treats incoming bytes as UTF-8-encoded text consisting +// of cells terminated by horizontal ('\t') or vertical ('\v') tabs, +// and newline ('\n') or formfeed ('\f') characters; both newline and +// formfeed act as line breaks. +// +// Tab-terminated cells in contiguous lines constitute a column. The +// Writer inserts padding as needed to make all cells in a column have +// the same width, effectively aligning the columns. It assumes that +// all characters have the same width, except for tabs for which a +// tabwidth must be specified. Column cells must be tab-terminated, not +// tab-separated: non-tab terminated trailing text at the end of a line +// forms a cell but that cell is not part of an aligned column. +// For instance, in this example (where | stands for a horizontal tab): +// +// aaaa|bbb|d +// aa |b |dd +// a | +// aa |cccc|eee +// +// the b and c are in distinct columns (the b column is not contiguous +// all the way). The d and e are not in a column at all (there's no +// terminating tab, nor would the column be contiguous). +// +// The Writer assumes that all Unicode code points have the same width; +// this may not be true in some fonts or if the string contains combining +// characters. +// +// If DiscardEmptyColumns is set, empty columns that are terminated +// entirely by vertical (or "soft") tabs are discarded. Columns +// terminated by horizontal (or "hard") tabs are not affected by +// this flag. +// +// If a Writer is configured to filter HTML, HTML tags and entities +// are passed through. The widths of tags and entities are +// assumed to be zero (tags) and one (entities) for formatting purposes. +// +// A segment of text may be escaped by bracketing it with Escape +// characters. The tabwriter passes escaped text segments through +// unchanged. In particular, it does not interpret any tabs or line +// breaks within the segment. If the StripEscape flag is set, the +// Escape characters are stripped from the output; otherwise they +// are passed through as well. For the purpose of formatting, the +// width of the escaped text is always computed excluding the Escape +// characters. +// +// The formfeed character acts like a newline but it also terminates +// all columns in the current line (effectively calling Flush). Tab- +// terminated cells in the next line start new columns. Unless found +// inside an HTML tag or inside an escaped text segment, formfeed +// characters appear as newlines in the output. +// +// The Writer must buffer input internally, because proper spacing +// of one line may depend on the cells in future lines. Clients must +// call Flush when done calling Write. +// +type Writer struct { + // configuration + output io.Writer + minwidth int + tabwidth int + padding int + padbytes [8]byte + flags uint + + // current state + buf []byte // collected text excluding tabs or line breaks + pos int // buffer position up to which cell.width of incomplete cell has been computed + cell cell // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections + endChar byte // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0) + lines [][]cell // list of lines; each line is a list of cells + widths []int // list of column widths in runes - re-used during formatting + + maxwidths []int // list of max column widths in runes +} + +// addLine adds a new line. +// flushed is a hint indicating whether the underlying writer was just flushed. +// If so, the previous line is not likely to be a good indicator of the new line's cells. +func (b *Writer) addLine(flushed bool) { + // Grow slice instead of appending, + // as that gives us an opportunity + // to re-use an existing []cell. + if n := len(b.lines) + 1; n <= cap(b.lines) { + b.lines = b.lines[:n] + b.lines[n-1] = b.lines[n-1][:0] + } else { + b.lines = append(b.lines, nil) + } + + if !flushed { + // The previous line is probably a good indicator + // of how many cells the current line will have. + // If the current line's capacity is smaller than that, + // abandon it and make a new one. + if n := len(b.lines); n >= 2 { + if prev := len(b.lines[n-2]); prev > cap(b.lines[n-1]) { + b.lines[n-1] = make([]cell, 0, prev) + } + } + } +} + +// Reset the current state. +func (b *Writer) reset() { + b.buf = b.buf[:0] + b.pos = 0 + b.cell = cell{} + b.endChar = 0 + b.lines = b.lines[0:0] + b.widths = b.widths[0:0] + b.addLine(true) +} + +// Internal representation (current state): +// +// - all text written is appended to buf; tabs and line breaks are stripped away +// - at any given time there is a (possibly empty) incomplete cell at the end +// (the cell starts after a tab or line break) +// - cell.size is the number of bytes belonging to the cell so far +// - cell.width is text width in runes of that cell from the start of the cell to +// position pos; html tags and entities are excluded from this width if html +// filtering is enabled +// - the sizes and widths of processed text are kept in the lines list +// which contains a list of cells for each line +// - the widths list is a temporary list with current widths used during +// formatting; it is kept in Writer because it's re-used +// +// |<---------- size ---------->| +// | | +// |<- width ->|<- ignored ->| | +// | | | | +// [---processed---tab------------......] +// ^ ^ ^ +// | | | +// buf start of incomplete cell pos + +// Formatting can be controlled with these flags. +const ( + // Ignore html tags and treat entities (starting with '&' + // and ending in ';') as single characters (width = 1). + FilterHTML uint = 1 << iota + + // Strip Escape characters bracketing escaped text segments + // instead of passing them through unchanged with the text. + StripEscape + + // Force right-alignment of cell content. + // Default is left-alignment. + AlignRight + + // Handle empty columns as if they were not present in + // the input in the first place. + DiscardEmptyColumns + + // Always use tabs for indentation columns (i.e., padding of + // leading empty cells on the left) independent of padchar. + TabIndent + + // Print a vertical bar ('|') between columns (after formatting). + // Discarded columns appear as zero-width columns ("||"). + Debug + + // Remember maximum widths seen per column even after Flush() is called. + RememberWidths +) + +// A Writer must be initialized with a call to Init. The first parameter (output) +// specifies the filter output. The remaining parameters control the formatting: +// +// minwidth minimal cell width including any padding +// tabwidth width of tab characters (equivalent number of spaces) +// padding padding added to a cell before computing its width +// padchar ASCII char used for padding +// if padchar == '\t', the Writer will assume that the +// width of a '\t' in the formatted output is tabwidth, +// and cells are left-aligned independent of align_left +// (for correct-looking results, tabwidth must correspond +// to the tab width in the viewer displaying the result) +// flags formatting control +// +func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + if minwidth < 0 || tabwidth < 0 || padding < 0 { + panic("negative minwidth, tabwidth, or padding") + } + b.output = output + b.minwidth = minwidth + b.tabwidth = tabwidth + b.padding = padding + for i := range b.padbytes { + b.padbytes[i] = padchar + } + if padchar == '\t' { + // tab padding enforces left-alignment + flags &^= AlignRight + } + b.flags = flags + + b.reset() + + return b +} + +// debugging support (keep code around) +func (b *Writer) dump() { + pos := 0 + for i, line := range b.lines { + print("(", i, ") ") + for _, c := range line { + print("[", string(b.buf[pos:pos+c.size]), "]") + pos += c.size + } + print("\n") + } + print("\n") +} + +// local error wrapper so we can distinguish errors we want to return +// as errors from genuine panics (which we don't want to return as errors) +type osError struct { + err error +} + +func (b *Writer) write0(buf []byte) { + n, err := b.output.Write(buf) + if n != len(buf) && err == nil { + err = io.ErrShortWrite + } + if err != nil { + panic(osError{err}) + } +} + +func (b *Writer) writeN(src []byte, n int) { + for n > len(src) { + b.write0(src) + n -= len(src) + } + b.write0(src[0:n]) +} + +var ( + newline = []byte{'\n'} + tabs = []byte("\t\t\t\t\t\t\t\t") +) + +func (b *Writer) writePadding(textw, cellw int, useTabs bool) { + if b.padbytes[0] == '\t' || useTabs { + // padding is done with tabs + if b.tabwidth == 0 { + return // tabs have no width - can't do any padding + } + // make cellw the smallest multiple of b.tabwidth + cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth + n := cellw - textw // amount of padding + if n < 0 { + panic("internal error") + } + b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth) + return + } + + // padding is done with non-tab characters + b.writeN(b.padbytes[0:], cellw-textw) +} + +var vbar = []byte{'|'} + +func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + for i := line0; i < line1; i++ { + line := b.lines[i] + + // if TabIndent is set, use tabs to pad leading empty cells + useTabs := b.flags&TabIndent != 0 + + for j, c := range line { + if j > 0 && b.flags&Debug != 0 { + // indicate column break + b.write0(vbar) + } + + if c.size == 0 { + // empty cell + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], useTabs) + } + } else { + // non-empty cell + useTabs = false + if b.flags&AlignRight == 0 { // align left + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + } else { // align right + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + } + } + } + + if i+1 == len(b.lines) { + // last buffered line - we don't have a newline, so just write + // any outstanding buffered data + b.write0(b.buf[pos : pos+b.cell.size]) + pos += b.cell.size + } else { + // not the last line - write newline + b.write0(newline) + } + } + return +} + +// Format the text between line0 and line1 (excluding line1); pos +// is the buffer position corresponding to the beginning of line0. +// Returns the buffer position corresponding to the beginning of +// line1 and an error, if any. +// +func (b *Writer) format(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + column := len(b.widths) + for this := line0; this < line1; this++ { + line := b.lines[this] + + if column >= len(line)-1 { + continue + } + // cell exists in this column => this line + // has more cells than the previous line + // (the last cell per line is ignored because cells are + // tab-terminated; the last cell per line describes the + // text before the newline/formfeed and does not belong + // to a column) + + // print unprinted lines until beginning of block + pos = b.writeLines(pos, line0, this) + line0 = this + + // column block begin + width := b.minwidth // minimal column width + discardable := true // true if all cells in this column are empty and "soft" + for ; this < line1; this++ { + line = b.lines[this] + if column >= len(line)-1 { + break + } + // cell exists in this column + c := line[column] + // update width + if w := c.width + b.padding; w > width { + width = w + } + // update discardable + if c.width > 0 || c.htab { + discardable = false + } + } + // column block end + + // discard empty columns if necessary + if discardable && b.flags&DiscardEmptyColumns != 0 { + width = 0 + } + + if b.flags&RememberWidths != 0 { + if len(b.maxwidths) < len(b.widths) { + b.maxwidths = append(b.maxwidths, b.widths[len(b.maxwidths):]...) + } + + switch { + case len(b.maxwidths) == len(b.widths): + b.maxwidths = append(b.maxwidths, width) + case b.maxwidths[len(b.widths)] > width: + width = b.maxwidths[len(b.widths)] + case b.maxwidths[len(b.widths)] < width: + b.maxwidths[len(b.widths)] = width + } + } + + // format and print all columns to the right of this column + // (we know the widths of this column and all columns to the left) + b.widths = append(b.widths, width) // push width + pos = b.format(pos, line0, this) + b.widths = b.widths[0 : len(b.widths)-1] // pop width + line0 = this + } + + // print unprinted lines until end + return b.writeLines(pos, line0, line1) +} + +// Append text to current cell. +func (b *Writer) append(text []byte) { + b.buf = append(b.buf, text...) + b.cell.size += len(text) +} + +// Update the cell width. +func (b *Writer) updateWidth() { + b.cell.width += utf8.RuneCount(b.buf[b.pos:]) + b.pos = len(b.buf) +} + +// To escape a text segment, bracket it with Escape characters. +// For instance, the tab in this string "Ignore this tab: \xff\t\xff" +// does not terminate a cell and constitutes a single character of +// width one for formatting purposes. +// +// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence. +// +const Escape = '\xff' + +// Start escaped mode. +func (b *Writer) startEscape(ch byte) { + switch ch { + case Escape: + b.endChar = Escape + case '<': + b.endChar = '>' + case '&': + b.endChar = ';' + } +} + +// Terminate escaped mode. If the escaped text was an HTML tag, its width +// is assumed to be zero for formatting purposes; if it was an HTML entity, +// its width is assumed to be one. In all other cases, the width is the +// unicode width of the text. +// +func (b *Writer) endEscape() { + switch b.endChar { + case Escape: + b.updateWidth() + if b.flags&StripEscape == 0 { + b.cell.width -= 2 // don't count the Escape chars + } + case '>': // tag of zero width + case ';': + b.cell.width++ // entity, count as one rune + } + b.pos = len(b.buf) + b.endChar = 0 +} + +// Terminate the current cell by adding it to the list of cells of the +// current line. Returns the number of cells in that line. +// +func (b *Writer) terminateCell(htab bool) int { + b.cell.htab = htab + line := &b.lines[len(b.lines)-1] + *line = append(*line, b.cell) + b.cell = cell{} + return len(*line) +} + +func handlePanic(err *error, op string) { + if e := recover(); e != nil { + if nerr, ok := e.(osError); ok { + *err = nerr.err + return + } + panic("tabwriter: panic during " + op) + } +} + +// RememberedWidths returns a copy of the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) RememberedWidths() []int { + retval := make([]int, len(b.maxwidths)) + copy(retval, b.maxwidths) + return retval +} + +// SetRememberedWidths sets the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) SetRememberedWidths(widths []int) *Writer { + b.maxwidths = make([]int, len(widths)) + copy(b.maxwidths, widths) + return b +} + +// Flush should be called after the last call to Write to ensure +// that any data buffered in the Writer is written to output. Any +// incomplete escape sequence at the end is considered +// complete for formatting purposes. +func (b *Writer) Flush() error { + return b.flush() +} + +func (b *Writer) flush() (err error) { + defer b.reset() // even in the presence of errors + defer handlePanic(&err, "Flush") + + // add current cell if not empty + if b.cell.size > 0 { + if b.endChar != 0 { + // inside escape - terminate it even if incomplete + b.endEscape() + } + b.terminateCell(false) + } + + // format contents of buffer + b.format(0, 0, len(b.lines)) + return nil +} + +var hbar = []byte("---\n") + +// Write writes buf to the writer b. +// The only errors returned are ones encountered +// while writing to the underlying output stream. +// +func (b *Writer) Write(buf []byte) (n int, err error) { + defer handlePanic(&err, "Write") + + // split text into cells + n = 0 + for i, ch := range buf { + if b.endChar == 0 { + // outside escape + switch ch { + case '\t', '\v', '\n', '\f': + // end of cell + b.append(buf[n:i]) + b.updateWidth() + n = i + 1 // ch consumed + ncells := b.terminateCell(ch == '\t') + if ch == '\n' || ch == '\f' { + // terminate line + b.addLine(ch == '\f') + if ch == '\f' || ncells == 1 { + // A '\f' always forces a flush. Otherwise, if the previous + // line has only one cell which does not have an impact on + // the formatting of the following lines (the last cell per + // line is ignored by format()), thus we can flush the + // Writer contents. + if err = b.Flush(); err != nil { + return + } + if ch == '\f' && b.flags&Debug != 0 { + // indicate section break + b.write0(hbar) + } + } + } + + case Escape: + // start of escaped sequence + b.append(buf[n:i]) + b.updateWidth() + n = i + if b.flags&StripEscape != 0 { + n++ // strip Escape + } + b.startEscape(Escape) + + case '<', '&': + // possibly an html tag/entity + if b.flags&FilterHTML != 0 { + // begin of tag/entity + b.append(buf[n:i]) + b.updateWidth() + n = i + b.startEscape(ch) + } + } + + } else { + // inside escape + if ch == b.endChar { + // end of tag/entity + j := i + 1 + if ch == Escape && b.flags&StripEscape != 0 { + j = i // strip Escape + } + b.append(buf[n:j]) + n = i + 1 // ch consumed + b.endEscape() + } + } + } + + // append leftover text + b.append(buf[n:]) + n = len(buf) + return +} + +// NewWriter allocates and initializes a new tabwriter.Writer. +// The parameters are the same as for the Init function. +// +func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags) +} diff --git a/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md b/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md new file mode 100644 index 000000000..229851590 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-wordwrap/README.md b/vendor/github.com/mitchellh/go-wordwrap/README.md new file mode 100644 index 000000000..60ae31170 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/README.md @@ -0,0 +1,39 @@ +# go-wordwrap + +`go-wordwrap` (Golang package: `wordwrap`) is a package for Go that +automatically wraps words into multiple lines. The primary use case for this +is in formatting CLI output, but of course word wrapping is a generally useful +thing to do. + +## Installation and Usage + +Install using `go get github.com/mitchellh/go-wordwrap`. + +Full documentation is available at +http://godoc.org/github.com/mitchellh/go-wordwrap + +Below is an example of its usage ignoring errors: + +```go +wrapped := wordwrap.WrapString("foo bar baz", 3) +fmt.Println(wrapped) +``` + +Would output: + +``` +foo +bar +baz +``` + +## Word Wrap Algorithm + +This library doesn't use any clever algorithm for word wrapping. The wrapping +is actually very naive: whenever there is whitespace or an explicit linebreak. +The goal of this library is for word wrapping CLI output, so the input is +typically pretty well controlled human language. Because of this, the naive +approach typically works just fine. + +In the future, we'd like to make the algorithm more advanced. We would do +so without breaking the API. diff --git a/vendor/github.com/mitchellh/go-wordwrap/go.mod b/vendor/github.com/mitchellh/go-wordwrap/go.mod new file mode 100644 index 000000000..2ae411b20 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/go-wordwrap diff --git a/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go b/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go new file mode 100644 index 000000000..ac67205bc --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go @@ -0,0 +1,73 @@ +package wordwrap + +import ( + "bytes" + "unicode" +) + +// WrapString wraps the given string within lim width in characters. +// +// Wrapping is currently naive and only happens at white-space. A future +// version of the library will implement smarter wrapping. This means that +// pathological cases can dramatically reach past the limit, such as a very +// long word. +func WrapString(s string, lim uint) string { + // Initialize a buffer with a slightly larger size to account for breaks + init := make([]byte, 0, len(s)) + buf := bytes.NewBuffer(init) + + var current uint + var wordBuf, spaceBuf bytes.Buffer + + for _, char := range s { + if char == '\n' { + if wordBuf.Len() == 0 { + if current+uint(spaceBuf.Len()) > lim { + current = 0 + } else { + current += uint(spaceBuf.Len()) + spaceBuf.WriteTo(buf) + } + spaceBuf.Reset() + } else { + current += uint(spaceBuf.Len() + wordBuf.Len()) + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + wordBuf.WriteTo(buf) + wordBuf.Reset() + } + buf.WriteRune(char) + current = 0 + } else if unicode.IsSpace(char) { + if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { + current += uint(spaceBuf.Len() + wordBuf.Len()) + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + wordBuf.WriteTo(buf) + wordBuf.Reset() + } + + spaceBuf.WriteRune(char) + } else { + + wordBuf.WriteRune(char) + + if current+uint(spaceBuf.Len()+wordBuf.Len()) > lim && uint(wordBuf.Len()) < lim { + buf.WriteRune('\n') + current = 0 + spaceBuf.Reset() + } + } + } + + if wordBuf.Len() == 0 { + if current+uint(spaceBuf.Len()) <= lim { + spaceBuf.WriteTo(buf) + } + } else { + spaceBuf.WriteTo(buf) + wordBuf.WriteTo(buf) + } + + return buf.String() +} diff --git a/vendor/github.com/peterbourgon/diskv/LICENSE b/vendor/github.com/peterbourgon/diskv/LICENSE new file mode 100644 index 000000000..41ce7f16e --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-2012 Peter Bourgon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/peterbourgon/diskv/README.md b/vendor/github.com/peterbourgon/diskv/README.md new file mode 100644 index 000000000..3474739ed --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/README.md @@ -0,0 +1,141 @@ +# What is diskv? + +Diskv (disk-vee) is a simple, persistent key-value store written in the Go +language. It starts with an incredibly simple API for storing arbitrary data on +a filesystem by key, and builds several layers of performance-enhancing +abstraction on top. The end result is a conceptually simple, but highly +performant, disk-backed storage system. + +[![Build Status][1]][2] + +[1]: https://drone.io/github.com/peterbourgon/diskv/status.png +[2]: https://drone.io/github.com/peterbourgon/diskv/latest + + +# Installing + +Install [Go 1][3], either [from source][4] or [with a prepackaged binary][5]. +Then, + +```bash +$ go get github.com/peterbourgon/diskv +``` + +[3]: http://golang.org +[4]: http://golang.org/doc/install/source +[5]: http://golang.org/doc/install + + +# Usage + +```go +package main + +import ( + "fmt" + "github.com/peterbourgon/diskv" +) + +func main() { + // Simplest transform function: put all the data files into the base dir. + flatTransform := func(s string) []string { return []string{} } + + // Initialize a new diskv store, rooted at "my-data-dir", with a 1MB cache. + d := diskv.New(diskv.Options{ + BasePath: "my-data-dir", + Transform: flatTransform, + CacheSizeMax: 1024 * 1024, + }) + + // Write three bytes to the key "alpha". + key := "alpha" + d.Write(key, []byte{'1', '2', '3'}) + + // Read the value back out of the store. + value, _ := d.Read(key) + fmt.Printf("%v\n", value) + + // Erase the key+value from the store (and the disk). + d.Erase(key) +} +``` + +More complex examples can be found in the "examples" subdirectory. + + +# Theory + +## Basic idea + +At its core, diskv is a map of a key (`string`) to arbitrary data (`[]byte`). +The data is written to a single file on disk, with the same name as the key. +The key determines where that file will be stored, via a user-provided +`TransformFunc`, which takes a key and returns a slice (`[]string`) +corresponding to a path list where the key file will be stored. The simplest +TransformFunc, + +```go +func SimpleTransform (key string) []string { + return []string{} +} +``` + +will place all keys in the same, base directory. The design is inspired by +[Redis diskstore][6]; a TransformFunc which emulates the default diskstore +behavior is available in the content-addressable-storage example. + +[6]: http://groups.google.com/group/redis-db/browse_thread/thread/d444bc786689bde9?pli=1 + +**Note** that your TransformFunc should ensure that one valid key doesn't +transform to a subset of another valid key. That is, it shouldn't be possible +to construct valid keys that resolve to directory names. As a concrete example, +if your TransformFunc splits on every 3 characters, then + +```go +d.Write("abcabc", val) // OK: written to /abc/abc/abcabc +d.Write("abc", val) // Error: attempted write to /abc/abc, but it's a directory +``` + +This will be addressed in an upcoming version of diskv. + +Probably the most important design principle behind diskv is that your data is +always flatly available on the disk. diskv will never do anything that would +prevent you from accessing, copying, backing up, or otherwise interacting with +your data via common UNIX commandline tools. + +## Adding a cache + +An in-memory caching layer is provided by combining the BasicStore +functionality with a simple map structure, and keeping it up-to-date as +appropriate. Since the map structure in Go is not threadsafe, it's combined +with a RWMutex to provide safe concurrent access. + +## Adding order + +diskv is a key-value store and therefore inherently unordered. An ordering +system can be injected into the store by passing something which satisfies the +diskv.Index interface. (A default implementation, using Google's +[btree][7] package, is provided.) Basically, diskv keeps an ordered (by a +user-provided Less function) index of the keys, which can be queried. + +[7]: https://github.com/google/btree + +## Adding compression + +Something which implements the diskv.Compression interface may be passed +during store creation, so that all Writes and Reads are filtered through +a compression/decompression pipeline. Several default implementations, +using stdlib compression algorithms, are provided. Note that data is cached +compressed; the cost of decompression is borne with each Read. + +## Streaming + +diskv also now provides ReadStream and WriteStream methods, to allow very large +data to be handled efficiently. + + +# Future plans + + * Needs plenty of robust testing: huge datasets, etc... + * More thorough benchmarking + * Your suggestions for use-cases I haven't thought of diff --git a/vendor/github.com/peterbourgon/diskv/compression.go b/vendor/github.com/peterbourgon/diskv/compression.go new file mode 100644 index 000000000..5192b0273 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/compression.go @@ -0,0 +1,64 @@ +package diskv + +import ( + "compress/flate" + "compress/gzip" + "compress/zlib" + "io" +) + +// Compression is an interface that Diskv uses to implement compression of +// data. Writer takes a destination io.Writer and returns a WriteCloser that +// compresses all data written through it. Reader takes a source io.Reader and +// returns a ReadCloser that decompresses all data read through it. You may +// define these methods on your own type, or use one of the NewCompression +// helpers. +type Compression interface { + Writer(dst io.Writer) (io.WriteCloser, error) + Reader(src io.Reader) (io.ReadCloser, error) +} + +// NewGzipCompression returns a Gzip-based Compression. +func NewGzipCompression() Compression { + return NewGzipCompressionLevel(flate.DefaultCompression) +} + +// NewGzipCompressionLevel returns a Gzip-based Compression with the given level. +func NewGzipCompressionLevel(level int) Compression { + return &genericCompression{ + wf: func(w io.Writer) (io.WriteCloser, error) { return gzip.NewWriterLevel(w, level) }, + rf: func(r io.Reader) (io.ReadCloser, error) { return gzip.NewReader(r) }, + } +} + +// NewZlibCompression returns a Zlib-based Compression. +func NewZlibCompression() Compression { + return NewZlibCompressionLevel(flate.DefaultCompression) +} + +// NewZlibCompressionLevel returns a Zlib-based Compression with the given level. +func NewZlibCompressionLevel(level int) Compression { + return NewZlibCompressionLevelDict(level, nil) +} + +// NewZlibCompressionLevelDict returns a Zlib-based Compression with the given +// level, based on the given dictionary. +func NewZlibCompressionLevelDict(level int, dict []byte) Compression { + return &genericCompression{ + func(w io.Writer) (io.WriteCloser, error) { return zlib.NewWriterLevelDict(w, level, dict) }, + func(r io.Reader) (io.ReadCloser, error) { return zlib.NewReaderDict(r, dict) }, + } +} + +type genericCompression struct { + wf func(w io.Writer) (io.WriteCloser, error) + rf func(r io.Reader) (io.ReadCloser, error) +} + +func (g *genericCompression) Writer(dst io.Writer) (io.WriteCloser, error) { + return g.wf(dst) +} + +func (g *genericCompression) Reader(src io.Reader) (io.ReadCloser, error) { + return g.rf(src) +} diff --git a/vendor/github.com/peterbourgon/diskv/diskv.go b/vendor/github.com/peterbourgon/diskv/diskv.go new file mode 100644 index 000000000..524dc0a6e --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/diskv.go @@ -0,0 +1,624 @@ +// Diskv (disk-vee) is a simple, persistent, key-value store. +// It stores all data flatly on the filesystem. + +package diskv + +import ( + "bytes" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "syscall" +) + +const ( + defaultBasePath = "diskv" + defaultFilePerm os.FileMode = 0666 + defaultPathPerm os.FileMode = 0777 +) + +var ( + defaultTransform = func(s string) []string { return []string{} } + errCanceled = errors.New("canceled") + errEmptyKey = errors.New("empty key") + errBadKey = errors.New("bad key") + errImportDirectory = errors.New("can't import a directory") +) + +// TransformFunction transforms a key into a slice of strings, with each +// element in the slice representing a directory in the file path where the +// key's entry will eventually be stored. +// +// For example, if TransformFunc transforms "abcdef" to ["ab", "cde", "f"], +// the final location of the data file will be /ab/cde/f/abcdef +type TransformFunction func(s string) []string + +// Options define a set of properties that dictate Diskv behavior. +// All values are optional. +type Options struct { + BasePath string + Transform TransformFunction + CacheSizeMax uint64 // bytes + PathPerm os.FileMode + FilePerm os.FileMode + // If TempDir is set, it will enable filesystem atomic writes by + // writing temporary files to that location before being moved + // to BasePath. + // Note that TempDir MUST be on the same device/partition as + // BasePath. + TempDir string + + Index Index + IndexLess LessFunction + + Compression Compression +} + +// Diskv implements the Diskv interface. You shouldn't construct Diskv +// structures directly; instead, use the New constructor. +type Diskv struct { + Options + mu sync.RWMutex + cache map[string][]byte + cacheSize uint64 +} + +// New returns an initialized Diskv structure, ready to use. +// If the path identified by baseDir already contains data, +// it will be accessible, but not yet cached. +func New(o Options) *Diskv { + if o.BasePath == "" { + o.BasePath = defaultBasePath + } + if o.Transform == nil { + o.Transform = defaultTransform + } + if o.PathPerm == 0 { + o.PathPerm = defaultPathPerm + } + if o.FilePerm == 0 { + o.FilePerm = defaultFilePerm + } + + d := &Diskv{ + Options: o, + cache: map[string][]byte{}, + cacheSize: 0, + } + + if d.Index != nil && d.IndexLess != nil { + d.Index.Initialize(d.IndexLess, d.Keys(nil)) + } + + return d +} + +// Write synchronously writes the key-value pair to disk, making it immediately +// available for reads. Write relies on the filesystem to perform an eventual +// sync to physical media. If you need stronger guarantees, see WriteStream. +func (d *Diskv) Write(key string, val []byte) error { + return d.WriteStream(key, bytes.NewBuffer(val), false) +} + +// WriteStream writes the data represented by the io.Reader to the disk, under +// the provided key. If sync is true, WriteStream performs an explicit sync on +// the file as soon as it's written. +// +// bytes.Buffer provides io.Reader semantics for basic data types. +func (d *Diskv) WriteStream(key string, r io.Reader, sync bool) error { + if len(key) <= 0 { + return errEmptyKey + } + + d.mu.Lock() + defer d.mu.Unlock() + + return d.writeStreamWithLock(key, r, sync) +} + +// createKeyFileWithLock either creates the key file directly, or +// creates a temporary file in TempDir if it is set. +func (d *Diskv) createKeyFileWithLock(key string) (*os.File, error) { + if d.TempDir != "" { + if err := os.MkdirAll(d.TempDir, d.PathPerm); err != nil { + return nil, fmt.Errorf("temp mkdir: %s", err) + } + f, err := ioutil.TempFile(d.TempDir, "") + if err != nil { + return nil, fmt.Errorf("temp file: %s", err) + } + + if err := f.Chmod(d.FilePerm); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return nil, fmt.Errorf("chmod: %s", err) + } + return f, nil + } + + mode := os.O_WRONLY | os.O_CREATE | os.O_TRUNC // overwrite if exists + f, err := os.OpenFile(d.completeFilename(key), mode, d.FilePerm) + if err != nil { + return nil, fmt.Errorf("open file: %s", err) + } + return f, nil +} + +// writeStream does no input validation checking. +func (d *Diskv) writeStreamWithLock(key string, r io.Reader, sync bool) error { + if err := d.ensurePathWithLock(key); err != nil { + return fmt.Errorf("ensure path: %s", err) + } + + f, err := d.createKeyFileWithLock(key) + if err != nil { + return fmt.Errorf("create key file: %s", err) + } + + wc := io.WriteCloser(&nopWriteCloser{f}) + if d.Compression != nil { + wc, err = d.Compression.Writer(f) + if err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("compression writer: %s", err) + } + } + + if _, err := io.Copy(wc, r); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("i/o copy: %s", err) + } + + if err := wc.Close(); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("compression close: %s", err) + } + + if sync { + if err := f.Sync(); err != nil { + f.Close() // error deliberately ignored + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("file sync: %s", err) + } + } + + if err := f.Close(); err != nil { + return fmt.Errorf("file close: %s", err) + } + + if f.Name() != d.completeFilename(key) { + if err := os.Rename(f.Name(), d.completeFilename(key)); err != nil { + os.Remove(f.Name()) // error deliberately ignored + return fmt.Errorf("rename: %s", err) + } + } + + if d.Index != nil { + d.Index.Insert(key) + } + + d.bustCacheWithLock(key) // cache only on read + + return nil +} + +// Import imports the source file into diskv under the destination key. If the +// destination key already exists, it's overwritten. If move is true, the +// source file is removed after a successful import. +func (d *Diskv) Import(srcFilename, dstKey string, move bool) (err error) { + if dstKey == "" { + return errEmptyKey + } + + if fi, err := os.Stat(srcFilename); err != nil { + return err + } else if fi.IsDir() { + return errImportDirectory + } + + d.mu.Lock() + defer d.mu.Unlock() + + if err := d.ensurePathWithLock(dstKey); err != nil { + return fmt.Errorf("ensure path: %s", err) + } + + if move { + if err := syscall.Rename(srcFilename, d.completeFilename(dstKey)); err == nil { + d.bustCacheWithLock(dstKey) + return nil + } else if err != syscall.EXDEV { + // If it failed due to being on a different device, fall back to copying + return err + } + } + + f, err := os.Open(srcFilename) + if err != nil { + return err + } + defer f.Close() + err = d.writeStreamWithLock(dstKey, f, false) + if err == nil && move { + err = os.Remove(srcFilename) + } + return err +} + +// Read reads the key and returns the value. +// If the key is available in the cache, Read won't touch the disk. +// If the key is not in the cache, Read will have the side-effect of +// lazily caching the value. +func (d *Diskv) Read(key string) ([]byte, error) { + rc, err := d.ReadStream(key, false) + if err != nil { + return []byte{}, err + } + defer rc.Close() + return ioutil.ReadAll(rc) +} + +// ReadStream reads the key and returns the value (data) as an io.ReadCloser. +// If the value is cached from a previous read, and direct is false, +// ReadStream will use the cached value. Otherwise, it will return a handle to +// the file on disk, and cache the data on read. +// +// If direct is true, ReadStream will lazily delete any cached value for the +// key, and return a direct handle to the file on disk. +// +// If compression is enabled, ReadStream taps into the io.Reader stream prior +// to decompression, and caches the compressed data. +func (d *Diskv) ReadStream(key string, direct bool) (io.ReadCloser, error) { + d.mu.RLock() + defer d.mu.RUnlock() + + if val, ok := d.cache[key]; ok { + if !direct { + buf := bytes.NewBuffer(val) + if d.Compression != nil { + return d.Compression.Reader(buf) + } + return ioutil.NopCloser(buf), nil + } + + go func() { + d.mu.Lock() + defer d.mu.Unlock() + d.uncacheWithLock(key, uint64(len(val))) + }() + } + + return d.readWithRLock(key) +} + +// read ignores the cache, and returns an io.ReadCloser representing the +// decompressed data for the given key, streamed from the disk. Clients should +// acquire a read lock on the Diskv and check the cache themselves before +// calling read. +func (d *Diskv) readWithRLock(key string) (io.ReadCloser, error) { + filename := d.completeFilename(key) + + fi, err := os.Stat(filename) + if err != nil { + return nil, err + } + if fi.IsDir() { + return nil, os.ErrNotExist + } + + f, err := os.Open(filename) + if err != nil { + return nil, err + } + + var r io.Reader + if d.CacheSizeMax > 0 { + r = newSiphon(f, d, key) + } else { + r = &closingReader{f} + } + + var rc = io.ReadCloser(ioutil.NopCloser(r)) + if d.Compression != nil { + rc, err = d.Compression.Reader(r) + if err != nil { + return nil, err + } + } + + return rc, nil +} + +// closingReader provides a Reader that automatically closes the +// embedded ReadCloser when it reaches EOF +type closingReader struct { + rc io.ReadCloser +} + +func (cr closingReader) Read(p []byte) (int, error) { + n, err := cr.rc.Read(p) + if err == io.EOF { + if closeErr := cr.rc.Close(); closeErr != nil { + return n, closeErr // close must succeed for Read to succeed + } + } + return n, err +} + +// siphon is like a TeeReader: it copies all data read through it to an +// internal buffer, and moves that buffer to the cache at EOF. +type siphon struct { + f *os.File + d *Diskv + key string + buf *bytes.Buffer +} + +// newSiphon constructs a siphoning reader that represents the passed file. +// When a successful series of reads ends in an EOF, the siphon will write +// the buffered data to Diskv's cache under the given key. +func newSiphon(f *os.File, d *Diskv, key string) io.Reader { + return &siphon{ + f: f, + d: d, + key: key, + buf: &bytes.Buffer{}, + } +} + +// Read implements the io.Reader interface for siphon. +func (s *siphon) Read(p []byte) (int, error) { + n, err := s.f.Read(p) + + if err == nil { + return s.buf.Write(p[0:n]) // Write must succeed for Read to succeed + } + + if err == io.EOF { + s.d.cacheWithoutLock(s.key, s.buf.Bytes()) // cache may fail + if closeErr := s.f.Close(); closeErr != nil { + return n, closeErr // close must succeed for Read to succeed + } + return n, err + } + + return n, err +} + +// Erase synchronously erases the given key from the disk and the cache. +func (d *Diskv) Erase(key string) error { + d.mu.Lock() + defer d.mu.Unlock() + + d.bustCacheWithLock(key) + + // erase from index + if d.Index != nil { + d.Index.Delete(key) + } + + // erase from disk + filename := d.completeFilename(key) + if s, err := os.Stat(filename); err == nil { + if s.IsDir() { + return errBadKey + } + if err = os.Remove(filename); err != nil { + return err + } + } else { + // Return err as-is so caller can do os.IsNotExist(err). + return err + } + + // clean up and return + d.pruneDirsWithLock(key) + return nil +} + +// EraseAll will delete all of the data from the store, both in the cache and on +// the disk. Note that EraseAll doesn't distinguish diskv-related data from non- +// diskv-related data. Care should be taken to always specify a diskv base +// directory that is exclusively for diskv data. +func (d *Diskv) EraseAll() error { + d.mu.Lock() + defer d.mu.Unlock() + d.cache = make(map[string][]byte) + d.cacheSize = 0 + if d.TempDir != "" { + os.RemoveAll(d.TempDir) // errors ignored + } + return os.RemoveAll(d.BasePath) +} + +// Has returns true if the given key exists. +func (d *Diskv) Has(key string) bool { + d.mu.Lock() + defer d.mu.Unlock() + + if _, ok := d.cache[key]; ok { + return true + } + + filename := d.completeFilename(key) + s, err := os.Stat(filename) + if err != nil { + return false + } + if s.IsDir() { + return false + } + + return true +} + +// Keys returns a channel that will yield every key accessible by the store, +// in undefined order. If a cancel channel is provided, closing it will +// terminate and close the keys channel. +func (d *Diskv) Keys(cancel <-chan struct{}) <-chan string { + return d.KeysPrefix("", cancel) +} + +// KeysPrefix returns a channel that will yield every key accessible by the +// store with the given prefix, in undefined order. If a cancel channel is +// provided, closing it will terminate and close the keys channel. If the +// provided prefix is the empty string, all keys will be yielded. +func (d *Diskv) KeysPrefix(prefix string, cancel <-chan struct{}) <-chan string { + var prepath string + if prefix == "" { + prepath = d.BasePath + } else { + prepath = d.pathFor(prefix) + } + c := make(chan string) + go func() { + filepath.Walk(prepath, walker(c, prefix, cancel)) + close(c) + }() + return c +} + +// walker returns a function which satisfies the filepath.WalkFunc interface. +// It sends every non-directory file entry down the channel c. +func walker(c chan<- string, prefix string, cancel <-chan struct{}) filepath.WalkFunc { + return func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() || !strings.HasPrefix(info.Name(), prefix) { + return nil // "pass" + } + + select { + case c <- info.Name(): + case <-cancel: + return errCanceled + } + + return nil + } +} + +// pathFor returns the absolute path for location on the filesystem where the +// data for the given key will be stored. +func (d *Diskv) pathFor(key string) string { + return filepath.Join(d.BasePath, filepath.Join(d.Transform(key)...)) +} + +// ensurePathWithLock is a helper function that generates all necessary +// directories on the filesystem for the given key. +func (d *Diskv) ensurePathWithLock(key string) error { + return os.MkdirAll(d.pathFor(key), d.PathPerm) +} + +// completeFilename returns the absolute path to the file for the given key. +func (d *Diskv) completeFilename(key string) string { + return filepath.Join(d.pathFor(key), key) +} + +// cacheWithLock attempts to cache the given key-value pair in the store's +// cache. It can fail if the value is larger than the cache's maximum size. +func (d *Diskv) cacheWithLock(key string, val []byte) error { + valueSize := uint64(len(val)) + if err := d.ensureCacheSpaceWithLock(valueSize); err != nil { + return fmt.Errorf("%s; not caching", err) + } + + // be very strict about memory guarantees + if (d.cacheSize + valueSize) > d.CacheSizeMax { + panic(fmt.Sprintf("failed to make room for value (%d/%d)", valueSize, d.CacheSizeMax)) + } + + d.cache[key] = val + d.cacheSize += valueSize + return nil +} + +// cacheWithoutLock acquires the store's (write) mutex and calls cacheWithLock. +func (d *Diskv) cacheWithoutLock(key string, val []byte) error { + d.mu.Lock() + defer d.mu.Unlock() + return d.cacheWithLock(key, val) +} + +func (d *Diskv) bustCacheWithLock(key string) { + if val, ok := d.cache[key]; ok { + d.uncacheWithLock(key, uint64(len(val))) + } +} + +func (d *Diskv) uncacheWithLock(key string, sz uint64) { + d.cacheSize -= sz + delete(d.cache, key) +} + +// pruneDirsWithLock deletes empty directories in the path walk leading to the +// key k. Typically this function is called after an Erase is made. +func (d *Diskv) pruneDirsWithLock(key string) error { + pathlist := d.Transform(key) + for i := range pathlist { + dir := filepath.Join(d.BasePath, filepath.Join(pathlist[:len(pathlist)-i]...)) + + // thanks to Steven Blenkinsop for this snippet + switch fi, err := os.Stat(dir); true { + case err != nil: + return err + case !fi.IsDir(): + panic(fmt.Sprintf("corrupt dirstate at %s", dir)) + } + + nlinks, err := filepath.Glob(filepath.Join(dir, "*")) + if err != nil { + return err + } else if len(nlinks) > 0 { + return nil // has subdirs -- do not prune + } + if err = os.Remove(dir); err != nil { + return err + } + } + + return nil +} + +// ensureCacheSpaceWithLock deletes entries from the cache in arbitrary order +// until the cache has at least valueSize bytes available. +func (d *Diskv) ensureCacheSpaceWithLock(valueSize uint64) error { + if valueSize > d.CacheSizeMax { + return fmt.Errorf("value size (%d bytes) too large for cache (%d bytes)", valueSize, d.CacheSizeMax) + } + + safe := func() bool { return (d.cacheSize + valueSize) <= d.CacheSizeMax } + + for key, val := range d.cache { + if safe() { + break + } + + d.uncacheWithLock(key, uint64(len(val))) + } + + if !safe() { + panic(fmt.Sprintf("%d bytes still won't fit in the cache! (max %d bytes)", valueSize, d.CacheSizeMax)) + } + + return nil +} + +// nopWriteCloser wraps an io.Writer and provides a no-op Close method to +// satisfy the io.WriteCloser interface. +type nopWriteCloser struct { + io.Writer +} + +func (wc *nopWriteCloser) Write(p []byte) (int, error) { return wc.Writer.Write(p) } +func (wc *nopWriteCloser) Close() error { return nil } diff --git a/vendor/github.com/peterbourgon/diskv/index.go b/vendor/github.com/peterbourgon/diskv/index.go new file mode 100644 index 000000000..96fee5152 --- /dev/null +++ b/vendor/github.com/peterbourgon/diskv/index.go @@ -0,0 +1,115 @@ +package diskv + +import ( + "sync" + + "github.com/google/btree" +) + +// Index is a generic interface for things that can +// provide an ordered list of keys. +type Index interface { + Initialize(less LessFunction, keys <-chan string) + Insert(key string) + Delete(key string) + Keys(from string, n int) []string +} + +// LessFunction is used to initialize an Index of keys in a specific order. +type LessFunction func(string, string) bool + +// btreeString is a custom data type that satisfies the BTree Less interface, +// making the strings it wraps sortable by the BTree package. +type btreeString struct { + s string + l LessFunction +} + +// Less satisfies the BTree.Less interface using the btreeString's LessFunction. +func (s btreeString) Less(i btree.Item) bool { + return s.l(s.s, i.(btreeString).s) +} + +// BTreeIndex is an implementation of the Index interface using google/btree. +type BTreeIndex struct { + sync.RWMutex + LessFunction + *btree.BTree +} + +// Initialize populates the BTree tree with data from the keys channel, +// according to the passed less function. It's destructive to the BTreeIndex. +func (i *BTreeIndex) Initialize(less LessFunction, keys <-chan string) { + i.Lock() + defer i.Unlock() + i.LessFunction = less + i.BTree = rebuild(less, keys) +} + +// Insert inserts the given key (only) into the BTree tree. +func (i *BTreeIndex) Insert(key string) { + i.Lock() + defer i.Unlock() + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + i.BTree.ReplaceOrInsert(btreeString{s: key, l: i.LessFunction}) +} + +// Delete removes the given key (only) from the BTree tree. +func (i *BTreeIndex) Delete(key string) { + i.Lock() + defer i.Unlock() + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + i.BTree.Delete(btreeString{s: key, l: i.LessFunction}) +} + +// Keys yields a maximum of n keys in order. If the passed 'from' key is empty, +// Keys will return the first n keys. If the passed 'from' key is non-empty, the +// first key in the returned slice will be the key that immediately follows the +// passed key, in key order. +func (i *BTreeIndex) Keys(from string, n int) []string { + i.RLock() + defer i.RUnlock() + + if i.BTree == nil || i.LessFunction == nil { + panic("uninitialized index") + } + + if i.BTree.Len() <= 0 { + return []string{} + } + + btreeFrom := btreeString{s: from, l: i.LessFunction} + skipFirst := true + if len(from) <= 0 || !i.BTree.Has(btreeFrom) { + // no such key, so fabricate an always-smallest item + btreeFrom = btreeString{s: "", l: func(string, string) bool { return true }} + skipFirst = false + } + + keys := []string{} + iterator := func(i btree.Item) bool { + keys = append(keys, i.(btreeString).s) + return len(keys) < n + } + i.BTree.AscendGreaterOrEqual(btreeFrom, iterator) + + if skipFirst && len(keys) > 0 { + keys = keys[1:] + } + + return keys +} + +// rebuildIndex does the work of regenerating the index +// with the given keys. +func rebuild(less LessFunction, keys <-chan string) *btree.BTree { + tree := btree.New(2) + for key := range keys { + tree.ReplaceOrInsert(btreeString{s: key, l: less}) + } + return tree +} diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/doc.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/doc.go new file mode 100644 index 000000000..5db6d52d4 --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:protobuf-gen=package +// +k8s:openapi-gen=true + +// +groupName=imagepolicy.k8s.io + +package v1alpha1 // import "k8s.io/api/imagepolicy/v1alpha1" diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go new file mode 100644 index 000000000..912a93ecb --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.pb.go @@ -0,0 +1,1412 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: k8s.io/kubernetes/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto + +package v1alpha1 + +import ( + fmt "fmt" + + io "io" + + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" + + math "math" + math_bits "math/bits" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +func (m *ImageReview) Reset() { *m = ImageReview{} } +func (*ImageReview) ProtoMessage() {} +func (*ImageReview) Descriptor() ([]byte, []int) { + return fileDescriptor_834793af728657a5, []int{0} +} +func (m *ImageReview) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ImageReview) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ImageReview) XXX_Merge(src proto.Message) { + xxx_messageInfo_ImageReview.Merge(m, src) +} +func (m *ImageReview) XXX_Size() int { + return m.Size() +} +func (m *ImageReview) XXX_DiscardUnknown() { + xxx_messageInfo_ImageReview.DiscardUnknown(m) +} + +var xxx_messageInfo_ImageReview proto.InternalMessageInfo + +func (m *ImageReviewContainerSpec) Reset() { *m = ImageReviewContainerSpec{} } +func (*ImageReviewContainerSpec) ProtoMessage() {} +func (*ImageReviewContainerSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_834793af728657a5, []int{1} +} +func (m *ImageReviewContainerSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ImageReviewContainerSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ImageReviewContainerSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_ImageReviewContainerSpec.Merge(m, src) +} +func (m *ImageReviewContainerSpec) XXX_Size() int { + return m.Size() +} +func (m *ImageReviewContainerSpec) XXX_DiscardUnknown() { + xxx_messageInfo_ImageReviewContainerSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_ImageReviewContainerSpec proto.InternalMessageInfo + +func (m *ImageReviewSpec) Reset() { *m = ImageReviewSpec{} } +func (*ImageReviewSpec) ProtoMessage() {} +func (*ImageReviewSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_834793af728657a5, []int{2} +} +func (m *ImageReviewSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ImageReviewSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ImageReviewSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_ImageReviewSpec.Merge(m, src) +} +func (m *ImageReviewSpec) XXX_Size() int { + return m.Size() +} +func (m *ImageReviewSpec) XXX_DiscardUnknown() { + xxx_messageInfo_ImageReviewSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_ImageReviewSpec proto.InternalMessageInfo + +func (m *ImageReviewStatus) Reset() { *m = ImageReviewStatus{} } +func (*ImageReviewStatus) ProtoMessage() {} +func (*ImageReviewStatus) Descriptor() ([]byte, []int) { + return fileDescriptor_834793af728657a5, []int{3} +} +func (m *ImageReviewStatus) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ImageReviewStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ImageReviewStatus) XXX_Merge(src proto.Message) { + xxx_messageInfo_ImageReviewStatus.Merge(m, src) +} +func (m *ImageReviewStatus) XXX_Size() int { + return m.Size() +} +func (m *ImageReviewStatus) XXX_DiscardUnknown() { + xxx_messageInfo_ImageReviewStatus.DiscardUnknown(m) +} + +var xxx_messageInfo_ImageReviewStatus proto.InternalMessageInfo + +func init() { + proto.RegisterType((*ImageReview)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReview") + proto.RegisterType((*ImageReviewContainerSpec)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReviewContainerSpec") + proto.RegisterType((*ImageReviewSpec)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReviewSpec") + proto.RegisterMapType((map[string]string)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReviewSpec.AnnotationsEntry") + proto.RegisterType((*ImageReviewStatus)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReviewStatus") + proto.RegisterMapType((map[string]string)(nil), "k8s.io.api.imagepolicy.v1alpha1.ImageReviewStatus.AuditAnnotationsEntry") +} + +func init() { + proto.RegisterFile("k8s.io/kubernetes/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto", fileDescriptor_834793af728657a5) +} + +var fileDescriptor_834793af728657a5 = []byte{ + // 607 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xcf, 0x6e, 0xd3, 0x4c, + 0x14, 0xc5, 0xe3, 0xa4, 0xff, 0x32, 0xf9, 0x3e, 0x9a, 0x0e, 0x20, 0x59, 0x59, 0xb8, 0x55, 0x90, + 0x50, 0x59, 0x30, 0x43, 0x2b, 0x84, 0x0a, 0x0b, 0x50, 0x5c, 0x21, 0x95, 0x05, 0x20, 0x0d, 0xbb, + 0xae, 0x98, 0x38, 0x17, 0xc7, 0x24, 0x9e, 0xb1, 0x3c, 0xe3, 0x94, 0xec, 0x78, 0x02, 0xc4, 0x1b, + 0xf0, 0x22, 0x3c, 0x40, 0x97, 0x5d, 0x76, 0x55, 0x51, 0xb3, 0xe4, 0x25, 0x90, 0xc7, 0x4e, 0x6c, + 0x92, 0x22, 0x94, 0x9d, 0xef, 0xbd, 0x73, 0x7e, 0xf7, 0xcc, 0xf1, 0xa0, 0x93, 0xd1, 0x91, 0x22, + 0x81, 0xa4, 0xa3, 0xa4, 0x0f, 0xb1, 0x00, 0x0d, 0x8a, 0x4e, 0x40, 0x0c, 0x64, 0x4c, 0x8b, 0x01, + 0x8f, 0x02, 0x1a, 0x84, 0xdc, 0x87, 0x48, 0x8e, 0x03, 0x6f, 0x4a, 0x27, 0x07, 0x7c, 0x1c, 0x0d, + 0xf9, 0x01, 0xf5, 0x41, 0x40, 0xcc, 0x35, 0x0c, 0x48, 0x14, 0x4b, 0x2d, 0xf1, 0x6e, 0x2e, 0x20, + 0x3c, 0x0a, 0x48, 0x45, 0x40, 0x66, 0x82, 0xce, 0x43, 0x3f, 0xd0, 0xc3, 0xa4, 0x4f, 0x3c, 0x19, + 0x52, 0x5f, 0xfa, 0x92, 0x1a, 0x5d, 0x3f, 0xf9, 0x60, 0x2a, 0x53, 0x98, 0xaf, 0x9c, 0xd7, 0x79, + 0x5c, 0x1a, 0x08, 0xb9, 0x37, 0x0c, 0x04, 0xc4, 0x53, 0x1a, 0x8d, 0xfc, 0xac, 0xa1, 0x68, 0x08, + 0x9a, 0xd3, 0xc9, 0x92, 0x8b, 0x0e, 0xfd, 0x9b, 0x2a, 0x4e, 0x84, 0x0e, 0x42, 0x58, 0x12, 0x3c, + 0xf9, 0x97, 0x40, 0x79, 0x43, 0x08, 0xf9, 0xa2, 0xae, 0xfb, 0xad, 0x8e, 0x5a, 0xaf, 0xb2, 0x6b, + 0x32, 0x98, 0x04, 0x70, 0x86, 0xdf, 0xa3, 0xad, 0xcc, 0xd3, 0x80, 0x6b, 0x6e, 0x5b, 0x7b, 0xd6, + 0x7e, 0xeb, 0xf0, 0x11, 0x29, 0x13, 0x99, 0xa3, 0x49, 0x34, 0xf2, 0xb3, 0x86, 0x22, 0xd9, 0x69, + 0x32, 0x39, 0x20, 0x6f, 0xfb, 0x1f, 0xc1, 0xd3, 0xaf, 0x41, 0x73, 0x17, 0x9f, 0x5f, 0xed, 0xd6, + 0xd2, 0xab, 0x5d, 0x54, 0xf6, 0xd8, 0x9c, 0x8a, 0x19, 0x5a, 0x53, 0x11, 0x78, 0x76, 0x7d, 0x89, + 0x7e, 0x63, 0xde, 0xa4, 0xe2, 0xee, 0x5d, 0x04, 0x9e, 0xfb, 0x5f, 0x41, 0x5f, 0xcb, 0x2a, 0x66, + 0x58, 0xf8, 0x14, 0x6d, 0x28, 0xcd, 0x75, 0xa2, 0xec, 0x86, 0xa1, 0x1e, 0xae, 0x44, 0x35, 0x4a, + 0xf7, 0x56, 0xc1, 0xdd, 0xc8, 0x6b, 0x56, 0x10, 0xbb, 0x2f, 0x90, 0x5d, 0x39, 0x7c, 0x2c, 0x85, + 0xe6, 0x59, 0x04, 0xd9, 0x76, 0x7c, 0x0f, 0xad, 0x1b, 0xba, 0x89, 0xaa, 0xe9, 0xfe, 0x5f, 0x20, + 0xd6, 0x73, 0x41, 0x3e, 0xeb, 0xfe, 0xaa, 0xa3, 0xed, 0x85, 0x4b, 0xe0, 0x10, 0x21, 0x6f, 0x46, + 0x52, 0xb6, 0xb5, 0xd7, 0xd8, 0x6f, 0x1d, 0x3e, 0x5d, 0xc5, 0xf4, 0x1f, 0x3e, 0xca, 0xc4, 0xe7, + 0x6d, 0xc5, 0x2a, 0x0b, 0xf0, 0x27, 0xd4, 0xe2, 0x42, 0x48, 0xcd, 0x75, 0x20, 0x85, 0xb2, 0xeb, + 0x66, 0x5f, 0x6f, 0xd5, 0xe8, 0x49, 0xaf, 0x64, 0xbc, 0x14, 0x3a, 0x9e, 0xba, 0xb7, 0x8b, 0xbd, + 0xad, 0xca, 0x84, 0x55, 0x57, 0x61, 0x8a, 0x9a, 0x82, 0x87, 0xa0, 0x22, 0xee, 0x81, 0xf9, 0x39, + 0x4d, 0x77, 0xa7, 0x10, 0x35, 0xdf, 0xcc, 0x06, 0xac, 0x3c, 0xd3, 0x79, 0x8e, 0xda, 0x8b, 0x6b, + 0x70, 0x1b, 0x35, 0x46, 0x30, 0xcd, 0x43, 0x66, 0xd9, 0x27, 0xbe, 0x83, 0xd6, 0x27, 0x7c, 0x9c, + 0x80, 0x79, 0x45, 0x4d, 0x96, 0x17, 0xcf, 0xea, 0x47, 0x56, 0xf7, 0x7b, 0x1d, 0xed, 0x2c, 0xfd, + 0x5c, 0xfc, 0x00, 0x6d, 0xf2, 0xf1, 0x58, 0x9e, 0xc1, 0xc0, 0x50, 0xb6, 0xdc, 0xed, 0xc2, 0xc4, + 0x66, 0x2f, 0x6f, 0xb3, 0xd9, 0x1c, 0xdf, 0x47, 0x1b, 0x31, 0x70, 0x25, 0x45, 0xce, 0x2e, 0xdf, + 0x05, 0x33, 0x5d, 0x56, 0x4c, 0xf1, 0x17, 0x0b, 0xb5, 0x79, 0x32, 0x08, 0x74, 0xc5, 0xae, 0xdd, + 0x30, 0xc9, 0x9e, 0xac, 0xfe, 0xfc, 0x48, 0x6f, 0x01, 0x95, 0x07, 0x6c, 0x17, 0xcb, 0xdb, 0x8b, + 0x63, 0xb6, 0xb4, 0xbb, 0x73, 0x8c, 0xee, 0xde, 0x08, 0x59, 0x25, 0x3e, 0x97, 0x9c, 0x5f, 0x3b, + 0xb5, 0x8b, 0x6b, 0xa7, 0x76, 0x79, 0xed, 0xd4, 0x3e, 0xa7, 0x8e, 0x75, 0x9e, 0x3a, 0xd6, 0x45, + 0xea, 0x58, 0x97, 0xa9, 0x63, 0xfd, 0x48, 0x1d, 0xeb, 0xeb, 0x4f, 0xa7, 0x76, 0xba, 0x35, 0xbb, + 0xc8, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x44, 0x16, 0x48, 0xa2, 0x79, 0x05, 0x00, 0x00, +} + +func (m *ImageReview) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageReview) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ImageReview) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ImageReviewContainerSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageReviewContainerSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ImageReviewContainerSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Image) + copy(dAtA[i:], m.Image) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Image))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ImageReviewSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageReviewSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ImageReviewSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Namespace) + copy(dAtA[i:], m.Namespace) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Namespace))) + i-- + dAtA[i] = 0x1a + if len(m.Annotations) > 0 { + keysForAnnotations := make([]string, 0, len(m.Annotations)) + for k := range m.Annotations { + keysForAnnotations = append(keysForAnnotations, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) + for iNdEx := len(keysForAnnotations) - 1; iNdEx >= 0; iNdEx-- { + v := m.Annotations[string(keysForAnnotations[iNdEx])] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintGenerated(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(keysForAnnotations[iNdEx]) + copy(dAtA[i:], keysForAnnotations[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(keysForAnnotations[iNdEx]))) + i-- + dAtA[i] = 0xa + i = encodeVarintGenerated(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Containers) > 0 { + for iNdEx := len(m.Containers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Containers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ImageReviewStatus) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageReviewStatus) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ImageReviewStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AuditAnnotations) > 0 { + keysForAuditAnnotations := make([]string, 0, len(m.AuditAnnotations)) + for k := range m.AuditAnnotations { + keysForAuditAnnotations = append(keysForAuditAnnotations, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAuditAnnotations) + for iNdEx := len(keysForAuditAnnotations) - 1; iNdEx >= 0; iNdEx-- { + v := m.AuditAnnotations[string(keysForAuditAnnotations[iNdEx])] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintGenerated(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(keysForAuditAnnotations[iNdEx]) + copy(dAtA[i:], keysForAuditAnnotations[iNdEx]) + i = encodeVarintGenerated(dAtA, i, uint64(len(keysForAuditAnnotations[iNdEx]))) + i-- + dAtA[i] = 0xa + i = encodeVarintGenerated(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0x1a + } + } + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x12 + i-- + if m.Allowed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + return len(dAtA) - i, nil +} + +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + offset -= sovGenerated(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ImageReview) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ImageReviewContainerSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Image) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ImageReviewSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Containers) > 0 { + for _, e := range m.Containers { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + if len(m.Annotations) > 0 { + for k, v := range m.Annotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + l = len(m.Namespace) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ImageReviewStatus) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 2 + l = len(m.Reason) + n += 1 + l + sovGenerated(uint64(l)) + if len(m.AuditAnnotations) > 0 { + for k, v := range m.AuditAnnotations { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v))) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + return n +} + +func sovGenerated(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenerated(x uint64) (n int) { + return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *ImageReview) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageReview{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "ImageReviewSpec", "ImageReviewSpec", 1), `&`, ``, 1) + `,`, + `Status:` + strings.Replace(strings.Replace(this.Status.String(), "ImageReviewStatus", "ImageReviewStatus", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ImageReviewContainerSpec) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageReviewContainerSpec{`, + `Image:` + fmt.Sprintf("%v", this.Image) + `,`, + `}`, + }, "") + return s +} +func (this *ImageReviewSpec) String() string { + if this == nil { + return "nil" + } + repeatedStringForContainers := "[]ImageReviewContainerSpec{" + for _, f := range this.Containers { + repeatedStringForContainers += strings.Replace(strings.Replace(f.String(), "ImageReviewContainerSpec", "ImageReviewContainerSpec", 1), `&`, ``, 1) + "," + } + repeatedStringForContainers += "}" + keysForAnnotations := make([]string, 0, len(this.Annotations)) + for k := range this.Annotations { + keysForAnnotations = append(keysForAnnotations, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAnnotations) + mapStringForAnnotations := "map[string]string{" + for _, k := range keysForAnnotations { + mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k]) + } + mapStringForAnnotations += "}" + s := strings.Join([]string{`&ImageReviewSpec{`, + `Containers:` + repeatedStringForContainers + `,`, + `Annotations:` + mapStringForAnnotations + `,`, + `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, + `}`, + }, "") + return s +} +func (this *ImageReviewStatus) String() string { + if this == nil { + return "nil" + } + keysForAuditAnnotations := make([]string, 0, len(this.AuditAnnotations)) + for k := range this.AuditAnnotations { + keysForAuditAnnotations = append(keysForAuditAnnotations, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForAuditAnnotations) + mapStringForAuditAnnotations := "map[string]string{" + for _, k := range keysForAuditAnnotations { + mapStringForAuditAnnotations += fmt.Sprintf("%v: %v,", k, this.AuditAnnotations[k]) + } + mapStringForAuditAnnotations += "}" + s := strings.Join([]string{`&ImageReviewStatus{`, + `Allowed:` + fmt.Sprintf("%v", this.Allowed) + `,`, + `Reason:` + fmt.Sprintf("%v", this.Reason) + `,`, + `AuditAnnotations:` + mapStringForAuditAnnotations + `,`, + `}`, + }, "") + return s +} +func valueToStringGenerated(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *ImageReview) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageReview: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageReview: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ImageReviewContainerSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageReviewContainerSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageReviewContainerSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Image", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Image = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ImageReviewSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageReviewSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageReviewSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Containers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Containers = append(m.Containers, ImageReviewContainerSpec{}) + if err := m.Containers[len(m.Containers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Annotations == nil { + m.Annotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Annotations[mapkey] = mapvalue + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ImageReviewStatus) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageReviewStatus: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageReviewStatus: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Allowed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Allowed = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AuditAnnotations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AuditAnnotations == nil { + m.AuditAnnotations = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthGenerated + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.AuditAnnotations[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenerated(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenerated + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthGenerated + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenerated + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipGenerated(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthGenerated + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") +) diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto new file mode 100644 index 000000000..381d0091b --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/generated.proto @@ -0,0 +1,86 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +// This file was autogenerated by go-to-protobuf. Do not edit it manually! + +syntax = 'proto2'; + +package k8s.io.api.imagepolicy.v1alpha1; + +import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/generated.proto"; +import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; + +// Package-wide variables from generator "generated". +option go_package = "v1alpha1"; + +// ImageReview checks if the set of images in a pod are allowed. +message ImageReview { + // +optional + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec holds information about the pod being evaluated + optional ImageReviewSpec spec = 2; + + // Status is filled in by the backend and indicates whether the pod should be allowed. + // +optional + optional ImageReviewStatus status = 3; +} + +// ImageReviewContainerSpec is a description of a container within the pod creation request. +message ImageReviewContainerSpec { + // This can be in the form image:tag or image@SHA:012345679abcdef. + // +optional + optional string image = 1; +} + +// ImageReviewSpec is a description of the pod creation request. +message ImageReviewSpec { + // Containers is a list of a subset of the information in each container of the Pod being created. + // +optional + repeated ImageReviewContainerSpec containers = 1; + + // Annotations is a list of key-value pairs extracted from the Pod's annotations. + // It only includes keys which match the pattern `*.image-policy.k8s.io/*`. + // It is up to each webhook backend to determine how to interpret these annotations, if at all. + // +optional + map annotations = 2; + + // Namespace is the namespace the pod is being created in. + // +optional + optional string namespace = 3; +} + +// ImageReviewStatus is the result of the review for the pod creation request. +message ImageReviewStatus { + // Allowed indicates that all images were allowed to be run. + optional bool allowed = 1; + + // Reason should be empty unless Allowed is false in which case it + // may contain a short description of what is wrong. Kubernetes + // may truncate excessively long errors when displaying to the user. + // +optional + optional string reason = 2; + + // AuditAnnotations will be added to the attributes object of the + // admission controller request using 'AddAnnotation'. The keys should + // be prefix-less (i.e., the admission controller will add an + // appropriate prefix). + // +optional + map auditAnnotations = 3; +} + diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/register.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/register.go new file mode 100644 index 000000000..477571bbb --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/register.go @@ -0,0 +1,51 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name for this API. +const GroupName = "imagepolicy.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ImageReview{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/types.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/types.go new file mode 100644 index 000000000..fd689e638 --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/types.go @@ -0,0 +1,80 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +genclient:noVerbs +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ImageReview checks if the set of images in a pod are allowed. +type ImageReview struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec holds information about the pod being evaluated + Spec ImageReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` + + // Status is filled in by the backend and indicates whether the pod should be allowed. + // +optional + Status ImageReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// ImageReviewSpec is a description of the pod creation request. +type ImageReviewSpec struct { + // Containers is a list of a subset of the information in each container of the Pod being created. + // +optional + Containers []ImageReviewContainerSpec `json:"containers,omitempty" protobuf:"bytes,1,rep,name=containers"` + // Annotations is a list of key-value pairs extracted from the Pod's annotations. + // It only includes keys which match the pattern `*.image-policy.k8s.io/*`. + // It is up to each webhook backend to determine how to interpret these annotations, if at all. + // +optional + Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,2,rep,name=annotations"` + // Namespace is the namespace the pod is being created in. + // +optional + Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"` +} + +// ImageReviewContainerSpec is a description of a container within the pod creation request. +type ImageReviewContainerSpec struct { + // This can be in the form image:tag or image@SHA:012345679abcdef. + // +optional + Image string `json:"image,omitempty" protobuf:"bytes,1,opt,name=image"` + // In future, we may add command line overrides, exec health check command lines, and so on. +} + +// ImageReviewStatus is the result of the review for the pod creation request. +type ImageReviewStatus struct { + // Allowed indicates that all images were allowed to be run. + Allowed bool `json:"allowed" protobuf:"varint,1,opt,name=allowed"` + // Reason should be empty unless Allowed is false in which case it + // may contain a short description of what is wrong. Kubernetes + // may truncate excessively long errors when displaying to the user. + // +optional + Reason string `json:"reason,omitempty" protobuf:"bytes,2,opt,name=reason"` + // AuditAnnotations will be added to the attributes object of the + // admission controller request using 'AddAnnotation'. The keys should + // be prefix-less (i.e., the admission controller will add an + // appropriate prefix). + // +optional + AuditAnnotations map[string]string `json:"auditAnnotations,omitempty" protobuf:"bytes,3,rep,name=auditAnnotations"` +} diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go new file mode 100644 index 000000000..0211d94af --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/types_swagger_doc_generated.go @@ -0,0 +1,71 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-generated-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. +var map_ImageReview = map[string]string{ + "": "ImageReview checks if the set of images in a pod are allowed.", + "spec": "Spec holds information about the pod being evaluated", + "status": "Status is filled in by the backend and indicates whether the pod should be allowed.", +} + +func (ImageReview) SwaggerDoc() map[string]string { + return map_ImageReview +} + +var map_ImageReviewContainerSpec = map[string]string{ + "": "ImageReviewContainerSpec is a description of a container within the pod creation request.", + "image": "This can be in the form image:tag or image@SHA:012345679abcdef.", +} + +func (ImageReviewContainerSpec) SwaggerDoc() map[string]string { + return map_ImageReviewContainerSpec +} + +var map_ImageReviewSpec = map[string]string{ + "": "ImageReviewSpec is a description of the pod creation request.", + "containers": "Containers is a list of a subset of the information in each container of the Pod being created.", + "annotations": "Annotations is a list of key-value pairs extracted from the Pod's annotations. It only includes keys which match the pattern `*.image-policy.k8s.io/*`. It is up to each webhook backend to determine how to interpret these annotations, if at all.", + "namespace": "Namespace is the namespace the pod is being created in.", +} + +func (ImageReviewSpec) SwaggerDoc() map[string]string { + return map_ImageReviewSpec +} + +var map_ImageReviewStatus = map[string]string{ + "": "ImageReviewStatus is the result of the review for the pod creation request.", + "allowed": "Allowed indicates that all images were allowed to be run.", + "reason": "Reason should be empty unless Allowed is false in which case it may contain a short description of what is wrong. Kubernetes may truncate excessively long errors when displaying to the user.", + "auditAnnotations": "AuditAnnotations will be added to the attributes object of the admission controller request using 'AddAnnotation'. The keys should be prefix-less (i.e., the admission controller will add an appropriate prefix).", +} + +func (ImageReviewStatus) SwaggerDoc() map[string]string { + return map_ImageReviewStatus +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go b/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..83d47b791 --- /dev/null +++ b/vendor/k8s.io/api/imagepolicy/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,120 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageReview) DeepCopyInto(out *ImageReview) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReview. +func (in *ImageReview) DeepCopy() *ImageReview { + if in == nil { + return nil + } + out := new(ImageReview) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImageReview) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageReviewContainerSpec) DeepCopyInto(out *ImageReviewContainerSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewContainerSpec. +func (in *ImageReviewContainerSpec) DeepCopy() *ImageReviewContainerSpec { + if in == nil { + return nil + } + out := new(ImageReviewContainerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageReviewSpec) DeepCopyInto(out *ImageReviewSpec) { + *out = *in + if in.Containers != nil { + in, out := &in.Containers, &out.Containers + *out = make([]ImageReviewContainerSpec, len(*in)) + copy(*out, *in) + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewSpec. +func (in *ImageReviewSpec) DeepCopy() *ImageReviewSpec { + if in == nil { + return nil + } + out := new(ImageReviewSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageReviewStatus) DeepCopyInto(out *ImageReviewStatus) { + *out = *in + if in.AuditAnnotations != nil { + in, out := &in.AuditAnnotations, &out.AuditAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewStatus. +func (in *ImageReviewStatus) DeepCopy() *ImageReviewStatus { + if in == nil { + return nil + } + out := new(ImageReviewStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go new file mode 100644 index 000000000..3d7b6f05b --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme/scheme.go @@ -0,0 +1,133 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package unstructuredscheme + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/json" + "k8s.io/apimachinery/pkg/runtime/serializer/versioning" +) + +var ( + scheme = runtime.NewScheme() + codecs = serializer.NewCodecFactory(scheme) +) + +// NewUnstructuredNegotiatedSerializer returns a simple, negotiated serializer +func NewUnstructuredNegotiatedSerializer() runtime.NegotiatedSerializer { + return unstructuredNegotiatedSerializer{ + scheme: scheme, + typer: NewUnstructuredObjectTyper(), + creator: NewUnstructuredCreator(), + } +} + +type unstructuredNegotiatedSerializer struct { + scheme *runtime.Scheme + typer runtime.ObjectTyper + creator runtime.ObjectCreater +} + +func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { + return []runtime.SerializerInfo{ + { + MediaType: "application/json", + MediaTypeType: "application", + MediaTypeSubType: "json", + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, true), + StreamSerializer: &runtime.StreamSerializerInfo{ + EncodesAsText: true, + Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false), + Framer: json.Framer, + }, + }, + { + MediaType: "application/yaml", + MediaTypeType: "application", + MediaTypeSubType: "yaml", + EncodesAsText: true, + Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, s.creator, s.typer), + }, + } +} + +func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, encoder, nil, gv, nil) +} + +func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { + return versioning.NewDefaultingCodecForScheme(s.scheme, nil, decoder, nil, gv) +} + +type unstructuredObjectTyper struct { +} + +// NewUnstructuredObjectTyper returns an object typer that can deal with unstructured things +func NewUnstructuredObjectTyper() runtime.ObjectTyper { + return unstructuredObjectTyper{} +} + +func (t unstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { + // Delegate for things other than Unstructured. + if _, ok := obj.(runtime.Unstructured); !ok { + return nil, false, fmt.Errorf("cannot type %T", obj) + } + gvk := obj.GetObjectKind().GroupVersionKind() + if len(gvk.Kind) == 0 { + return nil, false, runtime.NewMissingKindErr("object has no kind field ") + } + if len(gvk.Version) == 0 { + return nil, false, runtime.NewMissingVersionErr("object has no apiVersion field") + } + + return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil +} + +func (t unstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool { + return true +} + +type unstructuredCreator struct{} + +// NewUnstructuredCreator returns a simple object creator that always returns an unstructured +func NewUnstructuredCreator() runtime.ObjectCreater { + return unstructuredCreator{} +} + +func (c unstructuredCreator) New(kind schema.GroupVersionKind) (runtime.Object, error) { + ret := &unstructured.Unstructured{} + ret.SetGroupVersionKind(kind) + return ret, nil +} + +type unstructuredDefaulter struct { +} + +// NewUnstructuredDefaulter returns defaulter suitable for unstructured types that doesn't default anything +func NewUnstructuredDefaulter() runtime.ObjectDefaulter { + return unstructuredDefaulter{} +} + +func (d unstructuredDefaulter) Default(in runtime.Object) { +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/duration/duration.go b/vendor/k8s.io/apimachinery/pkg/util/duration/duration.go new file mode 100644 index 000000000..961ec5ed8 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/duration/duration.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package duration + +import ( + "fmt" + "time" +) + +// ShortHumanDuration returns a succint representation of the provided duration +// with limited precision for consumption by humans. +func ShortHumanDuration(d time.Duration) string { + // Allow deviation no more than 2 seconds(excluded) to tolerate machine time + // inconsistence, it can be considered as almost now. + if seconds := int(d.Seconds()); seconds < -1 { + return fmt.Sprintf("") + } else if seconds < 0 { + return fmt.Sprintf("0s") + } else if seconds < 60 { + return fmt.Sprintf("%ds", seconds) + } else if minutes := int(d.Minutes()); minutes < 60 { + return fmt.Sprintf("%dm", minutes) + } else if hours := int(d.Hours()); hours < 24 { + return fmt.Sprintf("%dh", hours) + } else if hours < 24*365 { + return fmt.Sprintf("%dd", hours/24) + } + return fmt.Sprintf("%dy", int(d.Hours()/24/365)) +} + +// HumanDuration returns a succint representation of the provided duration +// with limited precision for consumption by humans. It provides ~2-3 significant +// figures of duration. +func HumanDuration(d time.Duration) string { + // Allow deviation no more than 2 seconds(excluded) to tolerate machine time + // inconsistence, it can be considered as almost now. + if seconds := int(d.Seconds()); seconds < -1 { + return fmt.Sprintf("") + } else if seconds < 0 { + return fmt.Sprintf("0s") + } else if seconds < 60*2 { + return fmt.Sprintf("%ds", seconds) + } + minutes := int(d / time.Minute) + if minutes < 10 { + s := int(d/time.Second) % 60 + if s == 0 { + return fmt.Sprintf("%dm", minutes) + } + return fmt.Sprintf("%dm%ds", minutes, s) + } else if minutes < 60*3 { + return fmt.Sprintf("%dm", minutes) + } + hours := int(d / time.Hour) + if hours < 8 { + m := int(d/time.Minute) % 60 + if m == 0 { + return fmt.Sprintf("%dh", hours) + } + return fmt.Sprintf("%dh%dm", hours, m) + } else if hours < 48 { + return fmt.Sprintf("%dh", hours) + } else if hours < 24*8 { + h := hours % 24 + if h == 0 { + return fmt.Sprintf("%dd", hours/24) + } + return fmt.Sprintf("%dd%dh", hours/24, h) + } else if hours < 24*365*2 { + return fmt.Sprintf("%dd", hours/24) + } else if hours < 24*365*8 { + return fmt.Sprintf("%dy%dd", hours/24/365, (hours/24)%365) + } + return fmt.Sprintf("%dy", int(hours/24/365)) +} diff --git a/vendor/k8s.io/cli-runtime/LICENSE b/vendor/k8s.io/cli-runtime/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go new file mode 100644 index 000000000..f695fb5f9 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags.go @@ -0,0 +1,220 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/resource" +) + +// ResourceBuilderFlags are flags for finding resources +// TODO(juanvallejo): wire --local flag from commands through +type ResourceBuilderFlags struct { + FileNameFlags *FileNameFlags + + LabelSelector *string + FieldSelector *string + AllNamespaces *bool + All *bool + Local *bool + + Scheme *runtime.Scheme + Latest bool + StopOnFirstError bool +} + +// NewResourceBuilderFlags returns a default ResourceBuilderFlags +func NewResourceBuilderFlags() *ResourceBuilderFlags { + filenames := []string{} + + return &ResourceBuilderFlags{ + FileNameFlags: &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &filenames, + Recursive: boolPtr(true), + }, + } +} + +func (o *ResourceBuilderFlags) WithFile(recurse bool, files ...string) *ResourceBuilderFlags { + o.FileNameFlags = &FileNameFlags{ + Usage: "identifying the resource.", + Filenames: &files, + Recursive: boolPtr(recurse), + } + + return o +} + +func (o *ResourceBuilderFlags) WithLabelSelector(selector string) *ResourceBuilderFlags { + o.LabelSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithFieldSelector(selector string) *ResourceBuilderFlags { + o.FieldSelector = &selector + return o +} + +func (o *ResourceBuilderFlags) WithAllNamespaces(defaultVal bool) *ResourceBuilderFlags { + o.AllNamespaces = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithAll(defaultVal bool) *ResourceBuilderFlags { + o.All = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithLocal(defaultVal bool) *ResourceBuilderFlags { + o.Local = &defaultVal + return o +} + +func (o *ResourceBuilderFlags) WithScheme(scheme *runtime.Scheme) *ResourceBuilderFlags { + o.Scheme = scheme + return o +} + +func (o *ResourceBuilderFlags) WithLatest() *ResourceBuilderFlags { + o.Latest = true + return o +} + +func (o *ResourceBuilderFlags) StopOnError() *ResourceBuilderFlags { + o.StopOnFirstError = true + return o +} + +// AddFlags registers flags for finding resources +func (o *ResourceBuilderFlags) AddFlags(flagset *pflag.FlagSet) { + o.FileNameFlags.AddFlags(flagset) + + if o.LabelSelector != nil { + flagset.StringVarP(o.LabelSelector, "selector", "l", *o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + } + if o.FieldSelector != nil { + flagset.StringVar(o.FieldSelector, "field-selector", *o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + } + if o.AllNamespaces != nil { + flagset.BoolVarP(o.AllNamespaces, "all-namespaces", "A", *o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + } + if o.All != nil { + flagset.BoolVar(o.All, "all", *o.All, "Select all resources in the namespace of the specified resource types") + } + if o.Local != nil { + flagset.BoolVar(o.Local, "local", *o.Local, "If true, annotation will NOT contact api-server but run locally.") + } +} + +// ToBuilder gives you back a resource finder to visit resources that are located +func (o *ResourceBuilderFlags) ToBuilder(restClientGetter RESTClientGetter, resources []string) ResourceFinder { + namespace, enforceNamespace, namespaceErr := restClientGetter.ToRawKubeConfigLoader().Namespace() + + builder := resource.NewBuilder(restClientGetter). + NamespaceParam(namespace).DefaultNamespace() + + if o.AllNamespaces != nil { + builder.AllNamespaces(*o.AllNamespaces) + } + + if o.Scheme != nil { + builder.WithScheme(o.Scheme, o.Scheme.PrioritizedVersionsAllGroups()...) + } else { + builder.Unstructured() + } + + if o.FileNameFlags != nil { + opts := o.FileNameFlags.ToOptions() + builder.FilenameParam(enforceNamespace, &opts) + } + + if o.Local == nil || !*o.Local { + // resource type/name tuples only work non-local + if o.All != nil { + builder.ResourceTypeOrNameArgs(*o.All, resources...) + } else { + builder.ResourceTypeOrNameArgs(false, resources...) + } + // label selectors only work non-local (for now) + if o.LabelSelector != nil { + builder.LabelSelectorParam(*o.LabelSelector) + } + // field selectors only work non-local (forever) + if o.FieldSelector != nil { + builder.FieldSelectorParam(*o.FieldSelector) + } + // latest only works non-local (forever) + if o.Latest { + builder.Latest() + } + + } else { + builder.Local() + + if len(resources) > 0 { + builder.AddError(resource.LocalResourceError) + } + } + + if !o.StopOnFirstError { + builder.ContinueOnError() + } + + return &ResourceFindBuilderWrapper{ + builder: builder. + Flatten(). // I think we're going to recommend this everywhere + AddError(namespaceErr), + } +} + +// ResourceFindBuilderWrapper wraps a builder in an interface +type ResourceFindBuilderWrapper struct { + builder *resource.Builder +} + +// Do finds you resources to check +func (b *ResourceFindBuilderWrapper) Do() resource.Visitor { + return b.builder.Do() +} + +// ResourceFinder allows mocking the resource builder +// TODO resource builders needs to become more interfacey +type ResourceFinder interface { + Do() resource.Visitor +} + +// ResourceFinderFunc is a handy way to make a ResourceFinder +type ResourceFinderFunc func() resource.Visitor + +// Do implements ResourceFinder +func (fn ResourceFinderFunc) Do() resource.Visitor { + return fn() +} + +// ResourceFinderForResult skins a visitor for re-use as a ResourceFinder +func ResourceFinderForResult(result resource.Visitor) ResourceFinder { + return ResourceFinderFunc(func() resource.Visitor { + return result + }) +} + +func boolPtr(val bool) *bool { + return &val +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags_fake.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags_fake.go new file mode 100644 index 000000000..310382919 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/builder_flags_fake.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "k8s.io/cli-runtime/pkg/resource" +) + +// NewSimpleResourceFinder builds a super simple ResourceFinder that just iterates over the objects you provided +func NewSimpleFakeResourceFinder(infos ...*resource.Info) ResourceFinder { + return &fakeResourceFinder{ + Infos: infos, + } +} + +type fakeResourceFinder struct { + Infos []*resource.Info +} + +// Do implements the interface +func (f *fakeResourceFinder) Do() resource.Visitor { + return &fakeResourceResult{ + Infos: f.Infos, + } +} + +type fakeResourceResult struct { + Infos []*resource.Info +} + +// Visit just iterates over info +func (r *fakeResourceResult) Visit(fn resource.VisitorFunc) error { + for _, info := range r.Infos { + err := fn(info, nil) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go new file mode 100644 index 000000000..34b1f8e3a --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go @@ -0,0 +1,357 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "os" + "path/filepath" + "regexp" + "strings" + "sync" + "time" + + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + diskcached "k8s.io/client-go/discovery/cached/disk" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" +) + +const ( + flagClusterName = "cluster" + flagAuthInfoName = "user" + flagContext = "context" + flagNamespace = "namespace" + flagAPIServer = "server" + flagInsecure = "insecure-skip-tls-verify" + flagCertFile = "client-certificate" + flagKeyFile = "client-key" + flagCAFile = "certificate-authority" + flagBearerToken = "token" + flagImpersonate = "as" + flagImpersonateGroup = "as-group" + flagUsername = "username" + flagPassword = "password" + flagTimeout = "request-timeout" + flagHTTPCacheDir = "cache-dir" +) + +var defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache") + +// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands +// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages +// as per the golang type overlapping. +type RESTClientGetter interface { + // ToRESTConfig returns restconfig + ToRESTConfig() (*rest.Config, error) + // ToDiscoveryClient returns discovery client + ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) + // ToRESTMapper returns a restmapper + ToRESTMapper() (meta.RESTMapper, error) + // ToRawKubeConfigLoader return kubeconfig loader as-is + ToRawKubeConfigLoader() clientcmd.ClientConfig +} + +var _ RESTClientGetter = &ConfigFlags{} + +// ConfigFlags composes the set of values necessary +// for obtaining a REST client config +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 + + clientConfig clientcmd.ClientConfig + lock sync.Mutex + // If set to true, will use persistent client config and + // propagate the config to the places that need it, rather than + // loading the config multiple times + usePersistentConfig bool +} + +// ToRESTConfig implements RESTClientGetter. +// Returns a REST client configuration based on a provided path +// to a .kubeconfig file, loading rules, and config flag overrides. +// Expects the AddFlags method to have been called. +func (f *ConfigFlags) ToRESTConfig() (*rest.Config, error) { + return f.ToRawKubeConfigLoader().ClientConfig() +} + +// ToRawKubeConfigLoader binds config flag values to config overrides +// Returns an interactive clientConfig if the password flag is enabled, +// or a non-interactive clientConfig otherwise. +func (f *ConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + if f.usePersistentConfig { + return f.toRawKubePersistentConfigLoader() + } + return f.toRawKubeConfigLoader() +} + +func (f *ConfigFlags) toRawKubeConfigLoader() clientcmd.ClientConfig { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + // use the standard defaults for this client command + // DEPRECATED: remove and replace with something more accurate + loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig + + if f.KubeConfig != nil { + loadingRules.ExplicitPath = *f.KubeConfig + } + + overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults} + + // bind auth info flag values to overrides + if f.CertFile != nil { + overrides.AuthInfo.ClientCertificate = *f.CertFile + } + if f.KeyFile != nil { + overrides.AuthInfo.ClientKey = *f.KeyFile + } + if f.BearerToken != nil { + overrides.AuthInfo.Token = *f.BearerToken + } + if f.Impersonate != nil { + overrides.AuthInfo.Impersonate = *f.Impersonate + } + if f.ImpersonateGroup != nil { + overrides.AuthInfo.ImpersonateGroups = *f.ImpersonateGroup + } + if f.Username != nil { + overrides.AuthInfo.Username = *f.Username + } + if f.Password != nil { + overrides.AuthInfo.Password = *f.Password + } + + // bind cluster flags + if f.APIServer != nil { + overrides.ClusterInfo.Server = *f.APIServer + } + if f.CAFile != nil { + overrides.ClusterInfo.CertificateAuthority = *f.CAFile + } + if f.Insecure != nil { + overrides.ClusterInfo.InsecureSkipTLSVerify = *f.Insecure + } + + // bind context flags + if f.Context != nil { + overrides.CurrentContext = *f.Context + } + if f.ClusterName != nil { + overrides.Context.Cluster = *f.ClusterName + } + if f.AuthInfoName != nil { + overrides.Context.AuthInfo = *f.AuthInfoName + } + if f.Namespace != nil { + overrides.Context.Namespace = *f.Namespace + } + + if f.Timeout != nil { + overrides.Timeout = *f.Timeout + } + + var clientConfig clientcmd.ClientConfig + + // we only have an interactive prompt when a password is allowed + if f.Password == nil { + clientConfig = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides) + } else { + clientConfig = clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin) + } + + return clientConfig +} + +// toRawKubePersistentConfigLoader binds config flag values to config overrides +// Returns a persistent clientConfig for propagation. +func (f *ConfigFlags) toRawKubePersistentConfigLoader() clientcmd.ClientConfig { + f.lock.Lock() + defer f.lock.Unlock() + + if f.clientConfig == nil { + f.clientConfig = f.toRawKubeConfigLoader() + } + + return f.clientConfig +} + +// ToDiscoveryClient implements RESTClientGetter. +// Expects the AddFlags method to have been called. +// Returns a CachedDiscoveryInterface using a computed RESTConfig. +func (f *ConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + config, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + + // The more groups you have, the more discovery requests you need to make. + // given 25 groups (our groups + a few custom resources) with one-ish version each, discovery needs to make 50 requests + // double it just so we don't end up here again for a while. This config is only used for discovery. + config.Burst = 100 + + // retrieve a user-provided value for the "cache-dir" + // defaulting to ~/.kube/http-cache if no user-value is given. + httpCacheDir := defaultCacheDir + if f.CacheDir != nil { + httpCacheDir = *f.CacheDir + } + + discoveryCacheDir := computeDiscoverCacheDir(filepath.Join(homedir.HomeDir(), ".kube", "cache", "discovery"), config.Host) + return diskcached.NewCachedDiscoveryClientForConfig(config, discoveryCacheDir, httpCacheDir, time.Duration(10*time.Minute)) +} + +// ToRESTMapper returns a mapper. +func (f *ConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + discoveryClient, err := f.ToDiscoveryClient() + if err != nil { + return nil, err + } + + mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, discoveryClient) + return expander, nil +} + +// AddFlags binds client configuration flags to a given flagset +func (f *ConfigFlags) AddFlags(flags *pflag.FlagSet) { + if f.KubeConfig != nil { + flags.StringVar(f.KubeConfig, "kubeconfig", *f.KubeConfig, "Path to the kubeconfig file to use for CLI requests.") + } + if f.CacheDir != nil { + flags.StringVar(f.CacheDir, flagHTTPCacheDir, *f.CacheDir, "Default HTTP cache directory") + } + + // add config options + if f.CertFile != nil { + flags.StringVar(f.CertFile, flagCertFile, *f.CertFile, "Path to a client certificate file for TLS") + } + if f.KeyFile != nil { + flags.StringVar(f.KeyFile, flagKeyFile, *f.KeyFile, "Path to a client key file for TLS") + } + if f.BearerToken != nil { + flags.StringVar(f.BearerToken, flagBearerToken, *f.BearerToken, "Bearer token for authentication to the API server") + } + if f.Impersonate != nil { + flags.StringVar(f.Impersonate, flagImpersonate, *f.Impersonate, "Username to impersonate for the operation") + } + if f.ImpersonateGroup != nil { + flags.StringArrayVar(f.ImpersonateGroup, flagImpersonateGroup, *f.ImpersonateGroup, "Group to impersonate for the operation, this flag can be repeated to specify multiple groups.") + } + if f.Username != nil { + flags.StringVar(f.Username, flagUsername, *f.Username, "Username for basic authentication to the API server") + } + if f.Password != nil { + flags.StringVar(f.Password, flagPassword, *f.Password, "Password for basic authentication to the API server") + } + if f.ClusterName != nil { + flags.StringVar(f.ClusterName, flagClusterName, *f.ClusterName, "The name of the kubeconfig cluster to use") + } + if f.AuthInfoName != nil { + flags.StringVar(f.AuthInfoName, flagAuthInfoName, *f.AuthInfoName, "The name of the kubeconfig user to use") + } + if f.Namespace != nil { + flags.StringVarP(f.Namespace, flagNamespace, "n", *f.Namespace, "If present, the namespace scope for this CLI request") + } + if f.Context != nil { + flags.StringVar(f.Context, flagContext, *f.Context, "The name of the kubeconfig context to use") + } + + if f.APIServer != nil { + flags.StringVarP(f.APIServer, flagAPIServer, "s", *f.APIServer, "The address and port of the Kubernetes API server") + } + if f.Insecure != nil { + flags.BoolVar(f.Insecure, flagInsecure, *f.Insecure, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure") + } + if f.CAFile != nil { + flags.StringVar(f.CAFile, flagCAFile, *f.CAFile, "Path to a cert file for the certificate authority") + } + if f.Timeout != nil { + flags.StringVar(f.Timeout, flagTimeout, *f.Timeout, "The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests.") + } + +} + +// WithDeprecatedPasswordFlag enables the username and password config flags +func (f *ConfigFlags) WithDeprecatedPasswordFlag() *ConfigFlags { + f.Username = stringptr("") + f.Password = stringptr("") + return f +} + +// NewConfigFlags returns ConfigFlags with default values set +func NewConfigFlags(usePersistentConfig bool) *ConfigFlags { + impersonateGroup := []string{} + insecure := false + + return &ConfigFlags{ + Insecure: &insecure, + Timeout: stringptr("0"), + KubeConfig: stringptr(""), + + CacheDir: stringptr(defaultCacheDir), + ClusterName: stringptr(""), + AuthInfoName: stringptr(""), + Context: stringptr(""), + Namespace: stringptr(""), + APIServer: stringptr(""), + CertFile: stringptr(""), + KeyFile: stringptr(""), + CAFile: stringptr(""), + BearerToken: stringptr(""), + Impersonate: stringptr(""), + ImpersonateGroup: &impersonateGroup, + + usePersistentConfig: usePersistentConfig, + } +} + +func stringptr(val string) *string { + return &val +} + +// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive +var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`) + +// computeDiscoverCacheDir takes the parentDir and the host and comes up with a "usually non-colliding" name. +func computeDiscoverCacheDir(parentDir, host string) string { + // strip the optional scheme from host if its there: + schemelessHost := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1) + // now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived + safeHost := overlyCautiousIllegalFileCharacters.ReplaceAllString(schemelessHost, "_") + return filepath.Join(parentDir, safeHost) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags_fake.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags_fake.go new file mode 100644 index 000000000..64e9a6883 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/config_flags_fake.go @@ -0,0 +1,110 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +type TestConfigFlags struct { + clientConfig clientcmd.ClientConfig + discoveryClient discovery.CachedDiscoveryInterface + restMapper meta.RESTMapper +} + +func (f *TestConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + if f.clientConfig == nil { + panic("attempt to obtain a test RawKubeConfigLoader with no clientConfig specified") + } + return f.clientConfig +} + +func (f *TestConfigFlags) ToRESTConfig() (*rest.Config, error) { + return f.ToRawKubeConfigLoader().ClientConfig() +} + +func (f *TestConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + return f.discoveryClient, nil +} + +func (f *TestConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + if f.restMapper != nil { + return f.restMapper, nil + } + if f.discoveryClient != nil { + mapper := restmapper.NewDeferredDiscoveryRESTMapper(f.discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, f.discoveryClient) + return expander, nil + } + return nil, fmt.Errorf("no restmapper") +} + +func (f *TestConfigFlags) WithClientConfig(clientConfig clientcmd.ClientConfig) *TestConfigFlags { + f.clientConfig = clientConfig + return f +} + +func (f *TestConfigFlags) WithRESTMapper(mapper meta.RESTMapper) *TestConfigFlags { + f.restMapper = mapper + return f +} + +func (f *TestConfigFlags) WithDiscoveryClient(c discovery.CachedDiscoveryInterface) *TestConfigFlags { + f.discoveryClient = c + return f +} + +func (f *TestConfigFlags) WithNamespace(ns string) *TestConfigFlags { + if f.clientConfig == nil { + panic("attempt to obtain a test RawKubeConfigLoader with no clientConfig specified") + } + f.clientConfig = &namespacedClientConfig{ + delegate: f.clientConfig, + namespace: ns, + } + return f +} + +func NewTestConfigFlags() *TestConfigFlags { + return &TestConfigFlags{} +} + +type namespacedClientConfig struct { + delegate clientcmd.ClientConfig + namespace string +} + +func (c *namespacedClientConfig) Namespace() (string, bool, error) { + return c.namespace, false, nil +} + +func (c *namespacedClientConfig) RawConfig() (clientcmdapi.Config, error) { + return c.delegate.RawConfig() +} +func (c *namespacedClientConfig) ClientConfig() (*rest.Config, error) { + return c.delegate.ClientConfig() +} +func (c *namespacedClientConfig) ConfigAccess() clientcmd.ConfigAccess { + return c.delegate.ConfigAccess() +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/doc.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/doc.go new file mode 100644 index 000000000..4796a8a44 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package genericclioptions contains flags which can be added to you command, bound, completed, and produce +// useful helper functions. Nothing in this package can depend on kube/kube +package genericclioptions // import "k8s.io/cli-runtime/pkg/genericclioptions" diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/filename_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/filename_flags.go new file mode 100644 index 000000000..09e7b5bed --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/filename_flags.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/cli-runtime/pkg/resource" +) + +// Usage of this struct by itself is discouraged. +// These flags are composed by ResourceBuilderFlags +// which should be used instead. +type FileNameFlags struct { + Usage string + + Filenames *[]string + Kustomize *string + Recursive *bool +} + +func (o *FileNameFlags) ToOptions() resource.FilenameOptions { + options := resource.FilenameOptions{} + + if o == nil { + return options + } + + if o.Recursive != nil { + options.Recursive = *o.Recursive + } + if o.Filenames != nil { + options.Filenames = *o.Filenames + } + if o.Kustomize != nil { + options.Kustomize = *o.Kustomize + } + + return options +} + +func (o *FileNameFlags) AddFlags(flags *pflag.FlagSet) { + if o == nil { + return + } + + if o.Recursive != nil { + flags.BoolVarP(o.Recursive, "recursive", "R", *o.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") + } + if o.Filenames != nil { + flags.StringSliceVarP(o.Filenames, "filename", "f", *o.Filenames, o.Usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) + } + if o.Kustomize != nil { + flags.StringVarP(o.Kustomize, "kustomize", "k", *o.Kustomize, + "Process a kustomization directory. This flag can't be used together with -f or -R.") + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/io_options.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/io_options.go new file mode 100644 index 000000000..4fc3a77b0 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/io_options.go @@ -0,0 +1,57 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "bytes" + "io" + "io/ioutil" +) + +// IOStreams provides the standard names for iostreams. This is useful for embedding and for unit testing. +// Inconsistent and different names make it hard to read and review code +type IOStreams struct { + // In think, os.Stdin + In io.Reader + // Out think, os.Stdout + Out io.Writer + // ErrOut think, os.Stderr + ErrOut io.Writer +} + +// NewTestIOStreams returns a valid IOStreams and in, out, errout buffers for unit tests +func NewTestIOStreams() (IOStreams, *bytes.Buffer, *bytes.Buffer, *bytes.Buffer) { + in := &bytes.Buffer{} + out := &bytes.Buffer{} + errOut := &bytes.Buffer{} + + return IOStreams{ + In: in, + Out: out, + ErrOut: errOut, + }, in, out, errOut +} + +// NewTestIOStreamsDiscard returns a valid IOStreams that just discards +func NewTestIOStreamsDiscard() IOStreams { + in := &bytes.Buffer{} + return IOStreams{ + In: in, + Out: ioutil.Discard, + ErrOut: ioutil.Discard, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/json_yaml_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/json_yaml_flags.go new file mode 100644 index 000000000..a344eb0b6 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/json_yaml_flags.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "strings" + + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/printers" +) + +func (f *JSONYamlPrintFlags) AllowedFormats() []string { + if f == nil { + return []string{} + } + return []string{"json", "yaml"} +} + +// JSONYamlPrintFlags provides default flags necessary for json/yaml printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type JSONYamlPrintFlags struct { +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling --output=(yaml|json) printing. +// Returns false if the specified outputFormat does not match a supported format. +// Supported Format types can be found in pkg/printers/printers.go +func (f *JSONYamlPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + var printer printers.ResourcePrinter + + outputFormat = strings.ToLower(outputFormat) + switch outputFormat { + case "json": + printer = &printers.JSONPrinter{} + case "yaml": + printer = &printers.YAMLPrinter{} + default: + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} + } + + return printer, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to JSON or Yaml printing to it +func (f *JSONYamlPrintFlags) AddFlags(c *cobra.Command) {} + +// NewJSONYamlPrintFlags returns flags associated with +// yaml or json printing, with default values set. +func NewJSONYamlPrintFlags() *JSONYamlPrintFlags { + return &JSONYamlPrintFlags{} +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/jsonpath_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/jsonpath_flags.go new file mode 100644 index 000000000..0ebd6a649 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/jsonpath_flags.go @@ -0,0 +1,130 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "fmt" + "io/ioutil" + "sort" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/printers" +) + +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=jsonpath= +var jsonFormats = map[string]bool{ + "jsonpath": true, + "jsonpath-file": true, +} + +// JSONPathPrintFlags provides default flags necessary for template printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type JSONPathPrintFlags struct { + // indicates if it is OK to ignore missing keys for rendering + // an output template. + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *JSONPathPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(jsonFormats)) + for format := range jsonFormats { + formats = append(formats, format) + } + sort.Strings(formats) + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling --template format printing. +// Returns false if the specified templateFormat does not match a template format. +func (f *JSONPathPrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) { + if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { + return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + } + + templateValue := "" + + if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { + for format := range jsonFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = *f.TemplateArgument + } + + if _, supportedFormat := jsonFormats[templateFormat]; !supportedFormat { + return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("template format specified but no template given") + } + + if templateFormat == "jsonpath-file" { + data, err := ioutil.ReadFile(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) + } + + templateValue = string(data) + } + + p, err := printers.NewJSONPathPrinter(templateValue) + if err != nil { + return nil, fmt.Errorf("error parsing jsonpath %s, %v\n", templateValue, err) + } + + allowMissingKeys := true + if f.AllowMissingKeys != nil { + allowMissingKeys = *f.AllowMissingKeys + } + + p.AllowMissingKeys(allowMissingKeys) + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *JSONPathPrintFlags) AddFlags(c *cobra.Command) { + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when --output=jsonpath, --output=jsonpath-file.") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewJSONPathPrintFlags returns flags associated with +// --template printing, with default values set. +func NewJSONPathPrintFlags(templateValue string, allowMissingKeys bool) *JSONPathPrintFlags { + return &JSONPathPrintFlags{ + TemplateArgument: &templateValue, + AllowMissingKeys: &allowMissingKeys, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/kube_template_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/kube_template_flags.go new file mode 100644 index 000000000..df2b58c1c --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/kube_template_flags.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/printers" +) + +// KubeTemplatePrintFlags composes print flags that provide both a JSONPath and a go-template printer. +// This is necessary if dealing with cases that require support both both printers, since both sets of flags +// require overlapping flags. +type KubeTemplatePrintFlags struct { + GoTemplatePrintFlags *GoTemplatePrintFlags + JSONPathPrintFlags *JSONPathPrintFlags + + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *KubeTemplatePrintFlags) AllowedFormats() []string { + if f == nil { + return []string{} + } + return append(f.GoTemplatePrintFlags.AllowedFormats(), f.JSONPathPrintFlags.AllowedFormats()...) +} + +func (f *KubeTemplatePrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + if f == nil { + return nil, NoCompatiblePrinterError{} + } + + if p, err := f.JSONPathPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return p, err + } + return f.GoTemplatePrintFlags.ToPrinter(outputFormat) +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *KubeTemplatePrintFlags) AddFlags(c *cobra.Command) { + if f == nil { + return + } + + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewKubeTemplatePrintFlags returns flags associated with +// --template printing, with default values set. +func NewKubeTemplatePrintFlags() *KubeTemplatePrintFlags { + allowMissingKeysPtr := true + templateArgPtr := "" + + return &KubeTemplatePrintFlags{ + GoTemplatePrintFlags: &GoTemplatePrintFlags{ + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + }, + JSONPathPrintFlags: &JSONPathPrintFlags{ + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + }, + + TemplateArgument: &templateArgPtr, + AllowMissingKeys: &allowMissingKeysPtr, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/name_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/name_flags.go new file mode 100644 index 000000000..7aa89ab05 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/name_flags.go @@ -0,0 +1,81 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/printers" +) + +// NamePrintFlags provides default flags necessary for printing +// a resource's fully-qualified Kind.group/name, or a successful +// message about that resource if an Operation is provided. +type NamePrintFlags struct { + // Operation describes the name of the action that + // took place on an object, to be included in the + // finalized "successful" message. + Operation string +} + +func (f *NamePrintFlags) Complete(successTemplate string) error { + f.Operation = fmt.Sprintf(successTemplate, f.Operation) + return nil +} + +func (f *NamePrintFlags) AllowedFormats() []string { + if f == nil { + return []string{} + } + return []string{"name"} +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling --output=name printing. +// Returns false if the specified outputFormat does not match a supported format. +// Supported format types can be found in pkg/printers/printers.go +func (f *NamePrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + namePrinter := &printers.NamePrinter{ + Operation: f.Operation, + } + + outputFormat = strings.ToLower(outputFormat) + switch outputFormat { + case "name": + namePrinter.ShortOutput = true + fallthrough + case "": + return namePrinter, nil + default: + return nil, NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} + } +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to name printing to it +func (f *NamePrintFlags) AddFlags(c *cobra.Command) {} + +// NewNamePrintFlags returns flags associated with +// --name printing, with default values set. +func NewNamePrintFlags(operation string) *NamePrintFlags { + return &NamePrintFlags{ + Operation: operation, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/print_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/print_flags.go new file mode 100644 index 000000000..17b05c8cd --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/print_flags.go @@ -0,0 +1,158 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "fmt" + "sort" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" +) + +type NoCompatiblePrinterError struct { + OutputFormat *string + AllowedFormats []string + Options interface{} +} + +func (e NoCompatiblePrinterError) Error() string { + output := "" + if e.OutputFormat != nil { + output = *e.OutputFormat + } + + sort.Strings(e.AllowedFormats) + return fmt.Sprintf("unable to match a printer suitable for the output format %q, allowed formats are: %s", output, strings.Join(e.AllowedFormats, ",")) +} + +func IsNoCompatiblePrinterError(err error) bool { + if err == nil { + return false + } + + _, ok := err.(NoCompatiblePrinterError) + return ok +} + +// PrintFlags composes common printer flag structs +// used across all commands, and provides a method +// of retrieving a known printer based on flag values provided. +type PrintFlags struct { + JSONYamlPrintFlags *JSONYamlPrintFlags + NamePrintFlags *NamePrintFlags + TemplatePrinterFlags *KubeTemplatePrintFlags + + TypeSetterPrinter *printers.TypeSetterPrinter + + OutputFormat *string + + // OutputFlagSpecified indicates whether the user specifically requested a certain kind of output. + // Using this function allows a sophisticated caller to change the flag binding logic if they so desire. + OutputFlagSpecified func() bool +} + +func (f *PrintFlags) Complete(successTemplate string) error { + return f.NamePrintFlags.Complete(successTemplate) +} + +func (f *PrintFlags) AllowedFormats() []string { + ret := []string{} + ret = append(ret, f.JSONYamlPrintFlags.AllowedFormats()...) + ret = append(ret, f.NamePrintFlags.AllowedFormats()...) + ret = append(ret, f.TemplatePrinterFlags.AllowedFormats()...) + return ret +} + +func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { + outputFormat := "" + if f.OutputFormat != nil { + outputFormat = *f.OutputFormat + } + // For backwards compatibility we want to support a --template argument given, even when no --output format is provided. + // If no explicit output format has been provided via the --output flag, fallback + // to honoring the --template argument. + templateFlagSpecified := f.TemplatePrinterFlags != nil && + f.TemplatePrinterFlags.TemplateArgument != nil && + len(*f.TemplatePrinterFlags.TemplateArgument) > 0 + outputFlagSpecified := f.OutputFlagSpecified != nil && f.OutputFlagSpecified() + if templateFlagSpecified && !outputFlagSpecified { + outputFormat = "go-template" + } + + if f.JSONYamlPrintFlags != nil { + if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + if f.NamePrintFlags != nil { + if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + if f.TemplatePrinterFlags != nil { + if p, err := f.TemplatePrinterFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) { + return f.TypeSetterPrinter.WrapToPrinter(p, err) + } + } + + return nil, NoCompatiblePrinterError{OutputFormat: f.OutputFormat, AllowedFormats: f.AllowedFormats()} +} + +func (f *PrintFlags) AddFlags(cmd *cobra.Command) { + f.JSONYamlPrintFlags.AddFlags(cmd) + f.NamePrintFlags.AddFlags(cmd) + f.TemplatePrinterFlags.AddFlags(cmd) + + if f.OutputFormat != nil { + cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(f.AllowedFormats(), "|"))) + if f.OutputFlagSpecified == nil { + f.OutputFlagSpecified = func() bool { + return cmd.Flag("output").Changed + } + } + } +} + +// WithDefaultOutput sets a default output format if one is not provided through a flag value +func (f *PrintFlags) WithDefaultOutput(output string) *PrintFlags { + f.OutputFormat = &output + return f +} + +// WithTypeSetter sets a wrapper than will surround the returned printer with a printer to type resources +func (f *PrintFlags) WithTypeSetter(scheme *runtime.Scheme) *PrintFlags { + f.TypeSetterPrinter = printers.NewTypeSetter(scheme) + return f +} + +func NewPrintFlags(operation string) *PrintFlags { + outputFormat := "" + + return &PrintFlags{ + OutputFormat: &outputFormat, + + JSONYamlPrintFlags: NewJSONYamlPrintFlags(), + NamePrintFlags: NewNamePrintFlags(operation), + TemplatePrinterFlags: NewKubeTemplatePrintFlags(), + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go new file mode 100644 index 000000000..faf250d53 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/record_flags.go @@ -0,0 +1,199 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "os" + "path/filepath" + "strings" + + "github.com/evanphx/json-patch" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/json" +) + +// ChangeCauseAnnotation is the annotation indicating a guess at "why" something was changed +const ChangeCauseAnnotation = "kubernetes.io/change-cause" + +// RecordFlags contains all flags associated with the "--record" operation +type RecordFlags struct { + // Record indicates the state of the recording flag. It is a pointer so a caller can opt out or rebind + Record *bool + + changeCause string +} + +// ToRecorder returns a ChangeCause recorder if --record=false was not +// explicitly given by the user +func (f *RecordFlags) ToRecorder() (Recorder, error) { + if f == nil { + return NoopRecorder{}, nil + } + + shouldRecord := false + if f.Record != nil { + shouldRecord = *f.Record + } + + // if flag was explicitly set to false by the user, + // do not record + if !shouldRecord { + return NoopRecorder{}, nil + } + + return &ChangeCauseRecorder{ + changeCause: f.changeCause, + }, nil +} + +// Complete is called before the command is run, but after it is invoked to finish the state of the struct before use. +func (f *RecordFlags) Complete(cmd *cobra.Command) error { + if f == nil { + return nil + } + + f.changeCause = parseCommandArguments(cmd) + return nil +} + +func (f *RecordFlags) CompleteWithChangeCause(cause string) error { + if f == nil { + return nil + } + + f.changeCause = cause + return nil +} + +// AddFlags binds the requested flags to the provided flagset +// TODO have this only take a flagset +func (f *RecordFlags) AddFlags(cmd *cobra.Command) { + if f == nil { + return + } + + if f.Record != nil { + cmd.Flags().BoolVar(f.Record, "record", *f.Record, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.") + } +} + +// NewRecordFlags provides a RecordFlags with reasonable default values set for use +func NewRecordFlags() *RecordFlags { + record := false + + return &RecordFlags{ + Record: &record, + } +} + +// Recorder is used to record why a runtime.Object was changed in an annotation. +type Recorder interface { + // Record records why a runtime.Object was changed in an annotation. + Record(runtime.Object) error + MakeRecordMergePatch(runtime.Object) ([]byte, error) +} + +// NoopRecorder does nothing. It is a "do nothing" that can be returned so code doesn't switch on it. +type NoopRecorder struct{} + +// Record implements Recorder +func (r NoopRecorder) Record(obj runtime.Object) error { + return nil +} + +// MakeRecordMergePatch implements Recorder +func (r NoopRecorder) MakeRecordMergePatch(obj runtime.Object) ([]byte, error) { + return nil, nil +} + +// ChangeCauseRecorder annotates a "change-cause" to an input runtime object +type ChangeCauseRecorder struct { + changeCause string +} + +// Record annotates a "change-cause" to a given info if either "shouldRecord" is true, +// or the resource info previously contained a "change-cause" annotation. +func (r *ChangeCauseRecorder) Record(obj runtime.Object) error { + accessor, err := meta.Accessor(obj) + if err != nil { + return err + } + annotations := accessor.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[ChangeCauseAnnotation] = r.changeCause + accessor.SetAnnotations(annotations) + return nil +} + +// MakeRecordMergePatch produces a merge patch for updating the recording annotation. +func (r *ChangeCauseRecorder) MakeRecordMergePatch(obj runtime.Object) ([]byte, error) { + // copy so we don't mess with the original + objCopy := obj.DeepCopyObject() + if err := r.Record(objCopy); err != nil { + return nil, err + } + + oldData, err := json.Marshal(obj) + if err != nil { + return nil, err + } + newData, err := json.Marshal(objCopy) + if err != nil { + return nil, err + } + + return jsonpatch.CreateMergePatch(oldData, newData) +} + +// parseCommandArguments will stringify and return all environment arguments ie. a command run by a client +// using the factory. +// Set showSecrets false to filter out stuff like secrets. +func parseCommandArguments(cmd *cobra.Command) string { + if len(os.Args) == 0 { + return "" + } + + flags := "" + parseFunc := func(flag *pflag.Flag, value string) error { + flags = flags + " --" + flag.Name + if set, ok := flag.Annotations["classified"]; !ok || len(set) == 0 { + flags = flags + "=" + value + } else { + flags = flags + "=CLASSIFIED" + } + return nil + } + var err error + err = cmd.Flags().ParseAll(os.Args[1:], parseFunc) + if err != nil || !cmd.Flags().Parsed() { + return "" + } + + args := "" + if arguments := cmd.Flags().Args(); len(arguments) > 0 { + args = " " + strings.Join(arguments, " ") + } + + base := filepath.Base(os.Args[0]) + return base + args + flags +} diff --git a/vendor/k8s.io/cli-runtime/pkg/genericclioptions/template_flags.go b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/template_flags.go new file mode 100644 index 000000000..342912798 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/genericclioptions/template_flags.go @@ -0,0 +1,135 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package genericclioptions + +import ( + "fmt" + "io/ioutil" + "sort" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/printers" +) + +// templates are logically optional for specifying a format. +// this allows a user to specify a template format value +// as --output=go-template= +var templateFormats = map[string]bool{ + "template": true, + "go-template": true, + "go-template-file": true, + "templatefile": true, +} + +// GoTemplatePrintFlags provides default flags necessary for template printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type GoTemplatePrintFlags struct { + // indicates if it is OK to ignore missing keys for rendering + // an output template. + AllowMissingKeys *bool + TemplateArgument *string +} + +func (f *GoTemplatePrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(templateFormats)) + for format := range templateFormats { + formats = append(formats, format) + } + sort.Strings(formats) + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling --template format printing. +// Returns false if the specified templateFormat does not match a template format. +func (f *GoTemplatePrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) { + if (f.TemplateArgument == nil || len(*f.TemplateArgument) == 0) && len(templateFormat) == 0 { + return nil, NoCompatiblePrinterError{Options: f, OutputFormat: &templateFormat} + } + + templateValue := "" + + if f.TemplateArgument == nil || len(*f.TemplateArgument) == 0 { + for format := range templateFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = *f.TemplateArgument + } + + if _, supportedFormat := templateFormats[templateFormat]; !supportedFormat { + return nil, NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("template format specified but no template given") + } + + if templateFormat == "templatefile" || templateFormat == "go-template-file" { + data, err := ioutil.ReadFile(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading --template %s, %v\n", templateValue, err) + } + + templateValue = string(data) + } + + p, err := printers.NewGoTemplatePrinter([]byte(templateValue)) + if err != nil { + return nil, fmt.Errorf("error parsing template %s, %v\n", templateValue, err) + } + + allowMissingKeys := true + if f.AllowMissingKeys != nil { + allowMissingKeys = *f.AllowMissingKeys + } + + p.AllowMissingKeys(allowMissingKeys) + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to template printing to it +func (f *GoTemplatePrintFlags) AddFlags(c *cobra.Command) { + if f.TemplateArgument != nil { + c.Flags().StringVar(f.TemplateArgument, "template", *f.TemplateArgument, "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].") + c.MarkFlagFilename("template") + } + if f.AllowMissingKeys != nil { + c.Flags().BoolVar(f.AllowMissingKeys, "allow-missing-template-keys", *f.AllowMissingKeys, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.") + } +} + +// NewGoTemplatePrintFlags returns flags associated with +// --template printing, with default values set. +func NewGoTemplatePrintFlags() *GoTemplatePrintFlags { + allowMissingKeysPtr := true + templateValuePtr := "" + + return &GoTemplatePrintFlags{ + TemplateArgument: &templateValuePtr, + AllowMissingKeys: &allowMissingKeysPtr, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/builder.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/builder.go new file mode 100644 index 000000000..6aace7ce5 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/builder.go @@ -0,0 +1,32 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kustomize + +import ( + "io" + + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps" + "sigs.k8s.io/kustomize/pkg/commands/build" + "sigs.k8s.io/kustomize/pkg/fs" +) + +// RunKustomizeBuild runs kustomize build given a filesystem and a path +func RunKustomizeBuild(out io.Writer, fSys fs.FileSystem, path string) error { + f := k8sdeps.NewFactory() + o := build.NewOptions(path, "") + return o.RunBuild(out, fSys, f.ResmapF, f.TransformerF) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go new file mode 100644 index 000000000..9d40838ab --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/configmapfactory.go @@ -0,0 +1,125 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package configmapandsecret generates configmaps and secrets per generator rules. +package configmapandsecret + +import ( + "fmt" + "strings" + "unicode/utf8" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/types" +) + +// ConfigMapFactory makes ConfigMaps. +type ConfigMapFactory struct { + ldr ifc.Loader +} + +// NewConfigMapFactory returns a new ConfigMapFactory. +func NewConfigMapFactory(l ifc.Loader) *ConfigMapFactory { + return &ConfigMapFactory{ldr: l} +} + +func (f *ConfigMapFactory) makeFreshConfigMap( + args *types.ConfigMapArgs) *corev1.ConfigMap { + cm := &corev1.ConfigMap{} + cm.APIVersion = "v1" + cm.Kind = "ConfigMap" + cm.Name = args.Name + cm.Namespace = args.Namespace + cm.Data = map[string]string{} + return cm +} + +// MakeConfigMap returns a new ConfigMap, or nil and an error. +func (f *ConfigMapFactory) MakeConfigMap( + args *types.ConfigMapArgs, options *types.GeneratorOptions) (*corev1.ConfigMap, error) { + var all []kv.Pair + var err error + cm := f.makeFreshConfigMap(args) + + pairs, err := keyValuesFromEnvFile(f.ldr, args.EnvSource) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "env source file: %s", + args.EnvSource)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromLiteralSources(args.LiteralSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "literal sources %v", args.LiteralSources)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromFileSources(f.ldr, args.FileSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "file sources: %v", args.FileSources)) + } + all = append(all, pairs...) + + for _, p := range all { + err = addKvToConfigMap(cm, p.Key, p.Value) + if err != nil { + return nil, err + } + } + if options != nil { + cm.SetLabels(options.Labels) + cm.SetAnnotations(options.Annotations) + } + return cm, nil +} + +// addKvToConfigMap adds the given key and data to the given config map. +// Error if key invalid, or already exists. +func addKvToConfigMap(configMap *corev1.ConfigMap, keyName, data string) error { + // Note, the rules for ConfigMap keys are the exact same as the ones for SecretKeys. + if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 { + return fmt.Errorf("%q is not a valid key name for a ConfigMap: %s", keyName, strings.Join(errs, ";")) + } + + keyExistsErrorMsg := "cannot add key %s, another key by that name already exists: %v" + + // If the configmap data contains byte sequences that are all in the UTF-8 + // range, we will write it to .Data + if utf8.Valid([]byte(data)) { + if _, entryExists := configMap.Data[keyName]; entryExists { + return fmt.Errorf(keyExistsErrorMsg, keyName, configMap.Data) + } + configMap.Data[keyName] = data + return nil + } + + // otherwise, it's BinaryData + if configMap.BinaryData == nil { + configMap.BinaryData = map[string][]byte{} + } + if _, entryExists := configMap.BinaryData[keyName]; entryExists { + return fmt.Errorf(keyExistsErrorMsg, keyName, configMap.BinaryData) + } + configMap.BinaryData[keyName] = []byte(data) + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go new file mode 100644 index 000000000..893dfefc9 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/kv.go @@ -0,0 +1,107 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "fmt" + "path" + "strings" + + "github.com/pkg/errors" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +func keyValuesFromLiteralSources(sources []string) ([]kv.Pair, error) { + var kvs []kv.Pair + for _, s := range sources { + k, v, err := parseLiteralSource(s) + if err != nil { + return nil, err + } + kvs = append(kvs, kv.Pair{Key: k, Value: v}) + } + return kvs, nil +} + +func keyValuesFromFileSources(ldr ifc.Loader, sources []string) ([]kv.Pair, error) { + var kvs []kv.Pair + for _, s := range sources { + k, fPath, err := parseFileSource(s) + if err != nil { + return nil, err + } + content, err := ldr.Load(fPath) + if err != nil { + return nil, err + } + kvs = append(kvs, kv.Pair{Key: k, Value: string(content)}) + } + return kvs, nil +} + +func keyValuesFromEnvFile(l ifc.Loader, path string) ([]kv.Pair, error) { + if path == "" { + return nil, nil + } + content, err := l.Load(path) + if err != nil { + return nil, err + } + return kv.KeyValuesFromLines(content) +} + +// parseFileSource parses the source given. +// +// Acceptable formats include: +// 1. source-path: the basename will become the key name +// 2. source-name=source-path: the source-name will become the key name and +// source-path is the path to the key file. +// +// Key names cannot include '='. +func parseFileSource(source string) (keyName, filePath string, err error) { + numSeparators := strings.Count(source, "=") + switch { + case numSeparators == 0: + return path.Base(source), source, nil + case numSeparators == 1 && strings.HasPrefix(source, "="): + return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "=")) + case numSeparators == 1 && strings.HasSuffix(source, "="): + return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "=")) + case numSeparators > 1: + return "", "", errors.New("key names or file paths cannot contain '='") + default: + components := strings.Split(source, "=") + return components[0], components[1], nil + } +} + +// parseLiteralSource parses the source key=val pair into its component pieces. +// This functionality is distinguished from strings.SplitN(source, "=", 2) since +// it returns an error in the case of empty keys, values, or a missing equals sign. +func parseLiteralSource(source string) (keyName, value string, err error) { + // leading equal is invalid + if strings.Index(source, "=") == 0 { + return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source) + } + // split after the first equal (so values can have the = character) + items := strings.SplitN(source, "=", 2) + if len(items) != 2 { + return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source) + } + return items[0], strings.Trim(items[1], "\"'"), nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go new file mode 100644 index 000000000..97469f633 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret/secretfactory.go @@ -0,0 +1,106 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package configmapandsecret + +import ( + "fmt" + "strings" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/types" +) + +// SecretFactory makes Secrets. +type SecretFactory struct { + ldr ifc.Loader +} + +// NewSecretFactory returns a new SecretFactory. +func NewSecretFactory(ldr ifc.Loader) *SecretFactory { + return &SecretFactory{ldr: ldr} +} + +func (f *SecretFactory) makeFreshSecret(args *types.SecretArgs) *corev1.Secret { + s := &corev1.Secret{} + s.APIVersion = "v1" + s.Kind = "Secret" + s.Name = args.Name + s.Namespace = args.Namespace + s.Type = corev1.SecretType(args.Type) + if s.Type == "" { + s.Type = corev1.SecretTypeOpaque + } + s.Data = map[string][]byte{} + return s +} + +// MakeSecret returns a new secret. +func (f *SecretFactory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*corev1.Secret, error) { + var all []kv.Pair + var err error + s := f.makeFreshSecret(args) + + pairs, err := keyValuesFromEnvFile(f.ldr, args.EnvSource) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "env source file: %s", + args.EnvSource)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromLiteralSources(args.LiteralSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "literal sources %v", args.LiteralSources)) + } + all = append(all, pairs...) + + pairs, err = keyValuesFromFileSources(f.ldr, args.FileSources) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf( + "file sources: %v", args.FileSources)) + } + all = append(all, pairs...) + + for _, p := range all { + err = addKvToSecret(s, p.Key, p.Value) + if err != nil { + return nil, err + } + } + if options != nil { + s.SetLabels(options.Labels) + s.SetAnnotations(options.Annotations) + } + return s, nil +} + +func addKvToSecret(secret *corev1.Secret, keyName, data string) error { + // Note, the rules for SecretKeys keys are the exact same as the ones for ConfigMap. + if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 { + return fmt.Errorf("%q is not a valid key name for a Secret: %s", keyName, strings.Join(errs, ";")) + } + if _, entryExists := secret.Data[keyName]; entryExists { + return fmt.Errorf("cannot add key %s, another key by that name already exists", keyName) + } + secret.Data[keyName] = []byte(data) + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go new file mode 100644 index 000000000..c98cb8d68 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/doc.go @@ -0,0 +1,76 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// It's possible that kustomize's features will be vendored into +// the kubernetes/kubernetes repo and made available to kubectl +// commands, while at the same time the kustomize program will +// continue to exist as an independent CLI. Vendoring snapshots +// would be taken just before a kubectl release. +// +// This creates a problem in that freestanding-kustomize depends on +// (for example): +// +// https://github.com/kubernetes/apimachinery/ +// tree/master/pkg/util/yaml +// +// It vendors that package into +// sigs.k8s.io/kustomize/vendor/k8s.io/apimachinery/ +// +// Whereas kubectl-kustomize would have to depend on the "staging" +// version of this code, located at +// +// https://github.com/kubernetes/kubernetes/ +// blob/master/staging/src/k8s.io/apimachinery/pkg/util/yaml +// +// which is "vendored" via symlinks: +// k8s.io/kubernetes/vendor/k8s.io/apimachinery +// is a symlink to +// ../../staging/src/k8s.io/apimachinery +// +// The staging version is the canonical, under-development +// version of the code that kubectl depends on, whereas the packages +// at kubernetes/apimachinery are periodic snapshots of staging made +// for outside tools to depend on. +// +// apimachinery isn't the only package that poses this problem, just +// using it as a specific example. +// +// The kubectl binary cannot vendor in kustomize code that in +// turn vendors in the non-staging packages. +// +// One way to fix some of this would be to copy code - a hard fork. +// This has all the problems associated with a hard forking. +// +// Another way would be to break the kustomize repo into three: +// +// (1) kustomize - repo with the main() function, +// vendoring (2) and (3). +// +// (2) kustomize-libs - packages used by (1) with no +// apimachinery dependence. +// +// (3) kustomize-k8sdeps - A thin code layer that depends +// on (vendors) apimachinery to provide thin implementations +// to interfaces used in (2). +// +// The kubectl repo would then vendor from (2) only, and have +// a local implementation of (3). With that in mind, it's clear +// that (3) doesn't have to be a repo; the kustomize version of +// the thin layer can live directly in (1). +// +// This package is the code in (3), meant for kustomize. + +package k8sdeps diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go new file mode 100644 index 000000000..a83b4bdaa --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/factory.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package k8sdeps provides kustomize factory with k8s dependencies +package k8sdeps + +import ( + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator" + "sigs.k8s.io/kustomize/pkg/factory" +) + +// NewFactory creates an instance of KustFactory using k8sdeps factories +func NewFactory() *factory.KustFactory { + return factory.NewKustFactory( + kunstruct.NewKunstructuredFactoryImpl(), + validator.NewKustValidator(), + transformer.NewFactoryImpl(), + ) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go new file mode 100644 index 000000000..a1dec3169 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/factory.go @@ -0,0 +1,118 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kunstruct + +import ( + "bytes" + "fmt" + "io" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/types" +) + +// KunstructuredFactoryImpl hides construction using apimachinery types. +type KunstructuredFactoryImpl struct { + cmFactory *configmapandsecret.ConfigMapFactory + secretFactory *configmapandsecret.SecretFactory +} + +var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{} + +// NewKunstructuredFactoryImpl returns a factory. +func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory { + return &KunstructuredFactoryImpl{} +} + +// SliceFromBytes returns a slice of Kunstructured. +func (kf *KunstructuredFactoryImpl) SliceFromBytes( + in []byte) ([]ifc.Kunstructured, error) { + decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024) + var result []ifc.Kunstructured + var err error + for err == nil || isEmptyYamlError(err) { + var out unstructured.Unstructured + err = decoder.Decode(&out) + if err == nil { + if len(out.Object) == 0 { + continue + } + err = kf.validate(out) + if err != nil { + return nil, err + } + result = append(result, &UnstructAdapter{Unstructured: out}) + } + } + if err != io.EOF { + return nil, err + } + return result, nil +} + +func isEmptyYamlError(err error) bool { + return strings.Contains(err.Error(), "is missing in 'null'") +} + +// FromMap returns an instance of Kunstructured. +func (kf *KunstructuredFactoryImpl) FromMap( + m map[string]interface{}) ifc.Kunstructured { + return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}} +} + +// MakeConfigMap returns an instance of Kunstructured for ConfigMap +func (kf *KunstructuredFactoryImpl) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) { + cm, err := kf.cmFactory.MakeConfigMap(args, options) + if err != nil { + return nil, err + } + return NewKunstructuredFromObject(cm) +} + +// MakeSecret returns an instance of Kunstructured for Secret +func (kf *KunstructuredFactoryImpl) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) { + sec, err := kf.secretFactory.MakeSecret(args, options) + if err != nil { + return nil, err + } + return NewKunstructuredFromObject(sec) +} + +// Set sets loader +func (kf *KunstructuredFactoryImpl) Set(ldr ifc.Loader) { + kf.cmFactory = configmapandsecret.NewConfigMapFactory(ldr) + kf.secretFactory = configmapandsecret.NewSecretFactory(ldr) +} + +// validate validates that u has kind and name +// except for kind `List`, which doesn't require a name +func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error { + kind := u.GetKind() + if kind == "" { + return fmt.Errorf("missing kind in object %v", u) + } else if strings.HasSuffix(kind, "List") { + return nil + } + if u.GetName() == "" { + return fmt.Errorf("missing metadata.name in object %v", u) + } + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go new file mode 100644 index 000000000..0675b961d --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/helper.go @@ -0,0 +1,71 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package kunstruct provides unstructured from api machinery and factory for creating unstructured +package kunstruct + +import ( + "fmt" + "strings" +) + +func parseFields(path string) ([]string, error) { + if !strings.Contains(path, "[") { + return strings.Split(path, "."), nil + } + + var fields []string + start := 0 + insideParentheses := false + for i := range path { + switch path[i] { + case '.': + if !insideParentheses { + fields = append(fields, path[start:i]) + start = i + 1 + } + case '[': + if !insideParentheses { + if i == start { + start = i + 1 + } else { + fields = append(fields, path[start:i]) + start = i + 1 + } + insideParentheses = true + } else { + return nil, fmt.Errorf("nested parentheses are not allowed: %s", path) + } + case ']': + if insideParentheses { + fields = append(fields, path[start:i]) + start = i + 1 + insideParentheses = false + } else { + return nil, fmt.Errorf("invalid field path %s", path) + } + } + } + if start < len(path)-1 { + fields = append(fields, path[start:]) + } + for i, f := range fields { + if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") { + fields[i] = strings.Trim(f, "\"'") + } + } + return fields, nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go new file mode 100644 index 000000000..5ad306bf5 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct/kunstruct.go @@ -0,0 +1,92 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package kunstruct provides unstructured from api machinery and factory for creating unstructured +package kunstruct + +import ( + "encoding/json" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +var _ ifc.Kunstructured = &UnstructAdapter{} + +// UnstructAdapter wraps unstructured.Unstructured from +// https://github.com/kubernetes/apimachinery/blob/master/ +// pkg/apis/meta/v1/unstructured/unstructured.go +// to isolate dependence on apimachinery. +type UnstructAdapter struct { + unstructured.Unstructured +} + +// NewKunstructuredFromObject returns a new instance of Kunstructured. +func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) { + // Convert obj to a byte stream, then convert that to JSON (Unstructured). + marshaled, err := json.Marshal(obj) + if err != nil { + return &UnstructAdapter{}, err + } + var u unstructured.Unstructured + err = u.UnmarshalJSON(marshaled) + // creationTimestamp always 'null', remove it + u.SetCreationTimestamp(metav1.Time{}) + return &UnstructAdapter{Unstructured: u}, err +} + +// GetGvk returns the Gvk name of the object. +func (fs *UnstructAdapter) GetGvk() gvk.Gvk { + x := fs.GroupVersionKind() + return gvk.Gvk{ + Group: x.Group, + Version: x.Version, + Kind: x.Kind, + } +} + +// Copy provides a copy behind an interface. +func (fs *UnstructAdapter) Copy() ifc.Kunstructured { + return &UnstructAdapter{*fs.DeepCopy()} +} + +// Map returns the unstructured content map. +func (fs *UnstructAdapter) Map() map[string]interface{} { + return fs.Object +} + +// SetMap overrides the unstructured content map. +func (fs *UnstructAdapter) SetMap(m map[string]interface{}) { + fs.Object = m +} + +// GetFieldValue returns value at the given fieldpath. +func (fs *UnstructAdapter) GetFieldValue(path string) (string, error) { + fields, err := parseFields(path) + if err != nil { + return "", err + } + s, found, err := unstructured.NestedString( + fs.UnstructuredContent(), fields...) + if found || err != nil { + return s, err + } + return "", fmt.Errorf("no field named '%s'", path) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv/kv.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv/kv.go new file mode 100644 index 000000000..27b8b3431 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv/kv.go @@ -0,0 +1,102 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kv + +import ( + "bufio" + "bytes" + "fmt" + "os" + "strings" + "unicode" + "unicode/utf8" + + "k8s.io/apimachinery/pkg/util/validation" +) + +// Pair represents a pair. +type Pair struct { + Key string + Value string +} + +var utf8bom = []byte{0xEF, 0xBB, 0xBF} + +// KeyValuesFromLines parses given content in to a list of key-value pairs. +func KeyValuesFromLines(content []byte) ([]Pair, error) { + var kvs []Pair + + scanner := bufio.NewScanner(bytes.NewReader(content)) + currentLine := 0 + for scanner.Scan() { + // Process the current line, retrieving a key/value pair if + // possible. + scannedBytes := scanner.Bytes() + kv, err := KeyValuesFromLine(scannedBytes, currentLine) + if err != nil { + return nil, err + } + currentLine++ + + if len(kv.Key) == 0 { + // no key means line was empty or a comment + continue + } + + kvs = append(kvs, kv) + } + return kvs, nil +} + +// KeyValuesFromLine returns a kv with blank key if the line is empty or a comment. +// The value will be retrieved from the environment if necessary. +func KeyValuesFromLine(line []byte, currentLine int) (Pair, error) { + kv := Pair{} + + if !utf8.Valid(line) { + return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line)) + } + + // We trim UTF8 BOM from the first line of the file but no others + if currentLine == 0 { + line = bytes.TrimPrefix(line, utf8bom) + } + + // trim the line from all leading whitespace first + line = bytes.TrimLeftFunc(line, unicode.IsSpace) + + // If the line is empty or a comment, we return a blank key/value pair. + if len(line) == 0 || line[0] == '#' { + return kv, nil + } + + data := strings.SplitN(string(line), "=", 2) + key := data[0] + if errs := validation.IsEnvVarName(key); len(errs) != 0 { + return kv, fmt.Errorf("%q is not a valid key name: %s", key, strings.Join(errs, ";")) + } + + if len(data) == 2 { + kv.Value = data[1] + } else { + // No value (no `=` in the line) is a signal to obtain the value + // from the environment. + kv.Value = os.Getenv(key) + } + kv.Key = key + return kv, nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go new file mode 100644 index 000000000..bc435b379 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/factory.go @@ -0,0 +1,43 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package transformer provides transformer factory +package transformer + +import ( + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash" + "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// FactoryImpl makes patch transformer and name hash transformer +type FactoryImpl struct{} + +// NewFactoryImpl makes a new factoryImpl instance +func NewFactoryImpl() *FactoryImpl { + return &FactoryImpl{} +} + +// MakePatchTransformer makes a new patch transformer +func (p *FactoryImpl) MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) { + return patch.NewPatchTransformer(slice, rf) +} + +// MakeHashTransformer makes a new name hash transformer +func (p *FactoryImpl) MakeHashTransformer() transformers.Transformer { + return hash.NewNameHashTransformer() +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go new file mode 100644 index 000000000..17e24ff3e --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/hash.go @@ -0,0 +1,168 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hash + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +// KustHash compute hash for unstructured objects +type KustHash struct{} + +// NewKustHash returns a KustHash object +func NewKustHash() *KustHash { + return &KustHash{} +} + +// Hash returns a hash of either a ConfigMap or a Secret +func (h *KustHash) Hash(m map[string]interface{}) (string, error) { + u := unstructured.Unstructured{ + Object: m, + } + kind := u.GetKind() + switch kind { + case "ConfigMap": + cm, err := unstructuredToConfigmap(u) + if err != nil { + return "", err + } + return ConfigMapHash(cm) + case "Secret": + sec, err := unstructuredToSecret(u) + + if err != nil { + return "", err + } + return SecretHash(sec) + default: + return "", fmt.Errorf("type %s is supported for hashing in %v", kind, m) + } +} + +// ConfigMapHash returns a hash of the ConfigMap. +// The Data, Kind, and Name are taken into account. +func ConfigMapHash(cm *v1.ConfigMap) (string, error) { + encoded, err := encodeConfigMap(cm) + if err != nil { + return "", err + } + h, err := encodeHash(hash(encoded)) + if err != nil { + return "", err + } + return h, nil +} + +// SecretHash returns a hash of the Secret. +// The Data, Kind, Name, and Type are taken into account. +func SecretHash(sec *v1.Secret) (string, error) { + encoded, err := encodeSecret(sec) + if err != nil { + return "", err + } + h, err := encodeHash(hash(encoded)) + if err != nil { + return "", err + } + return h, nil +} + +// encodeConfigMap encodes a ConfigMap. +// Data, Kind, and Name are taken into account. +func encodeConfigMap(cm *v1.ConfigMap) (string, error) { + // json.Marshal sorts the keys in a stable order in the encoding + m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data} + if len(cm.BinaryData) > 0 { + m["binaryData"] = cm.BinaryData + } + data, err := json.Marshal(m) + if err != nil { + return "", err + } + return string(data), nil +} + +// encodeSecret encodes a Secret. +// Data, Kind, Name, and Type are taken into account. +func encodeSecret(sec *v1.Secret) (string, error) { + // json.Marshal sorts the keys in a stable order in the encoding + data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data}) + if err != nil { + return "", err + } + return string(data), nil +} + +// encodeHash extracts the first 40 bits of the hash from the hex string +// (1 hex char represents 4 bits), and then maps vowels and vowel-like hex +// characters to consonants to prevent bad words from being formed (the theory +// is that no vowels makes it really hard to make bad words). Since the string +// is hex, the only vowels it can contain are 'a' and 'e'. +// We picked some arbitrary consonants to map to from the same character set as GenerateName. +// See: https://github.com/kubernetes/apimachinery/blob/dc1f89aff9a7509782bde3b68824c8043a3e58cc/pkg/util/rand/rand.go#L75 +// If the hex string contains fewer than ten characters, returns an error. +func encodeHash(hex string) (string, error) { + if len(hex) < 10 { + return "", fmt.Errorf("the hex string must contain at least 10 characters") + } + enc := []rune(hex[:10]) + for i := range enc { + switch enc[i] { + case '0': + enc[i] = 'g' + case '1': + enc[i] = 'h' + case '3': + enc[i] = 'k' + case 'a': + enc[i] = 'm' + case 'e': + enc[i] = 't' + } + } + return string(enc), nil +} + +// hash hashes `data` with sha256 and returns the hex string +func hash(data string) string { + return fmt.Sprintf("%x", sha256.Sum256([]byte(data))) +} + +func unstructuredToConfigmap(u unstructured.Unstructured) (*v1.ConfigMap, error) { + marshaled, err := json.Marshal(u.Object) + if err != nil { + return nil, err + } + var out v1.ConfigMap + err = json.Unmarshal(marshaled, &out) + return &out, err +} + +func unstructuredToSecret(u unstructured.Unstructured) (*v1.Secret, error) { + marshaled, err := json.Marshal(u.Object) + if err != nil { + return nil, err + } + var out v1.Secret + err = json.Unmarshal(marshaled, &out) + return &out, err +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go new file mode 100644 index 000000000..a52072e8a --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash/namehash.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package hash + +import ( + "fmt" + + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +type nameHashTransformer struct{} + +var _ transformers.Transformer = &nameHashTransformer{} + +// NewNameHashTransformer construct a nameHashTransformer. +func NewNameHashTransformer() transformers.Transformer { + return &nameHashTransformer{} +} + +// Transform appends hash to generated resources. +func (o *nameHashTransformer) Transform(m resmap.ResMap) error { + for _, res := range m { + if res.NeedHashSuffix() { + h, err := NewKustHash().Hash(res.Map()) + if err != nil { + return err + } + res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h)) + } + } + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go new file mode 100644 index 000000000..357f3daba --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patch.go @@ -0,0 +1,174 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import ( + "encoding/json" + "fmt" + + "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// patchTransformer applies patches. +type patchTransformer struct { + patches []*resource.Resource + rf *resource.Factory +} + +var _ transformers.Transformer = &patchTransformer{} + +// NewPatchTransformer constructs a patchTransformer. +func NewPatchTransformer( + slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) { + if len(slice) == 0 { + return transformers.NewNoOpTransformer(), nil + } + return &patchTransformer{patches: slice, rf: rf}, nil +} + +// Transform apply the patches on top of the base resources. +func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error { + // Merge and then index the patches by Id. + patches, err := pt.mergePatches() + if err != nil { + return err + } + + // Strategic merge the resources exist in both base and patches. + for _, patch := range patches { + // Merge patches with base resource. + id := patch.Id() + matchedIds := baseResourceMap.GetMatchingIds(id.GvknEquals) + if len(matchedIds) == 0 { + return fmt.Errorf("failed to find an object with %s to apply the patch", id.GvknString()) + } + if len(matchedIds) > 1 { + return fmt.Errorf("found multiple objects %#v targeted by patch %#v (ambiguous)", matchedIds, id) + } + id = matchedIds[0] + base := baseResourceMap[id] + merged := map[string]interface{}{} + versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk())) + baseName := base.GetName() + switch { + case runtime.IsNotRegisteredError(err): + // Use JSON merge patch to handle types w/o schema + baseBytes, err := json.Marshal(base.Map()) + if err != nil { + return err + } + patchBytes, err := json.Marshal(patch.Map()) + if err != nil { + return err + } + mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes) + if err != nil { + return err + } + err = json.Unmarshal(mergedBytes, &merged) + if err != nil { + return err + } + case err != nil: + return err + default: + // Use Strategic-Merge-Patch to handle types w/ schema + // TODO: Change this to use the new Merge package. + // Store the name of the base object, because this name may have been munged. + // Apply this name to the patched object. + lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) + if err != nil { + return err + } + merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta( + base.Map(), + patch.Map(), + lookupPatchMeta) + if err != nil { + return err + } + } + base.SetName(baseName) + baseResourceMap[id].SetMap(merged) + } + return nil +} + +// mergePatches merge and index patches by Id. +// It errors out if there is conflict between patches. +func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) { + rc := resmap.ResMap{} + for ix, patch := range pt.patches { + id := patch.Id() + existing, found := rc[id] + if !found { + rc[id] = patch + continue + } + + versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk())) + if err != nil && !runtime.IsNotRegisteredError(err) { + return nil, err + } + var cd conflictDetector + if err != nil { + cd = newJMPConflictDetector(pt.rf) + } else { + cd, err = newSMPConflictDetector(versionedObj, pt.rf) + if err != nil { + return nil, err + } + } + + conflict, err := cd.hasConflict(existing, patch) + if err != nil { + return nil, err + } + if conflict { + conflictingPatch, err := cd.findConflict(ix, pt.patches) + if err != nil { + return nil, err + } + return nil, fmt.Errorf( + "conflict between %#v and %#v", + conflictingPatch.Map(), patch.Map()) + } + merged, err := cd.mergePatches(existing, patch) + if err != nil { + return nil, err + } + rc[id] = merged + } + return rc, nil +} + +// toSchemaGvk converts to a schema.GroupVersionKind. +func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind { + return schema.GroupVersionKind{ + Group: x.Group, + Version: x.Version, + Kind: x.Kind, + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go new file mode 100644 index 000000000..10353c77f --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch/patchconflictdetector.go @@ -0,0 +1,137 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import ( + "encoding/json" + + "github.com/evanphx/json-patch" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/mergepatch" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "sigs.k8s.io/kustomize/pkg/resource" +) + +type conflictDetector interface { + hasConflict(patch1, patch2 *resource.Resource) (bool, error) + findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) + mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) +} + +type jsonMergePatch struct { + rf *resource.Factory +} + +var _ conflictDetector = &jsonMergePatch{} + +func newJMPConflictDetector(rf *resource.Factory) conflictDetector { + return &jsonMergePatch{rf: rf} +} + +func (jmp *jsonMergePatch) hasConflict( + patch1, patch2 *resource.Resource) (bool, error) { + return mergepatch.HasConflicts(patch1.Map(), patch2.Map()) +} + +func (jmp *jsonMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { + for i, patch := range patches { + if i == conflictingPatchIdx { + continue + } + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { + continue + } + conflict, err := mergepatch.HasConflicts( + patch.Map(), + patches[conflictingPatchIdx].Map()) + if err != nil { + return nil, err + } + if conflict { + return patch, nil + } + } + return nil, nil +} + +func (jmp *jsonMergePatch) mergePatches( + patch1, patch2 *resource.Resource) (*resource.Resource, error) { + baseBytes, err := json.Marshal(patch1.Map()) + if err != nil { + return nil, err + } + patchBytes, err := json.Marshal(patch2.Map()) + if err != nil { + return nil, err + } + mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes) + if err != nil { + return nil, err + } + mergedMap := make(map[string]interface{}) + err = json.Unmarshal(mergedBytes, &mergedMap) + return jmp.rf.FromMap(mergedMap), err +} + +type strategicMergePatch struct { + lookupPatchMeta strategicpatch.LookupPatchMeta + rf *resource.Factory +} + +var _ conflictDetector = &strategicMergePatch{} + +func newSMPConflictDetector( + versionedObj runtime.Object, + rf *resource.Factory) (conflictDetector, error) { + lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) + return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err +} + +func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) { + return strategicpatch.MergingMapsHaveConflicts( + p1.Map(), p2.Map(), smp.lookupPatchMeta) +} + +func (smp *strategicMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { + for i, patch := range patches { + if i == conflictingPatchIdx { + continue + } + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { + continue + } + conflict, err := strategicpatch.MergingMapsHaveConflicts( + patch.Map(), + patches[conflictingPatchIdx].Map(), + smp.lookupPatchMeta) + if err != nil { + return nil, err + } + if conflict { + return patch, nil + } + } + return nil, nil +} + +func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { + mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta( + smp.lookupPatchMeta, patch1.Map(), patch2.Map()) + return smp.rf.FromMap(mergeJSONMap), err +} diff --git a/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go new file mode 100644 index 000000000..563e8d6b9 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator/validators.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package validator provides functions to validate labels, annotations, namespace using apimachinery +package validator + +import ( + "errors" + apivalidation "k8s.io/apimachinery/pkg/api/validation" + v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" + "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/apimachinery/pkg/util/validation/field" +) + +// KustValidator validates Labels and annotations by apimachinery +type KustValidator struct{} + +// NewKustValidator returns a KustValidator object +func NewKustValidator() *KustValidator { + return &KustValidator{} +} + +// MakeAnnotationValidator returns a MapValidatorFunc using apimachinery. +func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error { + return func(x map[string]string) error { + errs := apivalidation.ValidateAnnotations(x, field.NewPath("field")) + if len(errs) > 0 { + return errors.New(errs.ToAggregate().Error()) + } + return nil + } +} + +// MakeLabelValidator returns a MapValidatorFunc using apimachinery. +func (v *KustValidator) MakeLabelValidator() func(map[string]string) error { + return func(x map[string]string) error { + errs := v1validation.ValidateLabels(x, field.NewPath("field")) + if len(errs) > 0 { + return errors.New(errs.ToAggregate().Error()) + } + return nil + } +} + +// ValidateNamespace validates a string is a valid namespace using apimachinery. +func (v *KustValidator) ValidateNamespace(s string) []string { + return validation.IsDNS1123Label(s) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/discard.go b/vendor/k8s.io/cli-runtime/pkg/printers/discard.go new file mode 100644 index 000000000..cd934976d --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/discard.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" +) + +// NewDiscardingPrinter is a printer that discards all objects +func NewDiscardingPrinter() ResourcePrinterFunc { + return ResourcePrinterFunc(func(runtime.Object, io.Writer) error { + return nil + }) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/doc.go b/vendor/k8s.io/cli-runtime/pkg/printers/doc.go new file mode 100644 index 000000000..ee205371d --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package printers is helper for formatting and printing runtime objects into +// primitives io.writer. +package printers // import "k8s.io/cli-runtime/pkg/printers" diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/interface.go b/vendor/k8s.io/cli-runtime/pkg/printers/interface.go new file mode 100644 index 000000000..e06757f6d --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/interface.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// ResourcePrinterFunc is a function that can print objects +type ResourcePrinterFunc func(runtime.Object, io.Writer) error + +// PrintObj implements ResourcePrinter +func (fn ResourcePrinterFunc) PrintObj(obj runtime.Object, w io.Writer) error { + return fn(obj, w) +} + +// ResourcePrinter is an interface that knows how to print runtime objects. +type ResourcePrinter interface { + // Print receives a runtime object, formats it and prints it to a writer. + PrintObj(runtime.Object, io.Writer) error +} + +// PrintOptions struct defines a struct for various print options +type PrintOptions struct { + NoHeaders bool + WithNamespace bool + WithKind bool + Wide bool + ShowLabels bool + Kind schema.GroupKind + ColumnLabels []string + + SortBy string + + // indicates if it is OK to ignore missing keys for rendering an output template. + AllowMissingKeys bool +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/json.go b/vendor/k8s.io/cli-runtime/pkg/printers/json.go new file mode 100644 index 000000000..1c35b97d7 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/json.go @@ -0,0 +1,142 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + "sync/atomic" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "sigs.k8s.io/yaml" +) + +// JSONPrinter is an implementation of ResourcePrinter which outputs an object as JSON. +type JSONPrinter struct{} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer. +func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + switch obj := obj.(type) { + case *metav1.WatchEvent: + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj.Object.Object)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + data, err := json.Marshal(obj) + if err != nil { + return err + } + _, err = w.Write(data) + if err != nil { + return err + } + _, err = w.Write([]byte{'\n'}) + return err + case *runtime.Unknown: + var buf bytes.Buffer + err := json.Indent(&buf, obj.Raw, "", " ") + if err != nil { + return err + } + buf.WriteRune('\n') + _, err = buf.WriteTo(w) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + data = append(data, '\n') + _, err = w.Write(data) + return err +} + +// YAMLPrinter is an implementation of ResourcePrinter which outputs an object as YAML. +// The input object is assumed to be in the internal version of an API and is converted +// to the given version first. +// If PrintObj() is called multiple times, objects are separated with a '---' separator. +type YAMLPrinter struct { + printCount int64 +} + +// PrintObj prints the data as YAML. +func (p *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + count := atomic.AddInt64(&p.printCount, 1) + if count > 1 { + if _, err := w.Write([]byte("---\n")); err != nil { + return err + } + } + + switch obj := obj.(type) { + case *metav1.WatchEvent: + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj.Object.Object)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + data, err := json.Marshal(obj) + if err != nil { + return err + } + data, err = yaml.JSONToYAML(data) + if err != nil { + return err + } + _, err = w.Write(data) + return err + case *runtime.Unknown: + data, err := yaml.JSONToYAML(obj.Raw) + if err != nil { + return err + } + _, err = w.Write(data) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + output, err := yaml.Marshal(obj) + if err != nil { + return err + } + _, err = fmt.Fprint(w, string(output)) + return err +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go b/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go new file mode 100644 index 000000000..333b9c334 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go @@ -0,0 +1,147 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/util/jsonpath" +) + +// exists returns true if it would be possible to call the index function +// with these arguments. +// +// TODO: how to document this for users? +// +// index returns the result of indexing its first argument by the following +// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each +// indexed item must be a map, slice, or array. +func exists(item interface{}, indices ...interface{}) bool { + v := reflect.ValueOf(item) + for _, i := range indices { + index := reflect.ValueOf(i) + var isNil bool + if v, isNil = indirect(v); isNil { + return false + } + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.String: + var x int64 + switch index.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x = index.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x = int64(index.Uint()) + default: + return false + } + if x < 0 || x >= int64(v.Len()) { + return false + } + v = v.Index(int(x)) + case reflect.Map: + if !index.IsValid() { + index = reflect.Zero(v.Type().Key()) + } + if !index.Type().AssignableTo(v.Type().Key()) { + return false + } + if x := v.MapIndex(index); x.IsValid() { + v = x + } else { + v = reflect.Zero(v.Type().Elem()) + } + default: + return false + } + } + if _, isNil := indirect(v); isNil { + return false + } + return true +} + +// stolen from text/template +// indirect returns the item at the end of indirection, and a bool to indicate if it's nil. +// We indirect through pointers and empty interfaces (only) because +// non-empty interfaces have methods we might need. +func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { + for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { + if v.IsNil() { + return v, true + } + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break + } + } + return v, false +} + +// JSONPathPrinter is an implementation of ResourcePrinter which formats data with jsonpath expression. +type JSONPathPrinter struct { + rawTemplate string + *jsonpath.JSONPath +} + +func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) { + j := jsonpath.New("out") + if err := j.Parse(tmpl); err != nil { + return nil, err + } + return &JSONPathPrinter{ + rawTemplate: tmpl, + JSONPath: j, + }, nil +} + +// PrintObj formats the obj with the JSONPath Template. +func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + var queryObj interface{} = obj + if unstructured, ok := obj.(runtime.Unstructured); ok { + queryObj = unstructured.UnstructuredContent() + } else { + data, err := json.Marshal(obj) + if err != nil { + return err + } + queryObj = map[string]interface{}{} + if err := json.Unmarshal(data, &queryObj); err != nil { + return err + } + } + + if err := j.JSONPath.Execute(w, queryObj); err != nil { + buf := bytes.NewBuffer(nil) + fmt.Fprintf(buf, "Error executing template: %v. Printing more information for debugging the template:\n", err) + fmt.Fprintf(buf, "\ttemplate was:\n\t\t%v\n", j.rawTemplate) + fmt.Fprintf(buf, "\tobject given to jsonpath engine was:\n\t\t%#v\n\n", queryObj) + return fmt.Errorf("error executing jsonpath %q: %v\n", j.rawTemplate, buf.String()) + } + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/name.go b/vendor/k8s.io/cli-runtime/pkg/printers/name.go new file mode 100644 index 000000000..086166af2 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/name.go @@ -0,0 +1,130 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + "reflect" + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// NamePrinter is an implementation of ResourcePrinter which outputs "resource/name" pair of an object. +type NamePrinter struct { + // ShortOutput indicates whether an operation should be + // printed along side the "resource/name" pair for an object. + ShortOutput bool + // Operation describes the name of the action that + // took place on an object, to be included in the + // finalized "successful" message. + Operation string +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which decodes the object +// and print "resource/name" pair. If the object is a List, print all items in it. +func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + switch castObj := obj.(type) { + case *metav1.WatchEvent: + obj = castObj.Object.Object + } + + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + // we need an actual value in order to retrieve the package path for an object. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + if meta.IsListType(obj) { + // we allow unstructured lists for now because they always contain the GVK information. We should chase down + // callers and stop them from passing unflattened lists + // TODO chase the caller that is setting this and remove it. + if _, ok := obj.(*unstructured.UnstructuredList); !ok { + return fmt.Errorf("list types are not supported by name printing: %T", obj) + } + + items, err := meta.ExtractList(obj) + if err != nil { + return err + } + for _, obj := range items { + if err := p.PrintObj(obj, w); err != nil { + return err + } + } + return nil + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + name := "" + if acc, err := meta.Accessor(obj); err == nil { + if n := acc.GetName(); len(n) > 0 { + name = n + } + } + + return printObj(w, name, p.Operation, p.ShortOutput, GetObjectGroupKind(obj)) +} + +func GetObjectGroupKind(obj runtime.Object) schema.GroupKind { + if obj == nil { + return schema.GroupKind{Kind: ""} + } + groupVersionKind := obj.GetObjectKind().GroupVersionKind() + if len(groupVersionKind.Kind) > 0 { + return groupVersionKind.GroupKind() + } + + if uns, ok := obj.(*unstructured.Unstructured); ok { + if len(uns.GroupVersionKind().Kind) > 0 { + return uns.GroupVersionKind().GroupKind() + } + } + + return schema.GroupKind{Kind: ""} +} + +func printObj(w io.Writer, name string, operation string, shortOutput bool, groupKind schema.GroupKind) error { + if len(groupKind.Kind) == 0 { + return fmt.Errorf("missing kind for resource with name %v", name) + } + + if len(operation) > 0 { + operation = " " + operation + } + + if shortOutput { + operation = "" + } + + if len(groupKind.Group) == 0 { + fmt.Fprintf(w, "%s/%s%s\n", strings.ToLower(groupKind.Kind), name, operation) + return nil + } + + fmt.Fprintf(w, "%s.%s/%s%s\n", strings.ToLower(groupKind.Kind), groupKind.Group, name, operation) + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go b/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go new file mode 100644 index 000000000..e360c8fe0 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "strings" +) + +var ( + InternalObjectPrinterErr = "a versioned object must be passed to a printer" + + // disallowedPackagePrefixes contains regular expression templates + // for object package paths that are not allowed by printers. + disallowedPackagePrefixes = []string{ + "k8s.io/kubernetes/pkg/apis/", + } +) + +var InternalObjectPreventer = &illegalPackageSourceChecker{disallowedPackagePrefixes} + +func IsInternalObjectError(err error) bool { + if err == nil { + return false + } + + return err.Error() == InternalObjectPrinterErr +} + +// illegalPackageSourceChecker compares a given +// object's package path, and determines if the +// object originates from a disallowed source. +type illegalPackageSourceChecker struct { + // disallowedPrefixes is a slice of disallowed package path + // prefixes for a given runtime.Object that we are printing. + disallowedPrefixes []string +} + +func (c *illegalPackageSourceChecker) IsForbidden(pkgPath string) bool { + for _, forbiddenPrefix := range c.disallowedPrefixes { + if strings.HasPrefix(pkgPath, forbiddenPrefix) || strings.Contains(pkgPath, "/vendor/"+forbiddenPrefix) { + return true + } + } + + return false +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go new file mode 100644 index 000000000..8f6f072aa --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go @@ -0,0 +1,574 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + "reflect" + "strings" + "time" + + "github.com/liggitt/tabwriter" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/duration" + "k8s.io/apimachinery/pkg/watch" +) + +var _ ResourcePrinter = &HumanReadablePrinter{} + +type printHandler struct { + columnDefinitions []metav1beta1.TableColumnDefinition + printFunc reflect.Value +} + +var ( + statusHandlerEntry = &printHandler{ + columnDefinitions: statusColumnDefinitions, + printFunc: reflect.ValueOf(printStatus), + } + + statusColumnDefinitions = []metav1beta1.TableColumnDefinition{ + {Name: "Status", Type: "string"}, + {Name: "Reason", Type: "string"}, + {Name: "Message", Type: "string"}, + } + + defaultHandlerEntry = &printHandler{ + columnDefinitions: objectMetaColumnDefinitions, + printFunc: reflect.ValueOf(printObjectMeta), + } + + objectMetaColumnDefinitions = []metav1beta1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + + withEventTypePrefixColumns = []string{"EVENT"} + withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too. +) + +// HumanReadablePrinter is an implementation of ResourcePrinter which attempts to provide +// more elegant output. It is not threadsafe, but you may call PrintObj repeatedly; headers +// will only be printed if the object type changes. This makes it useful for printing items +// received from watches. +type HumanReadablePrinter struct { + options PrintOptions + lastType interface{} + lastColumns []metav1beta1.TableColumnDefinition + printedHeaders bool +} + +// NewTablePrinter creates a printer suitable for calling PrintObj(). +func NewTablePrinter(options PrintOptions) ResourcePrinter { + printer := &HumanReadablePrinter{ + options: options, + } + return printer +} + +func printHeader(columnNames []string, w io.Writer) error { + if _, err := fmt.Fprintf(w, "%s\n", strings.Join(columnNames, "\t")); err != nil { + return err + } + return nil +} + +// PrintObj prints the obj in a human-friendly format according to the type of the obj. +func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error { + + w, found := output.(*tabwriter.Writer) + if !found { + w = GetNewTabWriter(output) + output = w + defer w.Flush() + } + + var eventType string + if event, isEvent := obj.(*metav1.WatchEvent); isEvent { + eventType = event.Type + obj = event.Object.Object + } + + // Parameter "obj" is a table from server; print it. + // display tables following the rules of options + if table, ok := obj.(*metav1beta1.Table); ok { + // Do not print headers if this table has no column definitions, or they are the same as the last ones we printed + localOptions := h.options + if h.printedHeaders && (len(table.ColumnDefinitions) == 0 || reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns)) { + localOptions.NoHeaders = true + } + + if len(table.ColumnDefinitions) == 0 { + // If this table has no column definitions, use the columns from the last table we printed for decoration and layout. + // This is done when receiving tables in watch events to save bandwidth. + table.ColumnDefinitions = h.lastColumns + } else if !reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns) { + // If this table has column definitions, remember them for future use. + h.lastColumns = table.ColumnDefinitions + h.printedHeaders = false + } + + if len(table.Rows) > 0 { + h.printedHeaders = true + } + + if err := decorateTable(table, localOptions); err != nil { + return err + } + if len(eventType) > 0 { + if err := addColumns(beginning, table, + []metav1beta1.TableColumnDefinition{{Name: "Event", Type: "string"}}, + []cellValueFunc{func(metav1beta1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }}, + ); err != nil { + return err + } + } + return printTable(table, output, localOptions) + } + + // Could not find print handler for "obj"; use the default or status print handler. + // Print with the default or status handler, and use the columns from the last time + var handler *printHandler + if _, isStatus := obj.(*metav1.Status); isStatus { + handler = statusHandlerEntry + } else { + handler = defaultHandlerEntry + } + + includeHeaders := h.lastType != handler && !h.options.NoHeaders + + if h.lastType != nil && h.lastType != handler && !h.options.NoHeaders { + fmt.Fprintln(output) + } + + if err := printRowsForHandlerEntry(output, handler, eventType, obj, h.options, includeHeaders); err != nil { + return err + } + h.lastType = handler + + return nil +} + +// printTable prints a table to the provided output respecting the filtering rules for options +// for wide columns and filtered rows. It filters out rows that are Completed. You should call +// decorateTable if you receive a table from a remote server before calling printTable. +func printTable(table *metav1beta1.Table, output io.Writer, options PrintOptions) error { + if !options.NoHeaders { + // avoid printing headers if we have no rows to display + if len(table.Rows) == 0 { + return nil + } + + first := true + for _, column := range table.ColumnDefinitions { + if !options.Wide && column.Priority != 0 { + continue + } + if first { + first = false + } else { + fmt.Fprint(output, "\t") + } + fmt.Fprint(output, strings.ToUpper(column.Name)) + } + fmt.Fprintln(output) + } + for _, row := range table.Rows { + first := true + for i, cell := range row.Cells { + if i >= len(table.ColumnDefinitions) { + // https://issue.k8s.io/66379 + // don't panic in case of bad output from the server, with more cells than column definitions + break + } + column := table.ColumnDefinitions[i] + if !options.Wide && column.Priority != 0 { + continue + } + if first { + first = false + } else { + fmt.Fprint(output, "\t") + } + if cell != nil { + fmt.Fprint(output, cell) + } + } + fmt.Fprintln(output) + } + return nil +} + +type cellValueFunc func(metav1beta1.TableRow) (interface{}, error) + +type columnAddPosition int + +const ( + beginning columnAddPosition = 1 + end columnAddPosition = 2 +) + +func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav1beta1.TableColumnDefinition, valueFuncs []cellValueFunc) error { + if len(columns) != len(valueFuncs) { + return fmt.Errorf("cannot prepend columns, unmatched value functions") + } + if len(columns) == 0 { + return nil + } + + // Compute the new rows + newRows := make([][]interface{}, len(table.Rows)) + for i := range table.Rows { + newCells := make([]interface{}, 0, len(columns)+len(table.Rows[i].Cells)) + + if pos == end { + // If we're appending, start with the existing cells, + // then add nil cells to match the number of columns + newCells = append(newCells, table.Rows[i].Cells...) + for len(newCells) < len(table.ColumnDefinitions) { + newCells = append(newCells, nil) + } + } + + // Compute cells for new columns + for _, f := range valueFuncs { + newCell, err := f(table.Rows[i]) + if err != nil { + return err + } + newCells = append(newCells, newCell) + } + + if pos == beginning { + // If we're prepending, add existing cells + newCells = append(newCells, table.Rows[i].Cells...) + } + + // Remember the new cells for this row + newRows[i] = newCells + } + + // All cells successfully computed, now replace columns and rows + newColumns := make([]metav1beta1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions)) + switch pos { + case beginning: + newColumns = append(newColumns, columns...) + newColumns = append(newColumns, table.ColumnDefinitions...) + case end: + newColumns = append(newColumns, table.ColumnDefinitions...) + newColumns = append(newColumns, columns...) + default: + return fmt.Errorf("invalid column add position: %v", pos) + } + table.ColumnDefinitions = newColumns + for i := range table.Rows { + table.Rows[i].Cells = newRows[i] + } + + return nil +} + +// decorateTable takes a table and attempts to add label columns and the +// namespace column. It will fill empty columns with nil (if the object +// does not expose metadata). It returns an error if the table cannot +// be decorated. +func decorateTable(table *metav1beta1.Table, options PrintOptions) error { + width := len(table.ColumnDefinitions) + len(options.ColumnLabels) + if options.WithNamespace { + width++ + } + if options.ShowLabels { + width++ + } + + columns := table.ColumnDefinitions + + nameColumn := -1 + if options.WithKind && !options.Kind.Empty() { + for i := range columns { + if columns[i].Format == "name" && columns[i].Type == "string" { + nameColumn = i + break + } + } + } + + if width != len(table.ColumnDefinitions) { + columns = make([]metav1beta1.TableColumnDefinition, 0, width) + if options.WithNamespace { + columns = append(columns, metav1beta1.TableColumnDefinition{ + Name: "Namespace", + Type: "string", + }) + } + columns = append(columns, table.ColumnDefinitions...) + for _, label := range formatLabelHeaders(options.ColumnLabels) { + columns = append(columns, metav1beta1.TableColumnDefinition{ + Name: label, + Type: "string", + }) + } + if options.ShowLabels { + columns = append(columns, metav1beta1.TableColumnDefinition{ + Name: "Labels", + Type: "string", + }) + } + } + + rows := table.Rows + + includeLabels := len(options.ColumnLabels) > 0 || options.ShowLabels + if includeLabels || options.WithNamespace || nameColumn != -1 { + for i := range rows { + row := rows[i] + + if nameColumn != -1 { + row.Cells[nameColumn] = fmt.Sprintf("%s/%s", strings.ToLower(options.Kind.String()), row.Cells[nameColumn]) + } + + var m metav1.Object + if obj := row.Object.Object; obj != nil { + if acc, err := meta.Accessor(obj); err == nil { + m = acc + } + } + // if we can't get an accessor, fill out the appropriate columns with empty spaces + if m == nil { + if options.WithNamespace { + r := make([]interface{}, 1, width) + row.Cells = append(r, row.Cells...) + } + for j := 0; j < width-len(row.Cells); j++ { + row.Cells = append(row.Cells, nil) + } + rows[i] = row + continue + } + + if options.WithNamespace { + r := make([]interface{}, 1, width) + r[0] = m.GetNamespace() + row.Cells = append(r, row.Cells...) + } + if includeLabels { + row.Cells = appendLabelCells(row.Cells, m.GetLabels(), options) + } + rows[i] = row + } + } + + table.ColumnDefinitions = columns + table.Rows = rows + return nil +} + +// printRowsForHandlerEntry prints the incremental table output (headers if the current type is +// different from lastType) including all the rows in the object. It returns the current type +// or an error, if any. +func printRowsForHandlerEntry(output io.Writer, handler *printHandler, eventType string, obj runtime.Object, options PrintOptions, includeHeaders bool) error { + var results []reflect.Value + + args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} + results = handler.printFunc.Call(args) + if !results[1].IsNil() { + return results[1].Interface().(error) + } + + if includeHeaders { + var headers []string + for _, column := range handler.columnDefinitions { + if column.Priority != 0 && !options.Wide { + continue + } + headers = append(headers, strings.ToUpper(column.Name)) + } + headers = append(headers, formatLabelHeaders(options.ColumnLabels)...) + // LABELS is always the last column. + headers = append(headers, formatShowLabelsHeader(options.ShowLabels)...) + // prepend namespace header + if options.WithNamespace { + headers = append(withNamespacePrefixColumns, headers...) + } + // prepend event type header + if len(eventType) > 0 { + headers = append(withEventTypePrefixColumns, headers...) + } + printHeader(headers, output) + } + + if results[1].IsNil() { + rows := results[0].Interface().([]metav1beta1.TableRow) + printRows(output, eventType, rows, options) + return nil + } + return results[1].Interface().(error) +} + +var formattedEventType = map[string]string{ + string(watch.Added): "ADDED ", + string(watch.Modified): "MODIFIED", + string(watch.Deleted): "DELETED ", + string(watch.Error): "ERROR ", +} + +func formatEventType(eventType string) string { + if formatted, ok := formattedEventType[eventType]; ok { + return formatted + } + return string(eventType) +} + +// printRows writes the provided rows to output. +func printRows(output io.Writer, eventType string, rows []metav1beta1.TableRow, options PrintOptions) { + for _, row := range rows { + if len(eventType) > 0 { + fmt.Fprint(output, formatEventType(eventType)) + fmt.Fprint(output, "\t") + } + if options.WithNamespace { + if obj := row.Object.Object; obj != nil { + if m, err := meta.Accessor(obj); err == nil { + fmt.Fprint(output, m.GetNamespace()) + } + } + fmt.Fprint(output, "\t") + } + + for i, cell := range row.Cells { + if i != 0 { + fmt.Fprint(output, "\t") + } else { + // TODO: remove this once we drop the legacy printers + if options.WithKind && !options.Kind.Empty() { + fmt.Fprintf(output, "%s/%s", strings.ToLower(options.Kind.String()), cell) + continue + } + } + fmt.Fprint(output, cell) + } + + hasLabels := len(options.ColumnLabels) > 0 + if obj := row.Object.Object; obj != nil && (hasLabels || options.ShowLabels) { + if m, err := meta.Accessor(obj); err == nil { + for _, value := range labelValues(m.GetLabels(), options) { + output.Write([]byte("\t")) + output.Write([]byte(value)) + } + } + } + + output.Write([]byte("\n")) + } +} + +func formatLabelHeaders(columnLabels []string) []string { + formHead := make([]string, len(columnLabels)) + for i, l := range columnLabels { + p := strings.Split(l, "/") + formHead[i] = strings.ToUpper((p[len(p)-1])) + } + return formHead +} + +// headers for --show-labels=true +func formatShowLabelsHeader(showLabels bool) []string { + if showLabels { + return []string{"LABELS"} + } + return nil +} + +// labelValues returns a slice of value columns matching the requested print options. +func labelValues(itemLabels map[string]string, opts PrintOptions) []string { + var values []string + for _, key := range opts.ColumnLabels { + values = append(values, itemLabels[key]) + } + if opts.ShowLabels { + values = append(values, labels.FormatLabels(itemLabels)) + } + return values +} + +// appendLabelCells returns a slice of value columns matching the requested print options. +// Intended for use with tables. +func appendLabelCells(values []interface{}, itemLabels map[string]string, opts PrintOptions) []interface{} { + for _, key := range opts.ColumnLabels { + values = append(values, itemLabels[key]) + } + if opts.ShowLabels { + values = append(values, labels.FormatLabels(itemLabels)) + } + return values +} + +func printStatus(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) { + status, ok := obj.(*metav1.Status) + if !ok { + return nil, fmt.Errorf("expected *v1.Status, got %T", obj) + } + return []metav1beta1.TableRow{{ + Object: runtime.RawExtension{Object: obj}, + Cells: []interface{}{status.Status, status.Reason, status.Message}, + }}, nil +} + +func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) { + if meta.IsListType(obj) { + rows := make([]metav1beta1.TableRow, 0, 16) + err := meta.EachListItem(obj, func(obj runtime.Object) error { + nestedRows, err := printObjectMeta(obj, options) + if err != nil { + return err + } + rows = append(rows, nestedRows...) + return nil + }) + if err != nil { + return nil, err + } + return rows, nil + } + + rows := make([]metav1beta1.TableRow, 0, 1) + m, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + row := metav1beta1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp())) + rows = append(rows, row) + return rows, nil +} + +// translateTimestampSince returns the elapsed time since timestamp in +// human-readable approximation. +func translateTimestampSince(timestamp metav1.Time) string { + if timestamp.IsZero() { + return "" + } + + return duration.HumanDuration(time.Since(timestamp.Time)) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go b/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go new file mode 100644 index 000000000..21d60e1c4 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go @@ -0,0 +1,36 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "github.com/liggitt/tabwriter" +) + +const ( + tabwriterMinWidth = 6 + tabwriterWidth = 4 + tabwriterPadding = 3 + tabwriterPadChar = ' ' + tabwriterFlags = tabwriter.RememberWidths +) + +// GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. +func GetNewTabWriter(output io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/template.go b/vendor/k8s.io/cli-runtime/pkg/printers/template.go new file mode 100644 index 000000000..ccff54226 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/template.go @@ -0,0 +1,118 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "encoding/base64" + "fmt" + "io" + "reflect" + "text/template" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/json" +) + +// GoTemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template. +type GoTemplatePrinter struct { + rawTemplate string + template *template.Template +} + +func NewGoTemplatePrinter(tmpl []byte) (*GoTemplatePrinter, error) { + t, err := template.New("output"). + Funcs(template.FuncMap{ + "exists": exists, + "base64decode": base64decode, + }). + Parse(string(tmpl)) + if err != nil { + return nil, err + } + return &GoTemplatePrinter{ + rawTemplate: string(tmpl), + template: t, + }, nil +} + +// AllowMissingKeys tells the template engine if missing keys are allowed. +func (p *GoTemplatePrinter) AllowMissingKeys(allow bool) { + if allow { + p.template.Option("missingkey=default") + } else { + p.template.Option("missingkey=error") + } +} + +// PrintObj formats the obj with the Go Template. +func (p *GoTemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + var data []byte + var err error + data, err = json.Marshal(obj) + if err != nil { + return err + } + + out := map[string]interface{}{} + if err := json.Unmarshal(data, &out); err != nil { + return err + } + if err = p.safeExecute(w, out); err != nil { + // It is way easier to debug this stuff when it shows up in + // stdout instead of just stdin. So in addition to returning + // a nice error, also print useful stuff with the writer. + fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err) + fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", p.rawTemplate) + fmt.Fprintf(w, "\traw data was:\n\t\t%v\n", string(data)) + fmt.Fprintf(w, "\tobject given to template engine was:\n\t\t%+v\n\n", out) + return fmt.Errorf("error executing template %q: %v", p.rawTemplate, err) + } + return nil +} + +// safeExecute tries to execute the template, but catches panics and returns an error +// should the template engine panic. +func (p *GoTemplatePrinter) safeExecute(w io.Writer, obj interface{}) error { + var panicErr error + // Sorry for the double anonymous function. There's probably a clever way + // to do this that has the defer'd func setting the value to be returned, but + // that would be even less obvious. + retErr := func() error { + defer func() { + if x := recover(); x != nil { + panicErr = fmt.Errorf("caught panic: %+v", x) + } + }() + return p.template.Execute(w, obj) + }() + if panicErr != nil { + return panicErr + } + return retErr +} + +func base64decode(v string) (string, error) { + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return "", fmt.Errorf("base64 decode failed: %v", err) + } + return string(data), nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go b/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go new file mode 100644 index 000000000..8d2d9b56e --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// TypeSetterPrinter is an implementation of ResourcePrinter wraps another printer with types set on the objects +type TypeSetterPrinter struct { + Delegate ResourcePrinter + + Typer runtime.ObjectTyper +} + +// NewTypeSetter constructs a wrapping printer with required params +func NewTypeSetter(typer runtime.ObjectTyper) *TypeSetterPrinter { + return &TypeSetterPrinter{Typer: typer} +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which sets type information on the obj for the duration +// of printing. It is NOT threadsafe. +func (p *TypeSetterPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if obj == nil { + return p.Delegate.PrintObj(obj, w) + } + if !obj.GetObjectKind().GroupVersionKind().Empty() { + return p.Delegate.PrintObj(obj, w) + } + + // we were empty coming in, make sure we're empty going out. This makes the call thread-unsafe + defer func() { + obj.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{}) + }() + + gvks, _, err := p.Typer.ObjectKinds(obj) + if err != nil { + // printers wrapped by us expect to find the type information present + return fmt.Errorf("missing apiVersion or kind and cannot assign it; %v", err) + } + + for _, gvk := range gvks { + if len(gvk.Kind) == 0 { + continue + } + if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { + continue + } + obj.GetObjectKind().SetGroupVersionKind(gvk) + break + } + + return p.Delegate.PrintObj(obj, w) +} + +// ToPrinter returns a printer (not threadsafe!) that has been wrapped +func (p *TypeSetterPrinter) ToPrinter(delegate ResourcePrinter) ResourcePrinter { + if p == nil { + return delegate + } + + p.Delegate = delegate + return p +} + +// WrapToPrinter wraps the common ToPrinter method +func (p *TypeSetterPrinter) WrapToPrinter(delegate ResourcePrinter, err error) (ResourcePrinter, error) { + if err != nil { + return delegate, err + } + if p == nil { + return delegate, nil + } + + p.Delegate = delegate + return p, nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/builder.go b/vendor/k8s.io/cli-runtime/pkg/resource/builder.go new file mode 100644 index 000000000..88314404f --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/builder.go @@ -0,0 +1,1193 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "errors" + "fmt" + "io" + "net/url" + "os" + "strings" + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/restmapper" +) + +var FileExtensions = []string{".json", ".yaml", ".yml"} +var InputExtensions = append(FileExtensions, "stdin") + +const defaultHttpGetAttempts int = 3 + +// Builder provides convenience functions for taking arguments and parameters +// from the command line and converting them to a list of resources to iterate +// over using the Visitor interface. +type Builder struct { + categoryExpanderFn CategoryExpanderFunc + + // mapper is set explicitly by resource builders + mapper *mapper + + // clientConfigFn is a function to produce a client, *if* you need one + clientConfigFn ClientConfigFunc + + restMapperFn RESTMapperFunc + + // objectTyper is statically determinant per-command invocation based on your internal or unstructured choice + // it does not ever need to rely upon discovery. + objectTyper runtime.ObjectTyper + + // codecFactory describes which codecs you want to use + negotiatedSerializer runtime.NegotiatedSerializer + + // local indicates that we cannot make server calls + local bool + + errs []error + + paths []Visitor + stream bool + dir bool + + labelSelector *string + fieldSelector *string + selectAll bool + limitChunks int64 + requestTransforms []RequestTransform + + resources []string + + namespace string + allNamespace bool + names []string + + resourceTuples []resourceTuple + + defaultNamespace bool + requireNamespace bool + + flatten bool + latest bool + + requireObject bool + + singleResourceType bool + continueOnError bool + + singleItemImplied bool + + export bool + + schema ContentValidator + + // fakeClientFn is used for testing + fakeClientFn FakeClientFunc +} + +var missingResourceError = fmt.Errorf(`You must provide one or more resources by argument or filename. +Example resource specifications include: + '-f rsrc.yaml' + '--filename=rsrc.json' + ' ' + ''`) + +var LocalResourceError = errors.New(`error: you must specify resources by --filename when --local is set. +Example resource specifications include: + '-f rsrc.yaml' + '--filename=rsrc.json'`) + +// TODO: expand this to include other errors. +func IsUsageError(err error) bool { + if err == nil { + return false + } + return err == missingResourceError +} + +type FilenameOptions struct { + Filenames []string + Kustomize string + Recursive bool +} + +func (o *FilenameOptions) validate() []error { + var errs []error + if len(o.Filenames) > 0 && len(o.Kustomize) > 0 { + errs = append(errs, fmt.Errorf("only one of -f or -k can be specified")) + } + if len(o.Kustomize) > 0 && o.Recursive { + errs = append(errs, fmt.Errorf("the -k flag can't be used with -f or -R")) + } + return errs +} + +func (o *FilenameOptions) RequireFilenameOrKustomize() error { + if len(o.Filenames) == 0 && len(o.Kustomize) == 0 { + return fmt.Errorf("must specify one of -f and -k") + } + return nil +} + +type resourceTuple struct { + Resource string + Name string +} + +type FakeClientFunc func(version schema.GroupVersion) (RESTClient, error) + +func NewFakeBuilder(fakeClientFn FakeClientFunc, restMapper RESTMapperFunc, categoryExpander CategoryExpanderFunc) *Builder { + ret := newBuilder(nil, restMapper, categoryExpander) + ret.fakeClientFn = fakeClientFn + return ret +} + +// NewBuilder creates a builder that operates on generic objects. At least one of +// internal or unstructured must be specified. +// TODO: Add versioned client (although versioned is still lossy) +// TODO remove internal and unstructured mapper and instead have them set the negotiated serializer for use in the client +func newBuilder(clientConfigFn ClientConfigFunc, restMapper RESTMapperFunc, categoryExpander CategoryExpanderFunc) *Builder { + return &Builder{ + clientConfigFn: clientConfigFn, + restMapperFn: restMapper, + categoryExpanderFn: categoryExpander, + requireObject: true, + } +} + +func NewBuilder(restClientGetter RESTClientGetter) *Builder { + categoryExpanderFn := func() (restmapper.CategoryExpander, error) { + discoveryClient, err := restClientGetter.ToDiscoveryClient() + if err != nil { + return nil, err + } + return restmapper.NewDiscoveryCategoryExpander(discoveryClient), err + } + + return newBuilder( + restClientGetter.ToRESTConfig, + (&cachingRESTMapperFunc{delegate: restClientGetter.ToRESTMapper}).ToRESTMapper, + (&cachingCategoryExpanderFunc{delegate: categoryExpanderFn}).ToCategoryExpander, + ) +} + +func (b *Builder) Schema(schema ContentValidator) *Builder { + b.schema = schema + return b +} + +func (b *Builder) AddError(err error) *Builder { + if err == nil { + return b + } + b.errs = append(b.errs, err) + return b +} + +// FilenameParam groups input in two categories: URLs and files (files, directories, STDIN) +// If enforceNamespace is false, namespaces in the specs will be allowed to +// override the default namespace. If it is true, namespaces that don't match +// will cause an error. +// If ContinueOnError() is set prior to this method, objects on the path that are not +// recognized will be ignored (but logged at V(2)). +func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *FilenameOptions) *Builder { + if errs := filenameOptions.validate(); len(errs) > 0 { + b.errs = append(b.errs, errs...) + return b + } + recursive := filenameOptions.Recursive + paths := filenameOptions.Filenames + for _, s := range paths { + switch { + case s == "-": + b.Stdin() + case strings.Index(s, "http://") == 0 || strings.Index(s, "https://") == 0: + url, err := url.Parse(s) + if err != nil { + b.errs = append(b.errs, fmt.Errorf("the URL passed to filename %q is not valid: %v", s, err)) + continue + } + b.URL(defaultHttpGetAttempts, url) + default: + if !recursive { + b.singleItemImplied = true + } + b.Path(recursive, s) + } + } + if filenameOptions.Kustomize != "" { + b.paths = append(b.paths, &KustomizeVisitor{filenameOptions.Kustomize, + NewStreamVisitor(nil, b.mapper, filenameOptions.Kustomize, b.schema)}) + } + + if enforceNamespace { + b.RequireNamespace() + } + + return b +} + +// Unstructured updates the builder so that it will request and send unstructured +// objects. Unstructured objects preserve all fields sent by the server in a map format +// based on the object's JSON structure which means no data is lost when the client +// reads and then writes an object. Use this mode in preference to Internal unless you +// are working with Go types directly. +func (b *Builder) Unstructured() *Builder { + if b.mapper != nil { + b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use unstructured types")) + return b + } + b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper() + b.mapper = &mapper{ + localFn: b.isLocal, + restMapperFn: b.restMapperFn, + clientFn: b.getClient, + decoder: &metadataValidatingDecoder{unstructured.UnstructuredJSONScheme}, + } + + return b +} + +// WithScheme uses the scheme to manage typing, conversion (optional), and decoding. If decodingVersions +// is empty, then you can end up with internal types. You have been warned. +func (b *Builder) WithScheme(scheme *runtime.Scheme, decodingVersions ...schema.GroupVersion) *Builder { + if b.mapper != nil { + b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use internal types")) + return b + } + b.objectTyper = scheme + codecFactory := serializer.NewCodecFactory(scheme) + negotiatedSerializer := runtime.NegotiatedSerializer(codecFactory) + // if you specified versions, you're specifying a desire for external types, which you don't want to round-trip through + // internal types + if len(decodingVersions) > 0 { + negotiatedSerializer = codecFactory.WithoutConversion() + } + b.negotiatedSerializer = negotiatedSerializer + + b.mapper = &mapper{ + localFn: b.isLocal, + restMapperFn: b.restMapperFn, + clientFn: b.getClient, + decoder: codecFactory.UniversalDecoder(decodingVersions...), + } + + return b +} + +// LocalParam calls Local() if local is true. +func (b *Builder) LocalParam(local bool) *Builder { + if local { + b.Local() + } + return b +} + +// Local will avoid asking the server for results. +func (b *Builder) Local() *Builder { + b.local = true + return b +} + +func (b *Builder) isLocal() bool { + return b.local +} + +// Mapper returns a copy of the current mapper. +func (b *Builder) Mapper() *mapper { + mapper := *b.mapper + return &mapper +} + +// URL accepts a number of URLs directly. +func (b *Builder) URL(httpAttemptCount int, urls ...*url.URL) *Builder { + for _, u := range urls { + b.paths = append(b.paths, &URLVisitor{ + URL: u, + StreamVisitor: NewStreamVisitor(nil, b.mapper, u.String(), b.schema), + HttpAttemptCount: httpAttemptCount, + }) + } + return b +} + +// Stdin will read objects from the standard input. If ContinueOnError() is set +// prior to this method being called, objects in the stream that are unrecognized +// will be ignored (but logged at V(2)). +func (b *Builder) Stdin() *Builder { + b.stream = true + b.paths = append(b.paths, FileVisitorForSTDIN(b.mapper, b.schema)) + return b +} + +// Stream will read objects from the provided reader, and if an error occurs will +// include the name string in the error message. If ContinueOnError() is set +// prior to this method being called, objects in the stream that are unrecognized +// will be ignored (but logged at V(2)). +func (b *Builder) Stream(r io.Reader, name string) *Builder { + b.stream = true + b.paths = append(b.paths, NewStreamVisitor(r, b.mapper, name, b.schema)) + return b +} + +// Path accepts a set of paths that may be files, directories (all can containing +// one or more resources). Creates a FileVisitor for each file and then each +// FileVisitor is streaming the content to a StreamVisitor. If ContinueOnError() is set +// prior to this method being called, objects on the path that are unrecognized will be +// ignored (but logged at V(2)). +func (b *Builder) Path(recursive bool, paths ...string) *Builder { + for _, p := range paths { + _, err := os.Stat(p) + if os.IsNotExist(err) { + b.errs = append(b.errs, fmt.Errorf("the path %q does not exist", p)) + continue + } + if err != nil { + b.errs = append(b.errs, fmt.Errorf("the path %q cannot be accessed: %v", p, err)) + continue + } + + visitors, err := ExpandPathsToFileVisitors(b.mapper, p, recursive, FileExtensions, b.schema) + if err != nil { + b.errs = append(b.errs, fmt.Errorf("error reading %q: %v", p, err)) + } + if len(visitors) > 1 { + b.dir = true + } + + b.paths = append(b.paths, visitors...) + } + if len(b.paths) == 0 && len(b.errs) == 0 { + b.errs = append(b.errs, fmt.Errorf("error reading %v: recognized file extensions are %v", paths, FileExtensions)) + } + return b +} + +// ResourceTypes is a list of types of resources to operate on, when listing objects on +// the server or retrieving objects that match a selector. +func (b *Builder) ResourceTypes(types ...string) *Builder { + b.resources = append(b.resources, types...) + return b +} + +// ResourceNames accepts a default type and one or more names, and creates tuples of +// resources +func (b *Builder) ResourceNames(resource string, names ...string) *Builder { + for _, name := range names { + // See if this input string is of type/name format + tuple, ok, err := splitResourceTypeName(name) + if err != nil { + b.errs = append(b.errs, err) + return b + } + + if ok { + b.resourceTuples = append(b.resourceTuples, tuple) + continue + } + if len(resource) == 0 { + b.errs = append(b.errs, fmt.Errorf("the argument %q must be RESOURCE/NAME", name)) + continue + } + + // Use the given default type to create a resource tuple + b.resourceTuples = append(b.resourceTuples, resourceTuple{Resource: resource, Name: name}) + } + return b +} + +// LabelSelectorParam defines a selector that should be applied to the object types to load. +// This will not affect files loaded from disk or URL. If the parameter is empty it is +// a no-op - to select all resources invoke `b.LabelSelector(labels.Everything.String)`. +func (b *Builder) LabelSelectorParam(s string) *Builder { + selector := strings.TrimSpace(s) + if len(selector) == 0 { + return b + } + if b.selectAll { + b.errs = append(b.errs, fmt.Errorf("found non-empty label selector %q with previously set 'all' parameter. ", s)) + return b + } + return b.LabelSelector(selector) +} + +// LabelSelector accepts a selector directly and will filter the resulting list by that object. +// Use LabelSelectorParam instead for user input. +func (b *Builder) LabelSelector(selector string) *Builder { + if len(selector) == 0 { + return b + } + + b.labelSelector = &selector + return b +} + +// FieldSelectorParam defines a selector that should be applied to the object types to load. +// This will not affect files loaded from disk or URL. If the parameter is empty it is +// a no-op - to select all resources. +func (b *Builder) FieldSelectorParam(s string) *Builder { + s = strings.TrimSpace(s) + if len(s) == 0 { + return b + } + if b.selectAll { + b.errs = append(b.errs, fmt.Errorf("found non-empty field selector %q with previously set 'all' parameter. ", s)) + return b + } + b.fieldSelector = &s + return b +} + +// ExportParam accepts the export boolean for these resources +func (b *Builder) ExportParam(export bool) *Builder { + b.export = export + 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 { + b.namespace = namespace + return b +} + +// DefaultNamespace instructs the builder to set the namespace value for any object found +// to NamespaceParam() if empty. +func (b *Builder) DefaultNamespace() *Builder { + b.defaultNamespace = true + return b +} + +// AllNamespaces instructs the builder to metav1.NamespaceAll as a namespace to request resources +// across all of the namespace. This overrides the namespace set by NamespaceParam(). +func (b *Builder) AllNamespaces(allNamespace bool) *Builder { + if allNamespace { + b.namespace = metav1.NamespaceAll + } + b.allNamespace = allNamespace + return b +} + +// RequireNamespace instructs the builder to set the namespace value for any object found +// to NamespaceParam() if empty, and if the value on the resource does not match +// NamespaceParam() an error will be returned. +func (b *Builder) RequireNamespace() *Builder { + b.requireNamespace = true + return b +} + +// RequestChunksOf attempts to load responses from the server in batches of size limit +// to avoid long delays loading and transferring very large lists. If unset defaults to +// no chunking. +func (b *Builder) RequestChunksOf(chunkSize int64) *Builder { + b.limitChunks = chunkSize + return b +} + +// TransformRequests alters API calls made by clients requested from this builder. Pass +// an empty list to clear modifiers. +func (b *Builder) TransformRequests(opts ...RequestTransform) *Builder { + b.requestTransforms = opts + return b +} + +// SelectEverythingParam +func (b *Builder) SelectAllParam(selectAll bool) *Builder { + if selectAll && (b.labelSelector != nil || b.fieldSelector != nil) { + b.errs = append(b.errs, fmt.Errorf("setting 'all' parameter but found a non empty selector. ")) + return b + } + b.selectAll = selectAll + return b +} + +// ResourceTypeOrNameArgs indicates that the builder should accept arguments +// of the form `([,,...]| [,,...])`. When one argument is +// received, the types provided will be retrieved from the server (and be comma delimited). +// When two or more arguments are received, they must be a single type and resource name(s). +// The allowEmptySelector permits to select all the resources (via Everything func). +func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string) *Builder { + args = normalizeMultipleResourcesArgs(args) + if ok, err := hasCombinedTypeArgs(args); ok { + if err != nil { + b.errs = append(b.errs, err) + return b + } + for _, s := range args { + tuple, ok, err := splitResourceTypeName(s) + if err != nil { + b.errs = append(b.errs, err) + return b + } + if ok { + b.resourceTuples = append(b.resourceTuples, tuple) + } + } + return b + } + if len(args) > 0 { + // Try replacing aliases only in types + args[0] = b.ReplaceAliases(args[0]) + } + switch { + case len(args) > 2: + b.names = append(b.names, args[1:]...) + b.ResourceTypes(SplitResourceArgument(args[0])...) + 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])...) + if b.labelSelector == nil && allowEmptySelector { + selector := labels.Everything().String() + b.labelSelector = &selector + } + case len(args) == 0: + default: + b.errs = append(b.errs, fmt.Errorf("arguments must consist of a resource or a resource and name")) + } + return b +} + +// ReplaceAliases accepts an argument and tries to expand any existing +// aliases found in it +func (b *Builder) ReplaceAliases(input string) string { + replaced := []string{} + for _, arg := range strings.Split(input, ",") { + if b.categoryExpanderFn == nil { + continue + } + categoryExpander, err := b.categoryExpanderFn() + if err != nil { + b.AddError(err) + continue + } + + if resources, ok := categoryExpander.Expand(arg); ok { + asStrings := []string{} + for _, resource := range resources { + if len(resource.Group) == 0 { + asStrings = append(asStrings, resource.Resource) + continue + } + asStrings = append(asStrings, resource.Resource+"."+resource.Group) + } + arg = strings.Join(asStrings, ",") + } + replaced = append(replaced, arg) + } + return strings.Join(replaced, ",") +} + +func hasCombinedTypeArgs(args []string) (bool, error) { + hasSlash := 0 + for _, s := range args { + if strings.Contains(s, "/") { + hasSlash++ + } + } + switch { + case hasSlash > 0 && hasSlash == len(args): + return true, nil + case hasSlash > 0 && hasSlash != len(args): + baseCmd := "cmd" + if len(os.Args) > 0 { + baseCmdSlice := strings.Split(os.Args[0], "/") + baseCmd = baseCmdSlice[len(baseCmdSlice)-1] + } + return true, fmt.Errorf("there is no need to specify a resource type as a separate argument when passing arguments in resource/name form (e.g. '%s get resource/' instead of '%s get resource resource/'", baseCmd, baseCmd) + default: + return false, nil + } +} + +// Normalize args convert multiple resources to resource tuples, a,b,c d +// as a transform to a/d b/d c/d +func normalizeMultipleResourcesArgs(args []string) []string { + if len(args) >= 2 { + resources := []string{} + resources = append(resources, SplitResourceArgument(args[0])...) + if len(resources) > 1 { + names := []string{} + names = append(names, args[1:]...) + newArgs := []string{} + for _, resource := range resources { + for _, name := range names { + newArgs = append(newArgs, strings.Join([]string{resource, name}, "/")) + } + } + return newArgs + } + } + return args +} + +// splitResourceTypeName handles type/name resource formats and returns a resource tuple +// (empty or not), whether it successfully found one, and an error +func splitResourceTypeName(s string) (resourceTuple, bool, error) { + if !strings.Contains(s, "/") { + return resourceTuple{}, false, nil + } + seg := strings.Split(s, "/") + if len(seg) != 2 { + return resourceTuple{}, false, fmt.Errorf("arguments in resource/name form may not have more than one slash") + } + resource, name := seg[0], seg[1] + if len(resource) == 0 || len(name) == 0 || len(SplitResourceArgument(resource)) != 1 { + return resourceTuple{}, false, fmt.Errorf("arguments in resource/name form must have a single resource and name") + } + return resourceTuple{Resource: resource, Name: name}, true, nil +} + +// Flatten will convert any objects with a field named "Items" that is an array of runtime.Object +// compatible types into individual entries and give them their own items. The original object +// is not passed to any visitors. +func (b *Builder) Flatten() *Builder { + b.flatten = true + return b +} + +// Latest will fetch the latest copy of any objects loaded from URLs or files from the server. +func (b *Builder) Latest() *Builder { + b.latest = true + return b +} + +// RequireObject ensures that resulting infos have an object set. If false, resulting info may not have an object set. +func (b *Builder) RequireObject(require bool) *Builder { + b.requireObject = require + return b +} + +// ContinueOnError will attempt to load and visit as many objects as possible, even if some visits +// return errors or some objects cannot be loaded. The default behavior is to terminate after +// the first error is returned from a VisitorFunc. +func (b *Builder) ContinueOnError() *Builder { + b.continueOnError = true + return b +} + +// SingleResourceType will cause the builder to error if the user specifies more than a single type +// of resource. +func (b *Builder) SingleResourceType() *Builder { + b.singleResourceType = true + return b +} + +// mappingFor returns the RESTMapping for the Kind given, or the Kind referenced by the resource. +// Prefers a fully specified GroupVersionResource match. If one is not found, we match on a fully +// specified GroupVersionKind, or fallback to a match on GroupKind. +func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error) { + fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg) + gvk := schema.GroupVersionKind{} + restMapper, err := b.restMapperFn() + if err != nil { + return nil, err + } + + if fullySpecifiedGVR != nil { + gvk, _ = restMapper.KindFor(*fullySpecifiedGVR) + } + if gvk.Empty() { + gvk, _ = restMapper.KindFor(groupResource.WithVersion("")) + } + if !gvk.Empty() { + return restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + } + + fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg) + if fullySpecifiedGVK == nil { + gvk := groupKind.WithVersion("") + fullySpecifiedGVK = &gvk + } + + if !fullySpecifiedGVK.Empty() { + if mapping, err := restMapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil { + return mapping, nil + } + } + + mapping, err := restMapper.RESTMapping(groupKind, gvk.Version) + if err != nil { + // if we error out here, it is because we could not match a resource or a kind + // for the given argument. To maintain consistency with previous behavior, + // announce that a resource type could not be found. + // if the error is _not_ a *meta.NoKindMatchError, then we had trouble doing discovery, + // so we should return the original error since it may help a user diagnose what is actually wrong + if meta.IsNoMatchError(err) { + return nil, fmt.Errorf("the server doesn't have a resource type %q", groupResource.Resource) + } + return nil, err + } + + return mapping, nil +} + +func (b *Builder) resourceMappings() ([]*meta.RESTMapping, error) { + if len(b.resources) > 1 && b.singleResourceType { + return nil, fmt.Errorf("you may only specify a single resource type") + } + mappings := []*meta.RESTMapping{} + seen := map[schema.GroupVersionKind]bool{} + for _, r := range b.resources { + mapping, err := b.mappingFor(r) + if err != nil { + return nil, err + } + // This ensures the mappings for resources(shortcuts, plural) unique + if seen[mapping.GroupVersionKind] { + continue + } + seen[mapping.GroupVersionKind] = true + + mappings = append(mappings, mapping) + } + return mappings, nil +} + +func (b *Builder) resourceTupleMappings() (map[string]*meta.RESTMapping, error) { + mappings := make(map[string]*meta.RESTMapping) + canonical := make(map[schema.GroupVersionResource]struct{}) + for _, r := range b.resourceTuples { + if _, ok := mappings[r.Resource]; ok { + continue + } + mapping, err := b.mappingFor(r.Resource) + if err != nil { + return nil, err + } + + mappings[r.Resource] = mapping + canonical[mapping.Resource] = struct{}{} + } + if len(canonical) > 1 && b.singleResourceType { + return nil, fmt.Errorf("you may only specify a single resource type") + } + return mappings, nil +} + +func (b *Builder) visitorResult() *Result { + if len(b.errs) > 0 { + return &Result{err: utilerrors.NewAggregate(b.errs)} + } + + if b.selectAll { + selector := labels.Everything().String() + b.labelSelector = &selector + } + + // visit items specified by paths + if len(b.paths) != 0 { + return b.visitByPaths() + } + + // visit selectors + if b.labelSelector != nil || b.fieldSelector != nil { + return b.visitBySelector() + } + + // visit items specified by resource and name + if len(b.resourceTuples) != 0 { + return b.visitByResource() + } + + // visit items specified by name + if len(b.names) != 0 { + return b.visitByName() + } + + if len(b.resources) != 0 { + for _, r := range b.resources { + _, err := b.mappingFor(r) + if err != nil { + return &Result{err: err} + } + } + return &Result{err: fmt.Errorf("resource(s) were provided, but no name, label selector, or --all flag specified")} + } + return &Result{err: missingResourceError} +} + +func (b *Builder) visitBySelector() *Result { + result := &Result{ + targetsSingleItems: false, + } + + if len(b.names) != 0 { + return result.withError(fmt.Errorf("name cannot be provided when a selector is specified")) + } + if len(b.resourceTuples) != 0 { + return result.withError(fmt.Errorf("selectors and the all flag cannot be used when passing resource/name arguments")) + } + if len(b.resources) == 0 { + return result.withError(fmt.Errorf("at least one resource must be specified to use a selector")) + } + mappings, err := b.resourceMappings() + if err != nil { + result.err = err + return result + } + + var labelSelector, fieldSelector string + if b.labelSelector != nil { + labelSelector = *b.labelSelector + } + if b.fieldSelector != nil { + fieldSelector = *b.fieldSelector + } + + visitors := []Visitor{} + for _, mapping := range mappings { + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) + if err != nil { + result.err = err + return result + } + selectorNamespace := b.namespace + if mapping.Scope.Name() != meta.RESTScopeNameNamespace { + selectorNamespace = "" + } + visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, labelSelector, fieldSelector, b.export, b.limitChunks)) + } + if b.continueOnError { + result.visitor = EagerVisitorList(visitors) + } else { + result.visitor = VisitorList(visitors) + } + result.sources = visitors + return result +} + +func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) { + var ( + client RESTClient + err error + ) + + switch { + case b.fakeClientFn != nil: + client, err = b.fakeClientFn(gv) + case b.negotiatedSerializer != nil: + client, err = b.clientConfigFn.clientForGroupVersion(gv, b.negotiatedSerializer) + default: + client, err = b.clientConfigFn.unstructuredClientForGroupVersion(gv) + } + + if err != nil { + return nil, err + } + + return NewClientWithOptions(client, b.requestTransforms...), nil +} + +func (b *Builder) visitByResource() *Result { + // if b.singleItemImplied is false, this could be by default, so double-check length + // of resourceTuples to determine if in fact it is singleItemImplied or not + isSingleItemImplied := b.singleItemImplied + if !isSingleItemImplied { + isSingleItemImplied = len(b.resourceTuples) == 1 + } + + result := &Result{ + singleItemImplied: isSingleItemImplied, + targetsSingleItems: true, + } + + if len(b.resources) != 0 { + return result.withError(fmt.Errorf("you may not specify individual resources and bulk resources in the same call")) + } + + // retrieve one client for each resource + mappings, err := b.resourceTupleMappings() + if err != nil { + result.err = err + return result + } + clients := make(map[string]RESTClient) + for _, mapping := range mappings { + s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource.Resource) + if _, ok := clients[s]; ok { + continue + } + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) + if err != nil { + result.err = err + return result + } + clients[s] = client + } + + items := []Visitor{} + for _, tuple := range b.resourceTuples { + mapping, ok := mappings[tuple.Resource] + if !ok { + return result.withError(fmt.Errorf("resource %q is not recognized: %v", tuple.Resource, mappings)) + } + s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource.Resource) + client, ok := clients[s] + if !ok { + return result.withError(fmt.Errorf("could not find a client for resource %q", tuple.Resource)) + } + + selectorNamespace := b.namespace + if mapping.Scope.Name() != meta.RESTScopeNameNamespace { + selectorNamespace = "" + } else { + if len(b.namespace) == 0 { + errMsg := "namespace may not be empty when retrieving a resource by name" + if b.allNamespace { + errMsg = "a resource cannot be retrieved by name across all namespaces" + } + return result.withError(fmt.Errorf(errMsg)) + } + } + + info := &Info{ + Client: client, + Mapping: mapping, + Namespace: selectorNamespace, + Name: tuple.Name, + Export: b.export, + } + items = append(items, info) + } + + var visitors Visitor + if b.continueOnError { + visitors = EagerVisitorList(items) + } else { + visitors = VisitorList(items) + } + result.visitor = visitors + result.sources = items + return result +} + +func (b *Builder) visitByName() *Result { + result := &Result{ + singleItemImplied: len(b.names) == 1, + targetsSingleItems: true, + } + + if len(b.paths) != 0 { + return result.withError(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 { + return result.withError(fmt.Errorf("you must provide a resource and a resource name together")) + } + if len(b.resources) > 1 { + return result.withError(fmt.Errorf("you must specify only one resource")) + } + + mappings, err := b.resourceMappings() + if err != nil { + result.err = err + return result + } + mapping := mappings[0] + + client, err := b.getClient(mapping.GroupVersionKind.GroupVersion()) + if err != nil { + result.err = err + return result + } + + selectorNamespace := b.namespace + if mapping.Scope.Name() != meta.RESTScopeNameNamespace { + selectorNamespace = "" + } else { + if len(b.namespace) == 0 { + errMsg := "namespace may not be empty when retrieving a resource by name" + if b.allNamespace { + errMsg = "a resource cannot be retrieved by name across all namespaces" + } + return result.withError(fmt.Errorf(errMsg)) + } + } + + visitors := []Visitor{} + for _, name := range b.names { + info := &Info{ + Client: client, + Mapping: mapping, + Namespace: selectorNamespace, + Name: name, + Export: b.export, + } + visitors = append(visitors, info) + } + result.visitor = VisitorList(visitors) + result.sources = visitors + return result +} + +func (b *Builder) visitByPaths() *Result { + result := &Result{ + singleItemImplied: !b.dir && !b.stream && len(b.paths) == 1, + targetsSingleItems: true, + } + + if len(b.resources) != 0 { + return result.withError(fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify resource arguments as well")) + } + if len(b.names) != 0 { + return result.withError(fmt.Errorf("name cannot be provided when a path is specified")) + } + if len(b.resourceTuples) != 0 { + return result.withError(fmt.Errorf("resource/name arguments cannot be provided when a path is specified")) + } + + var visitors Visitor + if b.continueOnError { + visitors = EagerVisitorList(b.paths) + } else { + visitors = VisitorList(b.paths) + } + + if b.flatten { + visitors = NewFlattenListVisitor(visitors, b.objectTyper, b.mapper) + } + + // only items from disk can be refetched + if b.latest { + // must set namespace prior to fetching + if b.defaultNamespace { + visitors = NewDecoratedVisitor(visitors, SetNamespace(b.namespace)) + } + visitors = NewDecoratedVisitor(visitors, RetrieveLatest) + } + if b.labelSelector != nil { + selector, err := labels.Parse(*b.labelSelector) + if err != nil { + return result.withError(fmt.Errorf("the provided selector %q is not valid: %v", *b.labelSelector, err)) + } + visitors = NewFilteredVisitor(visitors, FilterByLabelSelector(selector)) + } + result.visitor = visitors + result.sources = b.paths + return result +} + +// Do returns a Result object with a Visitor for the resources identified by the Builder. +// The visitor will respect the error behavior specified by ContinueOnError. Note that stream +// inputs are consumed by the first execution - use Infos() or Object() on the Result to capture a list +// for further iteration. +func (b *Builder) Do() *Result { + r := b.visitorResult() + r.mapper = b.Mapper() + if r.err != nil { + return r + } + if b.flatten { + r.visitor = NewFlattenListVisitor(r.visitor, b.objectTyper, b.mapper) + } + helpers := []VisitorFunc{} + if b.defaultNamespace { + helpers = append(helpers, SetNamespace(b.namespace)) + } + if b.requireNamespace { + helpers = append(helpers, RequireNamespace(b.namespace)) + } + helpers = append(helpers, FilterNamespace) + if b.requireObject { + helpers = append(helpers, RetrieveLazy) + } + if b.continueOnError { + r.visitor = NewDecoratedVisitor(ContinueOnErrorVisitor{r.visitor}, helpers...) + } else { + r.visitor = NewDecoratedVisitor(r.visitor, helpers...) + } + return r +} + +// SplitResourceArgument splits the argument with commas and returns unique +// strings in the original order. +func SplitResourceArgument(arg string) []string { + out := []string{} + set := sets.NewString() + for _, s := range strings.Split(arg, ",") { + if set.Has(s) { + continue + } + set.Insert(s) + out = append(out, s) + } + return out +} + +// HasNames returns true if the provided args contain resource names +func HasNames(args []string) (bool, error) { + args = normalizeMultipleResourcesArgs(args) + hasCombinedTypes, err := hasCombinedTypeArgs(args) + if err != nil { + return false, err + } + return hasCombinedTypes || len(args) > 1, nil +} + +type cachingRESTMapperFunc struct { + delegate RESTMapperFunc + + lock sync.Mutex + cached meta.RESTMapper +} + +func (c *cachingRESTMapperFunc) ToRESTMapper() (meta.RESTMapper, error) { + c.lock.Lock() + defer c.lock.Unlock() + if c.cached != nil { + return c.cached, nil + } + + ret, err := c.delegate() + if err != nil { + return nil, err + } + c.cached = ret + return c.cached, nil +} + +type cachingCategoryExpanderFunc struct { + delegate CategoryExpanderFunc + + lock sync.Mutex + cached restmapper.CategoryExpander +} + +func (c *cachingCategoryExpanderFunc) ToCategoryExpander() (restmapper.CategoryExpander, error) { + c.lock.Lock() + defer c.lock.Unlock() + if c.cached != nil { + return c.cached, nil + } + + ret, err := c.delegate() + if err != nil { + return nil, err + } + c.cached = ret + return c.cached, nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/client.go b/vendor/k8s.io/cli-runtime/pkg/resource/client.go new file mode 100644 index 000000000..46380207f --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/client.go @@ -0,0 +1,58 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" +) + +// TODO require negotiatedSerializer. leaving it optional lets us plumb current behavior and deal with the difference after major plumbing is complete +func (clientConfigFn ClientConfigFunc) clientForGroupVersion(gv schema.GroupVersion, negotiatedSerializer runtime.NegotiatedSerializer) (RESTClient, error) { + cfg, err := clientConfigFn() + if err != nil { + return nil, err + } + if negotiatedSerializer != nil { + cfg.ContentConfig.NegotiatedSerializer = negotiatedSerializer + } + cfg.GroupVersion = &gv + if len(gv.Group) == 0 { + cfg.APIPath = "/api" + } else { + cfg.APIPath = "/apis" + } + + return rest.RESTClientFor(cfg) +} + +func (clientConfigFn ClientConfigFunc) unstructuredClientForGroupVersion(gv schema.GroupVersion) (RESTClient, error) { + cfg, err := clientConfigFn() + if err != nil { + return nil, err + } + cfg.ContentConfig = UnstructuredPlusDefaultContentConfig() + cfg.GroupVersion = &gv + if len(gv.Group) == 0 { + cfg.APIPath = "/api" + } else { + cfg.APIPath = "/apis" + } + + return rest.RESTClientFor(cfg) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/doc.go b/vendor/k8s.io/cli-runtime/pkg/resource/doc.go new file mode 100644 index 000000000..f83fdcbf8 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resource assists clients in dealing with RESTful objects that match the +// Kubernetes API conventions. The Helper object provides simple CRUD operations +// on resources. The Visitor interface makes it easy to deal with multiple resources +// in bulk for retrieval and operation. The Builder object simplifies converting +// standard command line arguments and parameters into a Visitor that can iterate +// over all of the identified resources, whether on the server or on the local +// filesystem. +package resource // import "k8s.io/cli-runtime/pkg/resource" diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/fake.go b/vendor/k8s.io/cli-runtime/pkg/resource/fake.go new file mode 100644 index 000000000..276c343e2 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/fake.go @@ -0,0 +1,40 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/restmapper" +) + +// FakeCategoryExpander is for testing only +var FakeCategoryExpander restmapper.CategoryExpander = restmapper.SimpleCategoryExpander{ + Expansions: map[string][]schema.GroupResource{ + "all": { + {Group: "", Resource: "pods"}, + {Group: "", Resource: "replicationcontrollers"}, + {Group: "", Resource: "services"}, + {Group: "apps", Resource: "statefulsets"}, + {Group: "autoscaling", Resource: "horizontalpodautoscalers"}, + {Group: "batch", Resource: "jobs"}, + {Group: "batch", Resource: "cronjobs"}, + {Group: "extensions", Resource: "daemonsets"}, + {Group: "extensions", Resource: "deployments"}, + {Group: "extensions", Resource: "replicasets"}, + }, + }, +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/helper.go b/vendor/k8s.io/cli-runtime/pkg/resource/helper.go new file mode 100644 index 000000000..851351cf1 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/helper.go @@ -0,0 +1,185 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "strconv" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" +) + +var metadataAccessor = meta.NewAccessor() + +// Helper provides methods for retrieving or mutating a RESTful +// resource. +type Helper struct { + // The name of this resource as the server would recognize it + Resource string + // A RESTClient capable of mutating this resource. + RESTClient RESTClient + // True if the resource type is scoped to namespaces + NamespaceScoped bool +} + +// NewHelper creates a Helper from a ResourceMapping +func NewHelper(client RESTClient, mapping *meta.RESTMapping) *Helper { + return &Helper{ + Resource: mapping.Resource.Resource, + RESTClient: client, + NamespaceScoped: mapping.Scope.Name() == meta.RESTScopeNameNamespace, + } +} + +func (m *Helper) Get(namespace, name string, export bool) (runtime.Object, error) { + req := m.RESTClient.Get(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + Name(name) + if export { + // TODO: I should be part of GetOptions + req.Param("export", strconv.FormatBool(export)) + } + return req.Do().Get() +} + +func (m *Helper) List(namespace, apiVersion string, export bool, options *metav1.ListOptions) (runtime.Object, error) { + req := m.RESTClient.Get(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + VersionedParams(options, metav1.ParameterCodec) + if export { + // TODO: I should be part of ListOptions + req.Param("export", strconv.FormatBool(export)) + } + return req.Do().Get() +} + +func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions) (watch.Interface, error) { + options.Watch = true + return m.RESTClient.Get(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + VersionedParams(options, metav1.ParameterCodec). + Watch() +} + +func (m *Helper) WatchSingle(namespace, name, resourceVersion string) (watch.Interface, error) { + return m.RESTClient.Get(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + VersionedParams(&metav1.ListOptions{ + ResourceVersion: resourceVersion, + Watch: true, + FieldSelector: fields.OneTermEqualSelector("metadata.name", name).String(), + }, metav1.ParameterCodec). + Watch() +} + +func (m *Helper) Delete(namespace, name string) (runtime.Object, error) { + return m.DeleteWithOptions(namespace, name, nil) +} + +func (m *Helper) DeleteWithOptions(namespace, name string, options *metav1.DeleteOptions) (runtime.Object, error) { + return m.RESTClient.Delete(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + Name(name). + Body(options). + Do(). + Get() +} + +func (m *Helper) Create(namespace string, modify bool, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) { + if options == nil { + options = &metav1.CreateOptions{} + } + if modify { + // Attempt to version the object based on client logic. + version, err := metadataAccessor.ResourceVersion(obj) + if err != nil { + // We don't know how to clear the version on this object, so send it to the server as is + return m.createResource(m.RESTClient, m.Resource, namespace, obj, options) + } + if version != "" { + if err := metadataAccessor.SetResourceVersion(obj, ""); err != nil { + return nil, err + } + } + } + + return m.createResource(m.RESTClient, m.Resource, namespace, obj, options) +} + +func (m *Helper) createResource(c RESTClient, resource, namespace string, obj runtime.Object, options *metav1.CreateOptions) (runtime.Object, error) { + return c.Post(). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(resource). + VersionedParams(options, metav1.ParameterCodec). + Body(obj). + Do(). + Get() +} +func (m *Helper) Patch(namespace, name string, pt types.PatchType, data []byte, options *metav1.PatchOptions) (runtime.Object, error) { + if options == nil { + options = &metav1.PatchOptions{} + } + return m.RESTClient.Patch(pt). + NamespaceIfScoped(namespace, m.NamespaceScoped). + Resource(m.Resource). + Name(name). + VersionedParams(options, metav1.ParameterCodec). + Body(data). + Do(). + Get() +} + +func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Object) (runtime.Object, error) { + c := m.RESTClient + + // Attempt to version the object based on client logic. + version, err := metadataAccessor.ResourceVersion(obj) + if err != nil { + // We don't know how to version this object, so send it to the server as is + return m.replaceResource(c, m.Resource, namespace, name, obj) + } + if version == "" && overwrite { + // Retrieve the current version of the object to overwrite the server object + serverObj, err := c.Get().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(m.Resource).Name(name).Do().Get() + if err != nil { + // The object does not exist, but we want it to be created + return m.replaceResource(c, m.Resource, namespace, name, obj) + } + serverVersion, err := metadataAccessor.ResourceVersion(serverObj) + if err != nil { + return nil, err + } + if err := metadataAccessor.SetResourceVersion(obj, serverVersion); err != nil { + return nil, err + } + } + + return m.replaceResource(c, m.Resource, namespace, name, obj) +} + +func (m *Helper) replaceResource(c RESTClient, resource, namespace, name string, obj runtime.Object) (runtime.Object, error) { + return c.Put().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Name(name).Body(obj).Do().Get() +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/interfaces.go b/vendor/k8s.io/cli-runtime/pkg/resource/interfaces.go new file mode 100644 index 000000000..29d7b34ab --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/interfaces.go @@ -0,0 +1,103 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" +) + +type RESTClientGetter interface { + ToRESTConfig() (*rest.Config, error) + ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) + ToRESTMapper() (meta.RESTMapper, error) +} + +type ClientConfigFunc func() (*rest.Config, error) +type RESTMapperFunc func() (meta.RESTMapper, error) +type CategoryExpanderFunc func() (restmapper.CategoryExpander, error) + +// RESTClient is a client helper for dealing with RESTful resources +// in a generic way. +type RESTClient interface { + Get() *rest.Request + Post() *rest.Request + Patch(types.PatchType) *rest.Request + Delete() *rest.Request + Put() *rest.Request +} + +// RequestTransform is a function that is given a chance to modify the outgoing request. +type RequestTransform func(*rest.Request) + +// NewClientWithOptions wraps the provided RESTClient and invokes each transform on each +// newly created request. +func NewClientWithOptions(c RESTClient, transforms ...RequestTransform) RESTClient { + if len(transforms) == 0 { + return c + } + return &clientOptions{c: c, transforms: transforms} +} + +type clientOptions struct { + c RESTClient + transforms []RequestTransform +} + +func (c *clientOptions) modify(req *rest.Request) *rest.Request { + for _, transform := range c.transforms { + transform(req) + } + return req +} + +func (c *clientOptions) Get() *rest.Request { + return c.modify(c.c.Get()) +} + +func (c *clientOptions) Post() *rest.Request { + return c.modify(c.c.Post()) +} +func (c *clientOptions) Patch(t types.PatchType) *rest.Request { + return c.modify(c.c.Patch(t)) +} +func (c *clientOptions) Delete() *rest.Request { + return c.modify(c.c.Delete()) +} +func (c *clientOptions) Put() *rest.Request { + return c.modify(c.c.Put()) +} + +// ContentValidator is an interface that knows how to validate an API object serialized to a byte array. +type ContentValidator interface { + ValidateBytes(data []byte) error +} + +// Visitor lets clients walk a list of resources. +type Visitor interface { + Visit(VisitorFunc) error +} + +// VisitorFunc implements the Visitor interface for a matching function. +// If there was a problem walking a list of resources, the incoming error +// will describe the problem and the function can decide how to handle that error. +// A nil returned indicates to accept an error to continue loops even when errors happen. +// This is useful for ignoring certain kinds of errors or aggregating errors in some way. +type VisitorFunc func(*Info, error) error diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/mapper.go b/vendor/k8s.io/cli-runtime/pkg/resource/mapper.go new file mode 100644 index 000000000..962f37711 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/mapper.go @@ -0,0 +1,161 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "fmt" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// Mapper is a convenience struct for holding references to the interfaces +// needed to create Info for arbitrary objects. +type mapper struct { + // localFn indicates the call can't make server requests + localFn func() bool + + restMapperFn RESTMapperFunc + clientFn func(version schema.GroupVersion) (RESTClient, error) + decoder runtime.Decoder +} + +// InfoForData creates an Info object for the given data. An error is returned +// if any of the decoding or client lookup steps fail. Name and namespace will be +// set into Info if the mapping's MetadataAccessor can retrieve them. +func (m *mapper) infoForData(data []byte, source string) (*Info, error) { + obj, gvk, err := m.decoder.Decode(data, nil, nil) + if err != nil { + return nil, fmt.Errorf("unable to decode %q: %v", source, err) + } + + name, _ := metadataAccessor.Name(obj) + namespace, _ := metadataAccessor.Namespace(obj) + resourceVersion, _ := metadataAccessor.ResourceVersion(obj) + + ret := &Info{ + Source: source, + Namespace: namespace, + Name: name, + ResourceVersion: resourceVersion, + + Object: obj, + } + + if m.localFn == nil || !m.localFn() { + restMapper, err := m.restMapperFn() + if err != nil { + return nil, err + } + mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("unable to recognize %q: %v", source, err) + } + ret.Mapping = mapping + + client, err := m.clientFn(gvk.GroupVersion()) + if err != nil { + return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) + } + ret.Client = client + } + + return ret, nil +} + +// InfoForObject creates an Info object for the given Object. An error is returned +// if the object cannot be introspected. Name and namespace will be set into Info +// if the mapping's MetadataAccessor can retrieve them. +func (m *mapper) infoForObject(obj runtime.Object, typer runtime.ObjectTyper, preferredGVKs []schema.GroupVersionKind) (*Info, error) { + groupVersionKinds, _, err := typer.ObjectKinds(obj) + if err != nil { + return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) + } + + gvk := groupVersionKinds[0] + if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 { + gvk = preferredObjectKind(groupVersionKinds, preferredGVKs) + } + + name, _ := metadataAccessor.Name(obj) + namespace, _ := metadataAccessor.Namespace(obj) + resourceVersion, _ := metadataAccessor.ResourceVersion(obj) + ret := &Info{ + Namespace: namespace, + Name: name, + ResourceVersion: resourceVersion, + + Object: obj, + } + + if m.localFn == nil || !m.localFn() { + restMapper, err := m.restMapperFn() + if err != nil { + return nil, err + } + mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, fmt.Errorf("unable to recognize %v", err) + } + ret.Mapping = mapping + + client, err := m.clientFn(gvk.GroupVersion()) + if err != nil { + return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) + } + ret.Client = client + } + + return ret, nil +} + +// preferredObjectKind picks the possibility that most closely matches the priority list in this order: +// GroupVersionKind matches (exact match) +// GroupKind matches +// Group matches +func preferredObjectKind(possibilities []schema.GroupVersionKind, preferences []schema.GroupVersionKind) schema.GroupVersionKind { + // Exact match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility == priority { + return possibility + } + } + } + + // GroupKind match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility.GroupKind() == priority.GroupKind() { + return possibility + } + } + } + + // Group match + for _, priority := range preferences { + for _, possibility := range possibilities { + if possibility.Group == priority.Group { + return possibility + } + } + } + + // Just pick the first + return possibilities[0] +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/metadata_decoder.go b/vendor/k8s.io/cli-runtime/pkg/resource/metadata_decoder.go new file mode 100644 index 000000000..c79c6b5e0 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/metadata_decoder.go @@ -0,0 +1,59 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer/json" +) + +// hold a single instance of the case-sensitive decoder +var caseSensitiveJsonIterator = json.CaseSensitiveJsonIterator() + +// metadataValidatingDecoder wraps a decoder and additionally ensures metadata schema fields decode before returning an unstructured object +type metadataValidatingDecoder struct { + decoder runtime.Decoder +} + +func (m *metadataValidatingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := m.decoder.Decode(data, defaults, into) + + // if we already errored, return + if err != nil { + return obj, gvk, err + } + + // if we're not unstructured, return + if _, isUnstructured := obj.(runtime.Unstructured); !isUnstructured { + return obj, gvk, err + } + + // make sure the data can decode into ObjectMeta before we return, + // so we don't silently truncate schema errors in metadata later with accesser get/set calls + v := &metadataOnlyObject{} + if typedErr := caseSensitiveJsonIterator.Unmarshal(data, v); typedErr != nil { + return obj, gvk, typedErr + } + return obj, gvk, err +} + +type metadataOnlyObject struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/result.go b/vendor/k8s.io/cli-runtime/pkg/resource/result.go new file mode 100644 index 000000000..b8722afe6 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/result.go @@ -0,0 +1,242 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "fmt" + "reflect" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/watch" +) + +// ErrMatchFunc can be used to filter errors that may not be true failures. +type ErrMatchFunc func(error) bool + +// Result contains helper methods for dealing with the outcome of a Builder. +type Result struct { + err error + visitor Visitor + + sources []Visitor + singleItemImplied bool + targetsSingleItems bool + + mapper *mapper + ignoreErrors []utilerrors.Matcher + + // populated by a call to Infos + info []*Info +} + +// withError allows a fluent style for internal result code. +func (r *Result) withError(err error) *Result { + r.err = err + return r +} + +// TargetsSingleItems returns true if any of the builder arguments pointed +// to non-list calls (if the user explicitly asked for any object by name). +// This includes directories, streams, URLs, and resource name tuples. +func (r *Result) TargetsSingleItems() bool { + return r.targetsSingleItems +} + +// IgnoreErrors will filter errors that occur when by visiting the result +// (but not errors that occur by creating the result in the first place), +// eliminating any that match fns. This is best used in combination with +// Builder.ContinueOnError(), where the visitors accumulate errors and return +// them after visiting as a slice of errors. If no errors remain after +// filtering, the various visitor methods on Result will return nil for +// err. +func (r *Result) IgnoreErrors(fns ...ErrMatchFunc) *Result { + for _, fn := range fns { + r.ignoreErrors = append(r.ignoreErrors, utilerrors.Matcher(fn)) + } + return r +} + +// Mapper returns a copy of the builder's mapper. +func (r *Result) Mapper() *mapper { + return r.mapper +} + +// Err returns one or more errors (via a util.ErrorList) that occurred prior +// to visiting the elements in the visitor. To see all errors including those +// that occur during visitation, invoke Infos(). +func (r *Result) Err() error { + return r.err +} + +// Visit implements the Visitor interface on the items described in the Builder. +// Note that some visitor sources are not traversable more than once, or may +// return different results. If you wish to operate on the same set of resources +// multiple times, use the Infos() method. +func (r *Result) Visit(fn VisitorFunc) error { + if r.err != nil { + return r.err + } + err := r.visitor.Visit(fn) + return utilerrors.FilterOut(err, r.ignoreErrors...) +} + +// IntoSingleItemImplied sets the provided boolean pointer to true if the Builder input +// implies a single item, or multiple. +func (r *Result) IntoSingleItemImplied(b *bool) *Result { + *b = r.singleItemImplied + return r +} + +// Infos returns an array of all of the resource infos retrieved via traversal. +// Will attempt to traverse the entire set of visitors only once, and will return +// a cached list on subsequent calls. +func (r *Result) Infos() ([]*Info, error) { + if r.err != nil { + return nil, r.err + } + if r.info != nil { + return r.info, nil + } + + infos := []*Info{} + err := r.visitor.Visit(func(info *Info, err error) error { + if err != nil { + return err + } + infos = append(infos, info) + return nil + }) + err = utilerrors.FilterOut(err, r.ignoreErrors...) + + r.info, r.err = infos, err + return infos, err +} + +// Object returns a single object representing the output of a single visit to all +// found resources. If the Builder was a singular context (expected to return a +// single resource by user input) and only a single resource was found, the resource +// will be returned as is. Otherwise, the returned resources will be part of an +// v1.List. The ResourceVersion of the v1.List will be set only if it is identical +// across all infos returned. +func (r *Result) Object() (runtime.Object, error) { + infos, err := r.Infos() + if err != nil { + return nil, err + } + + versions := sets.String{} + objects := []runtime.Object{} + for _, info := range infos { + if info.Object != nil { + objects = append(objects, info.Object) + versions.Insert(info.ResourceVersion) + } + } + + if len(objects) == 1 { + if r.singleItemImplied { + return objects[0], nil + } + // if the item is a list already, don't create another list + if meta.IsListType(objects[0]) { + return objects[0], nil + } + } + + version := "" + if len(versions) == 1 { + version = versions.List()[0] + } + + return toV1List(objects, version), err +} + +// Compile time check to enforce that list implements the necessary interface +var _ metav1.ListInterface = &v1.List{} +var _ metav1.ListMetaAccessor = &v1.List{} + +// toV1List takes a slice of Objects + their version, and returns +// a v1.List Object containing the objects in the Items field +func toV1List(objects []runtime.Object, version string) runtime.Object { + raw := []runtime.RawExtension{} + for _, o := range objects { + raw = append(raw, runtime.RawExtension{Object: o}) + } + return &v1.List{ + ListMeta: metav1.ListMeta{ + ResourceVersion: version, + }, + Items: raw, + } +} + +// ResourceMapping returns a single meta.RESTMapping representing the +// resources located by the builder, or an error if more than one +// mapping was found. +func (r *Result) ResourceMapping() (*meta.RESTMapping, error) { + if r.err != nil { + return nil, r.err + } + mappings := map[schema.GroupVersionResource]*meta.RESTMapping{} + for i := range r.sources { + m, ok := r.sources[i].(ResourceMapping) + if !ok { + return nil, fmt.Errorf("a resource mapping could not be loaded from %v", reflect.TypeOf(r.sources[i])) + } + mapping := m.ResourceMapping() + mappings[mapping.Resource] = mapping + } + if len(mappings) != 1 { + return nil, fmt.Errorf("expected only a single resource type") + } + for _, mapping := range mappings { + return mapping, nil + } + return nil, nil +} + +// Watch retrieves changes that occur on the server to the specified resource. +// It currently supports watching a single source - if the resource source +// (selectors or pure types) can be watched, they will be, otherwise the list +// will be visited (equivalent to the Infos() call) and if there is a single +// resource present, it will be watched, otherwise an error will be returned. +func (r *Result) Watch(resourceVersion string) (watch.Interface, error) { + if r.err != nil { + return nil, r.err + } + if len(r.sources) != 1 { + return nil, fmt.Errorf("you may only watch a single resource or type of resource at a time") + } + w, ok := r.sources[0].(Watchable) + if !ok { + info, err := r.Infos() + if err != nil { + return nil, err + } + if len(info) != 1 { + return nil, fmt.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", len(info)) + } + return info[0].Watch(resourceVersion) + } + return w.Watch(resourceVersion) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/scheme.go b/vendor/k8s.io/cli-runtime/pkg/resource/scheme.go new file mode 100644 index 000000000..0a47d1596 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/scheme.go @@ -0,0 +1,82 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "encoding/json" + "io" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" +) + +// dynamicCodec is a codec that wraps the standard unstructured codec +// with special handling for Status objects. +// Deprecated only used by test code and its wrong +type dynamicCodec struct{} + +func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { + obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj) + if err != nil { + return nil, nil, err + } + + if strings.ToLower(gvk.Kind) == "status" && gvk.Version == "v1" && (gvk.Group == "" || gvk.Group == "meta.k8s.io") { + if _, ok := obj.(*metav1.Status); !ok { + obj = &metav1.Status{} + err := json.Unmarshal(data, obj) + if err != nil { + return nil, nil, err + } + } + } + + return obj, gvk, nil +} + +func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error { + // There is no need to handle runtime.CacheableObject, as we only + // fallback to other encoders here. + return unstructured.UnstructuredJSONScheme.Encode(obj, w) +} + +// Identifier implements runtime.Encoder interface. +func (dynamicCodec) Identifier() runtime.Identifier { + return unstructured.UnstructuredJSONScheme.Identifier() +} + +// UnstructuredPlusDefaultContentConfig returns a rest.ContentConfig for dynamic types. It includes enough codecs to act as a "normal" +// serializer for the rest.client with options, status and the like. +func UnstructuredPlusDefaultContentConfig() rest.ContentConfig { + // TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need + // to talk to a kubernetes server + jsonInfo, _ := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) + + jsonInfo.Serializer = dynamicCodec{} + jsonInfo.PrettySerializer = nil + return rest.ContentConfig{ + AcceptContentTypes: runtime.ContentTypeJSON, + ContentType: runtime.ContentTypeJSON, + NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo), + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/selector.go b/vendor/k8s.io/cli-runtime/pkg/resource/selector.go new file mode 100644 index 000000000..0c0bdbec4 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/selector.go @@ -0,0 +1,118 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" +) + +// Selector is a Visitor for resources that match a label selector. +type Selector struct { + Client RESTClient + Mapping *meta.RESTMapping + Namespace string + LabelSelector string + FieldSelector string + Export bool + LimitChunks int64 +} + +// NewSelector creates a resource selector which hides details of getting items by their label selector. +func NewSelector(client RESTClient, mapping *meta.RESTMapping, namespace, labelSelector, fieldSelector string, export bool, limitChunks int64) *Selector { + return &Selector{ + Client: client, + Mapping: mapping, + Namespace: namespace, + LabelSelector: labelSelector, + FieldSelector: fieldSelector, + Export: export, + LimitChunks: limitChunks, + } +} + +// Visit implements Visitor and uses request chunking by default. +func (r *Selector) Visit(fn VisitorFunc) error { + var continueToken string + for { + list, err := NewHelper(r.Client, r.Mapping).List( + r.Namespace, + r.ResourceMapping().GroupVersionKind.GroupVersion().String(), + r.Export, + &metav1.ListOptions{ + LabelSelector: r.LabelSelector, + FieldSelector: r.FieldSelector, + Limit: r.LimitChunks, + Continue: continueToken, + }, + ) + if err != nil { + if errors.IsResourceExpired(err) { + return err + } + if errors.IsBadRequest(err) || errors.IsNotFound(err) { + if se, ok := err.(*errors.StatusError); ok { + // modify the message without hiding this is an API error + if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 { + se.ErrStatus.Message = fmt.Sprintf("Unable to list %q: %v", r.Mapping.Resource, se.ErrStatus.Message) + } else { + se.ErrStatus.Message = fmt.Sprintf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, se.ErrStatus.Message) + } + return se + } + if len(r.LabelSelector) == 0 && len(r.FieldSelector) == 0 { + return fmt.Errorf("Unable to list %q: %v", r.Mapping.Resource, err) + } + return fmt.Errorf("Unable to find %q that match label selector %q, field selector %q: %v", r.Mapping.Resource, r.LabelSelector, r.FieldSelector, err) + } + return err + } + resourceVersion, _ := metadataAccessor.ResourceVersion(list) + nextContinueToken, _ := metadataAccessor.Continue(list) + info := &Info{ + Client: r.Client, + Mapping: r.Mapping, + + Namespace: r.Namespace, + ResourceVersion: resourceVersion, + + Object: list, + } + + if err := fn(info, nil); err != nil { + return err + } + if len(nextContinueToken) == 0 { + return nil + } + continueToken = nextContinueToken + } +} + +func (r *Selector) Watch(resourceVersion string) (watch.Interface, error) { + return NewHelper(r.Client, r.Mapping).Watch(r.Namespace, r.ResourceMapping().GroupVersionKind.GroupVersion().String(), + &metav1.ListOptions{ResourceVersion: resourceVersion, LabelSelector: r.LabelSelector, FieldSelector: r.FieldSelector}) +} + +// ResourceMapping returns the mapping for this resource and implements ResourceMapping +func (r *Selector) ResourceMapping() *meta.RESTMapping { + return r.Mapping +} diff --git a/vendor/k8s.io/cli-runtime/pkg/resource/visitor.go b/vendor/k8s.io/cli-runtime/pkg/resource/visitor.go new file mode 100644 index 000000000..d9f4786b1 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/resource/visitor.go @@ -0,0 +1,762 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "bytes" + "fmt" + "io" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/text/encoding/unicode" + "golang.org/x/text/transform" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/cli-runtime/pkg/kustomize" + "sigs.k8s.io/kustomize/pkg/fs" +) + +const ( + constSTDINstr = "STDIN" + stopValidateMessage = "if you choose to ignore these errors, turn validation off with --validate=false" +) + +// Watchable describes a resource that can be watched for changes that occur on the server, +// beginning after the provided resource version. +type Watchable interface { + Watch(resourceVersion string) (watch.Interface, error) +} + +// ResourceMapping allows an object to return the resource mapping associated with +// the resource or resources it represents. +type ResourceMapping interface { + ResourceMapping() *meta.RESTMapping +} + +// Info contains temporary info to execute a REST call, or show the results +// of an already completed REST call. +type Info struct { + // Client will only be present if this builder was not local + Client RESTClient + // Mapping will only be present if this builder was not local + Mapping *meta.RESTMapping + + // Namespace will be set if the object is namespaced and has a specified value. + Namespace string + Name string + + // Optional, Source is the filename or URL to template file (.json or .yaml), + // or stdin to use to handle the resource + Source string + // Optional, this is the most recent value returned by the server if available. It will + // typically be in unstructured or internal forms, depending on how the Builder was + // defined. If retrieved from the server, the Builder expects the mapping client to + // decide the final form. Use the AsVersioned, AsUnstructured, and AsInternal helpers + // to alter the object versions. + Object runtime.Object + // Optional, this is the most recent resource version the server knows about for + // this type of resource. It may not match the resource version of the object, + // but if set it should be equal to or newer than the resource version of the + // object (however the server defines resource version). + ResourceVersion string + // Optional, should this resource be exported, stripped of cluster-specific and instance specific fields + Export bool +} + +// Visit implements Visitor +func (i *Info) Visit(fn VisitorFunc) error { + return fn(i, nil) +} + +// Get retrieves the object from the Namespace and Name fields +func (i *Info) Get() (err error) { + obj, err := NewHelper(i.Client, i.Mapping).Get(i.Namespace, i.Name, i.Export) + if err != nil { + if errors.IsNotFound(err) && len(i.Namespace) > 0 && i.Namespace != metav1.NamespaceDefault && i.Namespace != metav1.NamespaceAll { + err2 := i.Client.Get().AbsPath("api", "v1", "namespaces", i.Namespace).Do().Error() + if err2 != nil && errors.IsNotFound(err2) { + return err2 + } + } + return err + } + i.Object = obj + i.ResourceVersion, _ = metadataAccessor.ResourceVersion(obj) + return nil +} + +// Refresh updates the object with another object. If ignoreError is set +// the Object will be updated even if name, namespace, or resourceVersion +// attributes cannot be loaded from the object. +func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { + name, err := metadataAccessor.Name(obj) + if err != nil { + if !ignoreError { + return err + } + } else { + i.Name = name + } + namespace, err := metadataAccessor.Namespace(obj) + if err != nil { + if !ignoreError { + return err + } + } else { + i.Namespace = namespace + } + version, err := metadataAccessor.ResourceVersion(obj) + if err != nil { + if !ignoreError { + return err + } + } else { + i.ResourceVersion = version + } + i.Object = obj + return nil +} + +// ObjectName returns an approximate form of the resource's kind/name. +func (i *Info) ObjectName() string { + if i.Mapping != nil { + return fmt.Sprintf("%s/%s", i.Mapping.Resource.Resource, i.Name) + } + gvk := i.Object.GetObjectKind().GroupVersionKind() + if len(gvk.Group) == 0 { + return fmt.Sprintf("%s/%s", strings.ToLower(gvk.Kind), i.Name) + } + return fmt.Sprintf("%s.%s/%s\n", strings.ToLower(gvk.Kind), gvk.Group, i.Name) +} + +// String returns the general purpose string representation +func (i *Info) String() string { + basicInfo := fmt.Sprintf("Name: %q, Namespace: %q\nObject: %+q", i.Name, i.Namespace, i.Object) + if i.Mapping != nil { + mappingInfo := fmt.Sprintf("Resource: %q, GroupVersionKind: %q", i.Mapping.Resource.String(), + i.Mapping.GroupVersionKind.String()) + return fmt.Sprint(mappingInfo, "\n", basicInfo) + } + return basicInfo +} + +// Namespaced returns true if the object belongs to a namespace +func (i *Info) Namespaced() bool { + if i.Mapping != nil { + // if we have RESTMapper info, use it + return i.Mapping.Scope.Name() == meta.RESTScopeNameNamespace + } + // otherwise, use the presence of a namespace in the info as an indicator + return len(i.Namespace) > 0 +} + +// Watch returns server changes to this object after it was retrieved. +func (i *Info) Watch(resourceVersion string) (watch.Interface, error) { + return NewHelper(i.Client, i.Mapping).WatchSingle(i.Namespace, i.Name, resourceVersion) +} + +// ResourceMapping returns the mapping for this resource and implements ResourceMapping +func (i *Info) ResourceMapping() *meta.RESTMapping { + return i.Mapping +} + +// VisitorList implements Visit for the sub visitors it contains. The first error +// returned from a child Visitor will terminate iteration. +type VisitorList []Visitor + +// Visit implements Visitor +func (l VisitorList) Visit(fn VisitorFunc) error { + for i := range l { + if err := l[i].Visit(fn); err != nil { + return err + } + } + return nil +} + +// EagerVisitorList implements Visit for the sub visitors it contains. All errors +// will be captured and returned at the end of iteration. +type EagerVisitorList []Visitor + +// Visit implements Visitor, and gathers errors that occur during processing until +// all sub visitors have been visited. +func (l EagerVisitorList) Visit(fn VisitorFunc) error { + errs := []error(nil) + for i := range l { + if err := l[i].Visit(func(info *Info, err error) error { + if err != nil { + errs = append(errs, err) + return nil + } + if err := fn(info, nil); err != nil { + errs = append(errs, err) + } + return nil + }); err != nil { + errs = append(errs, err) + } + } + return utilerrors.NewAggregate(errs) +} + +func ValidateSchema(data []byte, schema ContentValidator) error { + if schema == nil { + return nil + } + if err := schema.ValidateBytes(data); err != nil { + return fmt.Errorf("error validating data: %v; %s", err, stopValidateMessage) + } + return nil +} + +// URLVisitor downloads the contents of a URL, and if successful, returns +// an info object representing the downloaded object. +type URLVisitor struct { + URL *url.URL + *StreamVisitor + HttpAttemptCount int +} + +func (v *URLVisitor) Visit(fn VisitorFunc) error { + body, err := readHttpWithRetries(httpgetImpl, time.Second, v.URL.String(), v.HttpAttemptCount) + if err != nil { + return err + } + defer body.Close() + v.StreamVisitor.Reader = body + return v.StreamVisitor.Visit(fn) +} + +// readHttpWithRetries tries to http.Get the v.URL retries times before giving up. +func readHttpWithRetries(get httpget, duration time.Duration, u string, attempts int) (io.ReadCloser, error) { + var err error + var body io.ReadCloser + if attempts <= 0 { + return nil, fmt.Errorf("http attempts must be greater than 0, was %d", attempts) + } + for i := 0; i < attempts; i++ { + var statusCode int + var status string + if i > 0 { + time.Sleep(duration) + } + + // Try to get the URL + statusCode, status, body, err = get(u) + + // Retry Errors + if err != nil { + continue + } + + // Error - Set the error condition from the StatusCode + if statusCode != http.StatusOK { + err = fmt.Errorf("unable to read URL %q, server reported %s, status code=%d", u, status, statusCode) + } + + if statusCode >= 500 && statusCode < 600 { + // Retry 500's + continue + } else { + // Don't retry other StatusCodes + break + } + } + return body, err +} + +// httpget Defines function to retrieve a url and return the results. Exists for unit test stubbing. +type httpget func(url string) (int, string, io.ReadCloser, error) + +// httpgetImpl Implements a function to retrieve a url and return the results. +func httpgetImpl(url string) (int, string, io.ReadCloser, error) { + resp, err := http.Get(url) + if err != nil { + return 0, "", nil, err + } + return resp.StatusCode, resp.Status, resp.Body, nil +} + +// DecoratedVisitor will invoke the decorators in order prior to invoking the visitor function +// passed to Visit. An error will terminate the visit. +type DecoratedVisitor struct { + visitor Visitor + decorators []VisitorFunc +} + +// NewDecoratedVisitor will create a visitor that invokes the provided visitor functions before +// the user supplied visitor function is invoked, giving them the opportunity to mutate the Info +// object or terminate early with an error. +func NewDecoratedVisitor(v Visitor, fn ...VisitorFunc) Visitor { + if len(fn) == 0 { + return v + } + return DecoratedVisitor{v, fn} +} + +// Visit implements Visitor +func (v DecoratedVisitor) Visit(fn VisitorFunc) error { + return v.visitor.Visit(func(info *Info, err error) error { + if err != nil { + return err + } + for i := range v.decorators { + if err := v.decorators[i](info, nil); err != nil { + return err + } + } + return fn(info, nil) + }) +} + +// ContinueOnErrorVisitor visits each item and, if an error occurs on +// any individual item, returns an aggregate error after all items +// are visited. +type ContinueOnErrorVisitor struct { + Visitor +} + +// Visit returns nil if no error occurs during traversal, a regular +// error if one occurs, or if multiple errors occur, an aggregate +// error. If the provided visitor fails on any individual item it +// will not prevent the remaining items from being visited. An error +// returned by the visitor directly may still result in some items +// not being visited. +func (v ContinueOnErrorVisitor) Visit(fn VisitorFunc) error { + errs := []error{} + err := v.Visitor.Visit(func(info *Info, err error) error { + if err != nil { + errs = append(errs, err) + return nil + } + if err := fn(info, nil); err != nil { + errs = append(errs, err) + } + return nil + }) + if err != nil { + errs = append(errs, err) + } + if len(errs) == 1 { + return errs[0] + } + return utilerrors.NewAggregate(errs) +} + +// FlattenListVisitor flattens any objects that runtime.ExtractList recognizes as a list +// - has an "Items" public field that is a slice of runtime.Objects or objects satisfying +// that interface - into multiple Infos. Returns nil in the case of no errors. +// When an error is hit on sub items (for instance, if a List contains an object that does +// not have a registered client or resource), returns an aggregate error. +type FlattenListVisitor struct { + visitor Visitor + typer runtime.ObjectTyper + mapper *mapper +} + +// NewFlattenListVisitor creates a visitor that will expand list style runtime.Objects +// into individual items and then visit them individually. +func NewFlattenListVisitor(v Visitor, typer runtime.ObjectTyper, mapper *mapper) Visitor { + return FlattenListVisitor{v, typer, mapper} +} + +func (v FlattenListVisitor) Visit(fn VisitorFunc) error { + return v.visitor.Visit(func(info *Info, err error) error { + if err != nil { + return err + } + if info.Object == nil { + return fn(info, nil) + } + if !meta.IsListType(info.Object) { + return fn(info, nil) + } + + items := []runtime.Object{} + itemsToProcess := []runtime.Object{info.Object} + + for i := 0; i < len(itemsToProcess); i++ { + currObj := itemsToProcess[i] + if !meta.IsListType(currObj) { + items = append(items, currObj) + continue + } + + currItems, err := meta.ExtractList(currObj) + if err != nil { + return err + } + if errs := runtime.DecodeList(currItems, v.mapper.decoder); len(errs) > 0 { + return utilerrors.NewAggregate(errs) + } + itemsToProcess = append(itemsToProcess, currItems...) + } + + // If we have a GroupVersionKind on the list, prioritize that when asking for info on the objects contained in the list + var preferredGVKs []schema.GroupVersionKind + if info.Mapping != nil && !info.Mapping.GroupVersionKind.Empty() { + preferredGVKs = append(preferredGVKs, info.Mapping.GroupVersionKind) + } + errs := []error{} + for i := range items { + item, err := v.mapper.infoForObject(items[i], v.typer, preferredGVKs) + if err != nil { + errs = append(errs, err) + continue + } + if len(info.ResourceVersion) != 0 { + item.ResourceVersion = info.ResourceVersion + } + if err := fn(item, nil); err != nil { + errs = append(errs, err) + } + } + return utilerrors.NewAggregate(errs) + + }) +} + +func ignoreFile(path string, extensions []string) bool { + if len(extensions) == 0 { + return false + } + ext := filepath.Ext(path) + for _, s := range extensions { + if s == ext { + return false + } + } + return true +} + +// FileVisitorForSTDIN return a special FileVisitor just for STDIN +func FileVisitorForSTDIN(mapper *mapper, schema ContentValidator) Visitor { + return &FileVisitor{ + Path: constSTDINstr, + StreamVisitor: NewStreamVisitor(nil, mapper, constSTDINstr, schema), + } +} + +// ExpandPathsToFileVisitors will return a slice of FileVisitors that will handle files from the provided path. +// After FileVisitors open the files, they will pass an io.Reader to a StreamVisitor to do the reading. (stdin +// is also taken care of). Paths argument also accepts a single file, and will return a single visitor +func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, extensions []string, schema ContentValidator) ([]Visitor, error) { + var visitors []Visitor + err := filepath.Walk(paths, func(path string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + if fi.IsDir() { + if path != paths && !recursive { + return filepath.SkipDir + } + return nil + } + // Don't check extension if the filepath was passed explicitly + if path != paths && ignoreFile(path, extensions) { + return nil + } + + visitor := &FileVisitor{ + Path: path, + StreamVisitor: NewStreamVisitor(nil, mapper, path, schema), + } + + visitors = append(visitors, visitor) + return nil + }) + + if err != nil { + return nil, err + } + return visitors, nil +} + +// FileVisitor is wrapping around a StreamVisitor, to handle open/close files +type FileVisitor struct { + Path string + *StreamVisitor +} + +// Visit in a FileVisitor is just taking care of opening/closing files +func (v *FileVisitor) Visit(fn VisitorFunc) error { + var f *os.File + if v.Path == constSTDINstr { + f = os.Stdin + } else { + var err error + f, err = os.Open(v.Path) + if err != nil { + return err + } + defer f.Close() + } + + // TODO: Consider adding a flag to force to UTF16, apparently some + // Windows tools don't write the BOM + utf16bom := unicode.BOMOverride(unicode.UTF8.NewDecoder()) + v.StreamVisitor.Reader = transform.NewReader(f, utf16bom) + + return v.StreamVisitor.Visit(fn) +} + +// KustomizeVisitor is wrapper around a StreamVisitor, to handle Kustomization directories +type KustomizeVisitor struct { + Path string + *StreamVisitor +} + +// Visit in a KustomizeVisitor gets the output of Kustomize build and save it in the Streamvisitor +func (v *KustomizeVisitor) Visit(fn VisitorFunc) error { + fSys := fs.MakeRealFS() + var out bytes.Buffer + err := kustomize.RunKustomizeBuild(&out, fSys, v.Path) + if err != nil { + return err + } + v.StreamVisitor.Reader = bytes.NewReader(out.Bytes()) + return v.StreamVisitor.Visit(fn) +} + +// StreamVisitor reads objects from an io.Reader and walks them. A stream visitor can only be +// visited once. +// TODO: depends on objects being in JSON format before being passed to decode - need to implement +// a stream decoder method on runtime.Codec to properly handle this. +type StreamVisitor struct { + io.Reader + *mapper + + Source string + Schema ContentValidator +} + +// NewStreamVisitor is a helper function that is useful when we want to change the fields of the struct but keep calls the same. +func NewStreamVisitor(r io.Reader, mapper *mapper, source string, schema ContentValidator) *StreamVisitor { + return &StreamVisitor{ + Reader: r, + mapper: mapper, + Source: source, + Schema: schema, + } +} + +// Visit implements Visitor over a stream. StreamVisitor is able to distinct multiple resources in one stream. +func (v *StreamVisitor) Visit(fn VisitorFunc) error { + d := yaml.NewYAMLOrJSONDecoder(v.Reader, 4096) + for { + ext := runtime.RawExtension{} + if err := d.Decode(&ext); err != nil { + if err == io.EOF { + return nil + } + return fmt.Errorf("error parsing %s: %v", v.Source, err) + } + // TODO: This needs to be able to handle object in other encodings and schemas. + ext.Raw = bytes.TrimSpace(ext.Raw) + if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) { + continue + } + if err := ValidateSchema(ext.Raw, v.Schema); err != nil { + return fmt.Errorf("error validating %q: %v", v.Source, err) + } + info, err := v.infoForData(ext.Raw, v.Source) + if err != nil { + if fnErr := fn(info, err); fnErr != nil { + return fnErr + } + continue + } + if err := fn(info, nil); err != nil { + return err + } + } +} + +func UpdateObjectNamespace(info *Info, err error) error { + if err != nil { + return err + } + if info.Object != nil { + return metadataAccessor.SetNamespace(info.Object, info.Namespace) + } + return nil +} + +// FilterNamespace omits the namespace if the object is not namespace scoped +func FilterNamespace(info *Info, err error) error { + if err != nil { + return err + } + if !info.Namespaced() { + info.Namespace = "" + UpdateObjectNamespace(info, nil) + } + return nil +} + +// SetNamespace ensures that every Info object visited will have a namespace +// set. If info.Object is set, it will be mutated as well. +func SetNamespace(namespace string) VisitorFunc { + return func(info *Info, err error) error { + if err != nil { + return err + } + if !info.Namespaced() { + return nil + } + if len(info.Namespace) == 0 { + info.Namespace = namespace + UpdateObjectNamespace(info, nil) + } + return nil + } +} + +// RequireNamespace will either set a namespace if none is provided on the +// Info object, or if the namespace is set and does not match the provided +// value, returns an error. This is intended to guard against administrators +// accidentally operating on resources outside their namespace. +func RequireNamespace(namespace string) VisitorFunc { + return func(info *Info, err error) error { + if err != nil { + return err + } + if !info.Namespaced() { + return nil + } + if len(info.Namespace) == 0 { + info.Namespace = namespace + UpdateObjectNamespace(info, nil) + return nil + } + if info.Namespace != namespace { + return fmt.Errorf("the namespace from the provided object %q does not match the namespace %q. You must pass '--namespace=%s' to perform this operation.", info.Namespace, namespace, info.Namespace) + } + return nil + } +} + +// RetrieveLatest updates the Object on each Info by invoking a standard client +// Get. +func RetrieveLatest(info *Info, err error) error { + if err != nil { + return err + } + if meta.IsListType(info.Object) { + return fmt.Errorf("watch is only supported on individual resources and resource collections, but a list of resources is found") + } + if len(info.Name) == 0 { + return nil + } + if info.Namespaced() && len(info.Namespace) == 0 { + return fmt.Errorf("no namespace set on resource %s %q", info.Mapping.Resource, info.Name) + } + return info.Get() +} + +// RetrieveLazy updates the object if it has not been loaded yet. +func RetrieveLazy(info *Info, err error) error { + if err != nil { + return err + } + if info.Object == nil { + return info.Get() + } + return nil +} + +// CreateAndRefresh creates an object from input info and refreshes info with that object +func CreateAndRefresh(info *Info) error { + obj, err := NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object, nil) + if err != nil { + return err + } + info.Refresh(obj, true) + return nil +} + +type FilterFunc func(info *Info, err error) (bool, error) + +type FilteredVisitor struct { + visitor Visitor + filters []FilterFunc +} + +func NewFilteredVisitor(v Visitor, fn ...FilterFunc) Visitor { + if len(fn) == 0 { + return v + } + return FilteredVisitor{v, fn} +} + +func (v FilteredVisitor) Visit(fn VisitorFunc) error { + return v.visitor.Visit(func(info *Info, err error) error { + if err != nil { + return err + } + for _, filter := range v.filters { + ok, err := filter(info, nil) + if err != nil { + return err + } + if !ok { + return nil + } + } + return fn(info, nil) + }) +} + +func FilterByLabelSelector(s labels.Selector) FilterFunc { + return func(info *Info, err error) (bool, error) { + if err != nil { + return false, err + } + a, err := meta.Accessor(info.Object) + if err != nil { + return false, err + } + if !s.Matches(labels.Set(a.GetLabels())) { + return false, nil + } + return true, nil + } +} + +type InfoListVisitor []*Info + +func (infos InfoListVisitor) Visit(fn VisitorFunc) error { + var err error + for _, i := range infos { + err = fn(i, err) + } + return err +} diff --git a/vendor/k8s.io/client-go/discovery/cached/disk/cached_discovery.go b/vendor/k8s.io/client-go/discovery/cached/disk/cached_discovery.go new file mode 100644 index 000000000..fd8b61d15 --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/cached/disk/cached_discovery.go @@ -0,0 +1,300 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package disk + +import ( + "errors" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "sync" + "time" + + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + "k8s.io/klog" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/version" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes/scheme" + restclient "k8s.io/client-go/rest" +) + +// CachedDiscoveryClient implements the functions that discovery server-supported API groups, +// versions and resources. +type CachedDiscoveryClient struct { + delegate discovery.DiscoveryInterface + + // cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. + cacheDirectory string + + // ttl is how long the cache should be considered valid + ttl time.Duration + + // mutex protects the variables below + mutex sync.Mutex + + // ourFiles are all filenames of cache files created by this process + ourFiles map[string]struct{} + // invalidated is true if all cache files should be ignored that are not ours (e.g. after Invalidate() was called) + invalidated bool + // fresh is true if all used cache files were ours + fresh bool +} + +var _ discovery.CachedDiscoveryInterface = &CachedDiscoveryClient{} + +// ServerResourcesForGroupVersion returns the supported resources for a group and version. +func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedResources := &metav1.APIResourceList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedResources); err == nil { + klog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedResources, nil + } + } + + liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion) + if err != nil { + klog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveResources, err + } + if liveResources == nil || len(liveResources.APIResources) == 0 { + klog.V(3).Infof("skipped caching discovery info, no resources found") + return liveResources, err + } + + if err := d.writeCachedFile(filename, liveResources); err != nil { + klog.V(1).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveResources, nil +} + +// ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. +func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + _, rs, err := discovery.ServerGroupsAndResources(d) + return rs, err +} + +// ServerGroupsAndResources returns the supported groups and resources for all groups and versions. +func (d *CachedDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return discovery.ServerGroupsAndResources(d) +} + +// ServerGroups returns the supported groups, with information like supported versions and the +// preferred version. +func (d *CachedDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { + filename := filepath.Join(d.cacheDirectory, "servergroups.json") + cachedBytes, err := d.getCachedFile(filename) + // don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback. + if err == nil { + cachedGroups := &metav1.APIGroupList{} + if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedGroups); err == nil { + klog.V(10).Infof("returning cached discovery info from %v", filename) + return cachedGroups, nil + } + } + + liveGroups, err := d.delegate.ServerGroups() + if err != nil { + klog.V(3).Infof("skipped caching discovery info due to %v", err) + return liveGroups, err + } + if liveGroups == nil || len(liveGroups.Groups) == 0 { + klog.V(3).Infof("skipped caching discovery info, no groups found") + return liveGroups, err + } + + if err := d.writeCachedFile(filename, liveGroups); err != nil { + klog.V(1).Infof("failed to write cache to %v due to %v", filename, err) + } + + return liveGroups, nil +} + +func (d *CachedDiscoveryClient) getCachedFile(filename string) ([]byte, error) { + // after invalidation ignore cache files not created by this process + d.mutex.Lock() + _, ourFile := d.ourFiles[filename] + if d.invalidated && !ourFile { + d.mutex.Unlock() + return nil, errors.New("cache invalidated") + } + d.mutex.Unlock() + + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + fileInfo, err := file.Stat() + if err != nil { + return nil, err + } + + if time.Now().After(fileInfo.ModTime().Add(d.ttl)) { + return nil, errors.New("cache expired") + } + + // the cache is present and its valid. Try to read and use it. + cachedBytes, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + d.mutex.Lock() + defer d.mutex.Unlock() + d.fresh = d.fresh && ourFile + + return cachedBytes, nil +} + +func (d *CachedDiscoveryClient) writeCachedFile(filename string, obj runtime.Object) error { + if err := os.MkdirAll(filepath.Dir(filename), 0750); err != nil { + return err + } + + bytes, err := runtime.Encode(scheme.Codecs.LegacyCodec(), obj) + if err != nil { + return err + } + + f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".") + if err != nil { + return err + } + defer os.Remove(f.Name()) + _, err = f.Write(bytes) + if err != nil { + return err + } + + err = os.Chmod(f.Name(), 0660) + if err != nil { + return err + } + + name := f.Name() + err = f.Close() + if err != nil { + return err + } + + // atomic rename + d.mutex.Lock() + defer d.mutex.Unlock() + err = os.Rename(name, filename) + if err == nil { + d.ourFiles[filename] = struct{}{} + } + return err +} + +// RESTClient returns a RESTClient that is used to communicate with API server +// by this client implementation. +func (d *CachedDiscoveryClient) RESTClient() restclient.Interface { + return d.delegate.RESTClient() +} + +// ServerPreferredResources returns the supported resources with the version preferred by the +// server. +func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return discovery.ServerPreferredResources(d) +} + +// ServerPreferredNamespacedResources returns the supported namespaced resources with the +// version preferred by the server. +func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return discovery.ServerPreferredNamespacedResources(d) +} + +// ServerVersion retrieves and parses the server's version (git version). +func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) { + return d.delegate.ServerVersion() +} + +// OpenAPISchema retrieves and parses the swagger API schema the server supports. +func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + return d.delegate.OpenAPISchema() +} + +// Fresh is supposed to tell the caller whether or not to retry if the cache +// fails to find something (false = retry, true = no need to retry). +func (d *CachedDiscoveryClient) Fresh() bool { + d.mutex.Lock() + defer d.mutex.Unlock() + + return d.fresh +} + +// Invalidate enforces that no cached data is used in the future that is older than the current time. +func (d *CachedDiscoveryClient) Invalidate() { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.ourFiles = map[string]struct{}{} + d.fresh = true + d.invalidated = true +} + +// NewCachedDiscoveryClientForConfig creates a new DiscoveryClient for the given config, and wraps +// the created client in a CachedDiscoveryClient. The provided configuration is updated with a +// custom transport that understands cache responses. +// We receive two distinct cache directories for now, in order to preserve old behavior +// which makes use of the --cache-dir flag value for storing cache data from the CacheRoundTripper, +// and makes use of the hardcoded destination (~/.kube/cache/discovery/...) for storing +// CachedDiscoveryClient cache data. If httpCacheDir is empty, the restconfig's transport will not +// be updated with a roundtripper that understands cache responses. +// If discoveryCacheDir is empty, cached server resource data will be looked up in the current directory. +// TODO(juanvallejo): the value of "--cache-dir" should be honored. Consolidate discoveryCacheDir with httpCacheDir +// so that server resources and http-cache data are stored in the same location, provided via config flags. +func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) { + if len(httpCacheDir) > 0 { + // update the given restconfig with a custom roundtripper that + // understands how to handle cache responses. + config = restclient.CopyConfig(config) + config.Wrap(func(rt http.RoundTripper) http.RoundTripper { + return newCacheRoundTripper(httpCacheDir, rt) + }) + } + + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) + if err != nil { + return nil, err + } + + return newCachedDiscoveryClient(discoveryClient, discoveryCacheDir, ttl), nil +} + +// NewCachedDiscoveryClient creates a new DiscoveryClient. cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well. +func newCachedDiscoveryClient(delegate discovery.DiscoveryInterface, cacheDirectory string, ttl time.Duration) *CachedDiscoveryClient { + return &CachedDiscoveryClient{ + delegate: delegate, + cacheDirectory: cacheDirectory, + ttl: ttl, + ourFiles: map[string]struct{}{}, + fresh: true, + } +} diff --git a/vendor/k8s.io/client-go/discovery/cached/disk/round_tripper.go b/vendor/k8s.io/client-go/discovery/cached/disk/round_tripper.go new file mode 100644 index 000000000..1dfb8297d --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/cached/disk/round_tripper.go @@ -0,0 +1,65 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package disk + +import ( + "net/http" + "os" + "path/filepath" + + "github.com/gregjones/httpcache" + "github.com/gregjones/httpcache/diskcache" + "github.com/peterbourgon/diskv" + "k8s.io/klog" +) + +type cacheRoundTripper struct { + rt *httpcache.Transport +} + +// newCacheRoundTripper creates a roundtripper that reads the ETag on +// response headers and send the If-None-Match header on subsequent +// corresponding requests. +func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper { + d := diskv.New(diskv.Options{ + PathPerm: os.FileMode(0750), + FilePerm: os.FileMode(0660), + BasePath: cacheDir, + TempDir: filepath.Join(cacheDir, ".diskv-temp"), + }) + t := httpcache.NewTransport(diskcache.NewWithDiskv(d)) + t.Transport = rt + + return &cacheRoundTripper{rt: t} +} + +func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return rt.rt.RoundTrip(req) +} + +func (rt *cacheRoundTripper) CancelRequest(req *http.Request) { + type canceler interface { + CancelRequest(*http.Request) + } + if cr, ok := rt.rt.Transport.(canceler); ok { + cr.CancelRequest(req) + } else { + klog.Errorf("CancelRequest not implemented by %T", rt.rt.Transport) + } +} + +func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport } diff --git a/vendor/k8s.io/client-go/scale/client.go b/vendor/k8s.io/client-go/scale/client.go new file mode 100644 index 000000000..17519345e --- /dev/null +++ b/vendor/k8s.io/client-go/scale/client.go @@ -0,0 +1,225 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scale + +import ( + "fmt" + + autoscaling "k8s.io/api/autoscaling/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" + restclient "k8s.io/client-go/rest" +) + +var scaleConverter = NewScaleConverter() +var codecs = serializer.NewCodecFactory(scaleConverter.Scheme()) + +// scaleClient is an implementation of ScalesGetter +// which makes use of a RESTMapper and a generic REST +// client to support an discoverable resource. +// It behaves somewhat similarly to the dynamic ClientPool, +// but is more specifically scoped to Scale. +type scaleClient struct { + mapper PreferredResourceMapper + + apiPathResolverFunc dynamic.APIPathResolverFunc + scaleKindResolver ScaleKindResolver + clientBase restclient.Interface +} + +// NewForConfig creates a new ScalesGetter which resolves kinds +// to resources using the given RESTMapper, and API paths using +// the given dynamic.APIPathResolverFunc. +func NewForConfig(cfg *restclient.Config, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) (ScalesGetter, error) { + // so that the RESTClientFor doesn't complain + cfg.GroupVersion = &schema.GroupVersion{} + + cfg.NegotiatedSerializer = codecs.WithoutConversion() + if len(cfg.UserAgent) == 0 { + cfg.UserAgent = restclient.DefaultKubernetesUserAgent() + } + + client, err := restclient.RESTClientFor(cfg) + if err != nil { + return nil, err + } + + return New(client, mapper, resolver, scaleKindResolver), nil +} + +// New creates a new ScalesGetter using the given client to make requests. +// The GroupVersion on the client is ignored. +func New(baseClient restclient.Interface, mapper PreferredResourceMapper, resolver dynamic.APIPathResolverFunc, scaleKindResolver ScaleKindResolver) ScalesGetter { + return &scaleClient{ + mapper: mapper, + + apiPathResolverFunc: resolver, + scaleKindResolver: scaleKindResolver, + clientBase: baseClient, + } +} + +// apiPathFor returns the absolute api path for the given GroupVersion +func (c *scaleClient) apiPathFor(groupVer schema.GroupVersion) string { + // we need to set the API path based on GroupVersion (defaulting to the legacy path if none is set) + // TODO: we "cheat" here since the API path really only depends on group ATM, but this should + // *probably* take GroupVersionResource and not GroupVersionKind. + apiPath := c.apiPathResolverFunc(groupVer.WithKind("")) + if apiPath == "" { + apiPath = "/api" + } + + return restclient.DefaultVersionedAPIPath(apiPath, groupVer) +} + +// pathAndVersionFor returns the appropriate base path and the associated full GroupVersionResource +// for the given GroupResource +func (c *scaleClient) pathAndVersionFor(resource schema.GroupResource) (string, schema.GroupVersionResource, error) { + gvr, err := c.mapper.ResourceFor(resource.WithVersion("")) + if err != nil { + return "", gvr, fmt.Errorf("unable to get full preferred group-version-resource for %s: %v", resource.String(), err) + } + + groupVer := gvr.GroupVersion() + + return c.apiPathFor(groupVer), gvr, nil +} + +// namespacedScaleClient is an ScaleInterface for fetching +// Scales in a given namespace. +type namespacedScaleClient struct { + client *scaleClient + namespace string +} + +// convertToScale converts the response body to autoscaling/v1.Scale +func convertToScale(result *restclient.Result) (*autoscaling.Scale, error) { + scaleBytes, err := result.Raw() + if err != nil { + return nil, err + } + decoder := scaleConverter.codecs.UniversalDecoder(scaleConverter.ScaleVersions()...) + rawScaleObj, err := runtime.Decode(decoder, scaleBytes) + if err != nil { + return nil, err + } + + // convert whatever this is to autoscaling/v1.Scale + scaleObj, err := scaleConverter.ConvertToVersion(rawScaleObj, autoscaling.SchemeGroupVersion) + if err != nil { + return nil, fmt.Errorf("received an object from a /scale endpoint which was not convertible to autoscaling Scale: %v", err) + } + + return scaleObj.(*autoscaling.Scale), nil +} + +func (c *scaleClient) Scales(namespace string) ScaleInterface { + return &namespacedScaleClient{ + client: c, + namespace: namespace, + } +} + +func (c *namespacedScaleClient) Get(resource schema.GroupResource, name string) (*autoscaling.Scale, error) { + // Currently, a /scale endpoint can return different scale types. + // Until we have support for the alternative API representations proposal, + // we need to deal with accepting different API versions. + // In practice, this is autoscaling/v1.Scale and extensions/v1beta1.Scale + + path, gvr, err := c.client.pathAndVersionFor(resource) + if err != nil { + return nil, fmt.Errorf("unable to get client for %s: %v", resource.String(), err) + } + + result := c.client.clientBase.Get(). + AbsPath(path). + NamespaceIfScoped(c.namespace, c.namespace != ""). + Resource(gvr.Resource). + Name(name). + SubResource("scale"). + Do() + if err := result.Error(); err != nil { + return nil, err + } + + return convertToScale(&result) +} + +func (c *namespacedScaleClient) Update(resource schema.GroupResource, scale *autoscaling.Scale) (*autoscaling.Scale, error) { + path, gvr, err := c.client.pathAndVersionFor(resource) + if err != nil { + return nil, fmt.Errorf("unable to get client for %s: %v", resource.String(), err) + } + + // Currently, a /scale endpoint can receive and return different scale types. + // Until we have support for the alternative API representations proposal, + // we need to deal with sending and accepting different API versions. + + // figure out what scale we actually need here + desiredGVK, err := c.client.scaleKindResolver.ScaleForResource(gvr) + if err != nil { + return nil, fmt.Errorf("could not find proper group-version for scale subresource of %s: %v", gvr.String(), err) + } + + // convert this to whatever this endpoint wants + scaleUpdate, err := scaleConverter.ConvertToVersion(scale, desiredGVK.GroupVersion()) + if err != nil { + return nil, fmt.Errorf("could not convert scale update to external Scale: %v", err) + } + encoder := scaleConverter.codecs.LegacyCodec(desiredGVK.GroupVersion()) + scaleUpdateBytes, err := runtime.Encode(encoder, scaleUpdate) + if err != nil { + return nil, fmt.Errorf("could not encode scale update to external Scale: %v", err) + } + + result := c.client.clientBase.Put(). + AbsPath(path). + NamespaceIfScoped(c.namespace, c.namespace != ""). + Resource(gvr.Resource). + Name(scale.Name). + SubResource("scale"). + Body(scaleUpdateBytes). + Do() + if err := result.Error(); err != nil { + // propagate "raw" error from the API + // this allows callers to interpret underlying Reason field + // for example: errors.IsConflict(err) + return nil, err + } + + return convertToScale(&result) +} + +func (c *namespacedScaleClient) Patch(gvr schema.GroupVersionResource, name string, pt types.PatchType, data []byte) (*autoscaling.Scale, error) { + groupVersion := gvr.GroupVersion() + result := c.client.clientBase.Patch(pt). + AbsPath(c.client.apiPathFor(groupVersion)). + NamespaceIfScoped(c.namespace, c.namespace != ""). + Resource(gvr.Resource). + Name(name). + SubResource("scale"). + Body(data). + Do() + if err := result.Error(); err != nil { + return nil, err + } + + return convertToScale(&result) +} diff --git a/vendor/k8s.io/client-go/scale/doc.go b/vendor/k8s.io/client-go/scale/doc.go new file mode 100644 index 000000000..b6fa3f5f2 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package scale provides a polymorphic scale client capable of fetching +// and updating Scale for any resource which implements the `scale` subresource, +// as long as that subresource operates on a version of scale convertable to +// autoscaling.Scale. +package scale // import "k8s.io/client-go/scale" diff --git a/vendor/k8s.io/client-go/scale/interfaces.go b/vendor/k8s.io/client-go/scale/interfaces.go new file mode 100644 index 000000000..16c20d79f --- /dev/null +++ b/vendor/k8s.io/client-go/scale/interfaces.go @@ -0,0 +1,44 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scale + +import ( + autoscalingapi "k8s.io/api/autoscaling/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" +) + +// ScalesGetter can produce a ScaleInterface +type ScalesGetter interface { + // Scales produces a ScaleInterface for a particular namespace. + // Set namespace to the empty string for non-namespaced resources. + Scales(namespace string) ScaleInterface +} + +// ScaleInterface can fetch and update scales for +// resources in a particular namespace which implement +// the scale subresource. +type ScaleInterface interface { + // Get fetches the scale of the given scalable resource. + Get(resource schema.GroupResource, name string) (*autoscalingapi.Scale, error) + + // Update updates the scale of the given scalable resource. + Update(resource schema.GroupResource, scale *autoscalingapi.Scale) (*autoscalingapi.Scale, error) + + // Patch patches the scale of the given scalable resource. + Patch(gvr schema.GroupVersionResource, name string, pt types.PatchType, data []byte) (*autoscalingapi.Scale, error) +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsint/doc.go b/vendor/k8s.io/client-go/scale/scheme/appsint/doc.go new file mode 100644 index 000000000..16f29e2af --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsint/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package appsint contains the necessary scaffolding of the +// internal version of extensions as required by conversion logic. +// It doesn't have any of its own types -- it's just necessary to +// get the expected behavior out of runtime.Scheme.ConvertToVersion +// and associated methods. +package appsint diff --git a/vendor/k8s.io/client-go/scale/scheme/appsint/register.go b/vendor/k8s.io/client-go/scale/scheme/appsint/register.go new file mode 100644 index 000000000..d3a76b518 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsint/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package appsint + +import ( + appsv1beta2 "k8s.io/api/apps/v1beta2" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + scalescheme "k8s.io/client-go/scale/scheme" +) + +// GroupName is the group name use in this package +const GroupName = appsv1beta2.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &scalescheme.Scale{}, + ) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/conversion.go new file mode 100644 index 000000000..af062b3c6 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/conversion.go @@ -0,0 +1,87 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package appsv1beta1 + +import ( + "fmt" + + v1beta1 "k8s.io/api/apps/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +// addConversions registers conversions between the internal version +// of Scale and supported external versions of Scale. +func addConversionFuncs(scheme *runtime.Scheme) error { + err := scheme.AddConversionFuncs( + Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus, + Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus, + ) + if err != nil { + return err + } + + return nil +} +func Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(in *scheme.ScaleStatus, out *v1beta1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.Selector = nil + out.TargetSelector = "" + if in.Selector != nil { + if in.Selector.MatchExpressions == nil || len(in.Selector.MatchExpressions) == 0 { + out.Selector = in.Selector.MatchLabels + } + + selector, err := metav1.LabelSelectorAsSelector(in.Selector) + if err != nil { + return fmt.Errorf("invalid label selector: %v", err) + } + out.TargetSelector = selector.String() + } + + return nil +} + +func Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(in *v1beta1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + + // Normally when 2 fields map to the same internal value we favor the old field, since + // old clients can't be expected to know about new fields but clients that know about the + // new field can be expected to know about the old field (though that's not quite true, due + // to kubectl apply). However, these fields are readonly, so any non-nil value should work. + if in.TargetSelector != "" { + labelSelector, err := metav1.ParseToLabelSelector(in.TargetSelector) + if err != nil { + out.Selector = nil + return fmt.Errorf("failed to parse target selector: %v", err) + } + out.Selector = labelSelector + } else if in.Selector != nil { + out.Selector = new(metav1.LabelSelector) + selector := make(map[string]string) + for key, val := range in.Selector { + selector[key] = val + } + out.Selector.MatchLabels = selector + } else { + out.Selector = nil + } + + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/doc.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/doc.go new file mode 100644 index 000000000..830619b44 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/vendor/k8s.io/client-go/scale/scheme +// +k8s:conversion-gen-external-types=k8s.io/api/apps/v1beta1 + +package appsv1beta1 // import "k8s.io/client-go/scale/scheme/appsv1beta1" diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/register.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/register.go new file mode 100644 index 000000000..a684f2d53 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package appsv1beta1 + +import ( + appsapiv1beta1 "k8s.io/api/apps/v1beta1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = appsapiv1beta1.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &appsapiv1beta1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addConversionFuncs) +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..16d53c697 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta1/zz_generated.conversion.go @@ -0,0 +1,143 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package appsv1beta1 + +import ( + v1beta1 "k8s.io/api/apps/v1beta1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1beta1.Scale)(nil), (*scheme.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Scale_To_scheme_Scale(a.(*v1beta1.Scale), b.(*scheme.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.Scale)(nil), (*v1beta1.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_Scale_To_v1beta1_Scale(a.(*scheme.Scale), b.(*v1beta1.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ScaleSpec)(nil), (*scheme.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(a.(*v1beta1.ScaleSpec), b.(*scheme.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleSpec)(nil), (*v1beta1.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(a.(*scheme.ScaleSpec), b.(*v1beta1.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_Scale_To_scheme_Scale(in *v1beta1.Scale, out *scheme.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Scale_To_scheme_Scale is an autogenerated conversion function. +func Convert_v1beta1_Scale_To_scheme_Scale(in *v1beta1.Scale, out *scheme.Scale, s conversion.Scope) error { + return autoConvert_v1beta1_Scale_To_scheme_Scale(in, out, s) +} + +func autoConvert_scheme_Scale_To_v1beta1_Scale(in *scheme.Scale, out *v1beta1.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_scheme_Scale_To_v1beta1_Scale is an autogenerated conversion function. +func Convert_scheme_Scale_To_v1beta1_Scale(in *scheme.Scale, out *v1beta1.Scale, s conversion.Scope) error { + return autoConvert_scheme_Scale_To_v1beta1_Scale(in, out, s) +} + +func autoConvert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in *v1beta1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec is an autogenerated conversion function. +func Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in *v1beta1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in, out, s) +} + +func autoConvert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in *scheme.ScaleSpec, out *v1beta1.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec is an autogenerated conversion function. +func Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in *scheme.ScaleSpec, out *v1beta1.ScaleSpec, s conversion.Scope) error { + return autoConvert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in, out, s) +} + +func autoConvert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(in *v1beta1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (map[string]string vs *k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector) + // WARNING: in.TargetSelector requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(in *scheme.ScaleStatus, out *v1beta1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector vs map[string]string) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/conversion.go new file mode 100644 index 000000000..f07de6bda --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/conversion.go @@ -0,0 +1,87 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package appsv1beta2 + +import ( + "fmt" + + v1beta2 "k8s.io/api/apps/v1beta2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +// addConversions registers conversions between the internal version +// of Scale and supported external versions of Scale. +func addConversionFuncs(scheme *runtime.Scheme) error { + err := scheme.AddConversionFuncs( + Convert_scheme_ScaleStatus_To_v1beta2_ScaleStatus, + Convert_v1beta2_ScaleStatus_To_scheme_ScaleStatus, + ) + if err != nil { + return err + } + + return nil +} +func Convert_scheme_ScaleStatus_To_v1beta2_ScaleStatus(in *scheme.ScaleStatus, out *v1beta2.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.Selector = nil + out.TargetSelector = "" + if in.Selector != nil { + if in.Selector.MatchExpressions == nil || len(in.Selector.MatchExpressions) == 0 { + out.Selector = in.Selector.MatchLabels + } + + selector, err := metav1.LabelSelectorAsSelector(in.Selector) + if err != nil { + return fmt.Errorf("invalid label selector: %v", err) + } + out.TargetSelector = selector.String() + } + + return nil +} + +func Convert_v1beta2_ScaleStatus_To_scheme_ScaleStatus(in *v1beta2.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + + // Normally when 2 fields map to the same internal value we favor the old field, since + // old clients can't be expected to know about new fields but clients that know about the + // new field can be expected to know about the old field (though that's not quite true, due + // to kubectl apply). However, these fields are readonly, so any non-nil value should work. + if in.TargetSelector != "" { + labelSelector, err := metav1.ParseToLabelSelector(in.TargetSelector) + if err != nil { + out.Selector = nil + return fmt.Errorf("failed to parse target selector: %v", err) + } + out.Selector = labelSelector + } else if in.Selector != nil { + out.Selector = new(metav1.LabelSelector) + selector := make(map[string]string) + for key, val := range in.Selector { + selector[key] = val + } + out.Selector.MatchLabels = selector + } else { + out.Selector = nil + } + + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/doc.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/doc.go new file mode 100644 index 000000000..c21a56d56 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/vendor/k8s.io/client-go/scale/scheme +// +k8s:conversion-gen-external-types=k8s.io/api/apps/v1beta2 + +package appsv1beta2 // import "k8s.io/client-go/scale/scheme/appsv1beta2" diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/register.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/register.go new file mode 100644 index 000000000..88de08932 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package appsv1beta2 + +import ( + appsapiv1beta2 "k8s.io/api/apps/v1beta2" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = appsapiv1beta2.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &appsapiv1beta2.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addConversionFuncs) +} diff --git a/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go new file mode 100644 index 000000000..1901be8cb --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/appsv1beta2/zz_generated.conversion.go @@ -0,0 +1,143 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package appsv1beta2 + +import ( + v1beta2 "k8s.io/api/apps/v1beta2" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1beta2.Scale)(nil), (*scheme.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scale_To_scheme_Scale(a.(*v1beta2.Scale), b.(*scheme.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.Scale)(nil), (*v1beta2.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_Scale_To_v1beta2_Scale(a.(*scheme.Scale), b.(*v1beta2.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.ScaleSpec)(nil), (*scheme.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ScaleSpec_To_scheme_ScaleSpec(a.(*v1beta2.ScaleSpec), b.(*scheme.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleSpec)(nil), (*v1beta2.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleSpec_To_v1beta2_ScaleSpec(a.(*scheme.ScaleSpec), b.(*v1beta2.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta2.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta2.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta2.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta2_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta2.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta2.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta2_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta2.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta2.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta2_Scale_To_scheme_Scale(in *v1beta2.Scale, out *scheme.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta2_ScaleSpec_To_scheme_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta2_ScaleStatus_To_scheme_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta2_Scale_To_scheme_Scale is an autogenerated conversion function. +func Convert_v1beta2_Scale_To_scheme_Scale(in *v1beta2.Scale, out *scheme.Scale, s conversion.Scope) error { + return autoConvert_v1beta2_Scale_To_scheme_Scale(in, out, s) +} + +func autoConvert_scheme_Scale_To_v1beta2_Scale(in *scheme.Scale, out *v1beta2.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_scheme_ScaleSpec_To_v1beta2_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_scheme_ScaleStatus_To_v1beta2_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_scheme_Scale_To_v1beta2_Scale is an autogenerated conversion function. +func Convert_scheme_Scale_To_v1beta2_Scale(in *scheme.Scale, out *v1beta2.Scale, s conversion.Scope) error { + return autoConvert_scheme_Scale_To_v1beta2_Scale(in, out, s) +} + +func autoConvert_v1beta2_ScaleSpec_To_scheme_ScaleSpec(in *v1beta2.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_v1beta2_ScaleSpec_To_scheme_ScaleSpec is an autogenerated conversion function. +func Convert_v1beta2_ScaleSpec_To_scheme_ScaleSpec(in *v1beta2.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + return autoConvert_v1beta2_ScaleSpec_To_scheme_ScaleSpec(in, out, s) +} + +func autoConvert_scheme_ScaleSpec_To_v1beta2_ScaleSpec(in *scheme.ScaleSpec, out *v1beta2.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_scheme_ScaleSpec_To_v1beta2_ScaleSpec is an autogenerated conversion function. +func Convert_scheme_ScaleSpec_To_v1beta2_ScaleSpec(in *scheme.ScaleSpec, out *v1beta2.ScaleSpec, s conversion.Scope) error { + return autoConvert_scheme_ScaleSpec_To_v1beta2_ScaleSpec(in, out, s) +} + +func autoConvert_v1beta2_ScaleStatus_To_scheme_ScaleStatus(in *v1beta2.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (map[string]string vs *k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector) + // WARNING: in.TargetSelector requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_scheme_ScaleStatus_To_v1beta2_ScaleStatus(in *scheme.ScaleStatus, out *v1beta2.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector vs map[string]string) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/conversion.go b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/conversion.go new file mode 100644 index 000000000..a775bcc22 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/conversion.go @@ -0,0 +1,69 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package autoscalingv1 + +import ( + "fmt" + + v1 "k8s.io/api/autoscaling/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +// addConversions registers conversions between the internal version +// of Scale and supported external versions of Scale. +func addConversionFuncs(scheme *runtime.Scheme) error { + err := scheme.AddConversionFuncs( + Convert_scheme_ScaleStatus_To_v1_ScaleStatus, + Convert_v1_ScaleStatus_To_scheme_ScaleStatus, + ) + if err != nil { + return err + } + + return nil +} + +func Convert_scheme_ScaleStatus_To_v1_ScaleStatus(in *scheme.ScaleStatus, out *v1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.Selector = "" + if in.Selector != nil { + selector, err := metav1.LabelSelectorAsSelector(in.Selector) + if err != nil { + return fmt.Errorf("invalid label selector: %v", err) + } + out.Selector = selector.String() + } + + return nil +} + +func Convert_v1_ScaleStatus_To_scheme_ScaleStatus(in *v1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + if in.Selector != "" { + labelSelector, err := metav1.ParseToLabelSelector(in.Selector) + if err != nil { + out.Selector = nil + return fmt.Errorf("failed to parse target selector: %v", err) + } + out.Selector = labelSelector + } + + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/doc.go b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/doc.go new file mode 100644 index 000000000..03684dd90 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/vendor/k8s.io/client-go/scale/scheme +// +k8s:conversion-gen-external-types=k8s.io/api/autoscaling/v1 + +package autoscalingv1 // import "k8s.io/client-go/scale/scheme/autoscalingv1" diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/register.go b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/register.go new file mode 100644 index 000000000..b15701c4f --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package autoscalingv1 + +import ( + autoscalingapiv1 "k8s.io/api/autoscaling/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = autoscalingapiv1.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &autoscalingapiv1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addConversionFuncs) +} diff --git a/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go new file mode 100644 index 000000000..203f8b323 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/autoscalingv1/zz_generated.conversion.go @@ -0,0 +1,142 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package autoscalingv1 + +import ( + v1 "k8s.io/api/autoscaling/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1.Scale)(nil), (*scheme.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_Scale_To_scheme_Scale(a.(*v1.Scale), b.(*scheme.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.Scale)(nil), (*v1.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_Scale_To_v1_Scale(a.(*scheme.Scale), b.(*v1.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ScaleSpec)(nil), (*scheme.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ScaleSpec_To_scheme_ScaleSpec(a.(*v1.ScaleSpec), b.(*scheme.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleSpec)(nil), (*v1.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleSpec_To_v1_ScaleSpec(a.(*scheme.ScaleSpec), b.(*v1.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleStatus)(nil), (*v1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*scheme.ScaleStatus)(nil), (*v1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1_Scale_To_scheme_Scale(in *v1.Scale, out *scheme.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1_ScaleSpec_To_scheme_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1_ScaleStatus_To_scheme_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1_Scale_To_scheme_Scale is an autogenerated conversion function. +func Convert_v1_Scale_To_scheme_Scale(in *v1.Scale, out *scheme.Scale, s conversion.Scope) error { + return autoConvert_v1_Scale_To_scheme_Scale(in, out, s) +} + +func autoConvert_scheme_Scale_To_v1_Scale(in *scheme.Scale, out *v1.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_scheme_ScaleSpec_To_v1_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_scheme_ScaleStatus_To_v1_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_scheme_Scale_To_v1_Scale is an autogenerated conversion function. +func Convert_scheme_Scale_To_v1_Scale(in *scheme.Scale, out *v1.Scale, s conversion.Scope) error { + return autoConvert_scheme_Scale_To_v1_Scale(in, out, s) +} + +func autoConvert_v1_ScaleSpec_To_scheme_ScaleSpec(in *v1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_v1_ScaleSpec_To_scheme_ScaleSpec is an autogenerated conversion function. +func Convert_v1_ScaleSpec_To_scheme_ScaleSpec(in *v1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + return autoConvert_v1_ScaleSpec_To_scheme_ScaleSpec(in, out, s) +} + +func autoConvert_scheme_ScaleSpec_To_v1_ScaleSpec(in *scheme.ScaleSpec, out *v1.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_scheme_ScaleSpec_To_v1_ScaleSpec is an autogenerated conversion function. +func Convert_scheme_ScaleSpec_To_v1_ScaleSpec(in *scheme.ScaleSpec, out *v1.ScaleSpec, s conversion.Scope) error { + return autoConvert_scheme_ScaleSpec_To_v1_ScaleSpec(in, out, s) +} + +func autoConvert_v1_ScaleStatus_To_scheme_ScaleStatus(in *v1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (string vs *k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector) + return nil +} + +func autoConvert_scheme_ScaleStatus_To_v1_ScaleStatus(in *scheme.ScaleStatus, out *v1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector vs string) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/doc.go b/vendor/k8s.io/client-go/scale/scheme/doc.go new file mode 100644 index 000000000..0203d6d5a --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:deepcopy-gen=package + +// Package scheme contains a runtime.Scheme to be used for serializing +// and deserializing different versions of Scale, and for converting +// in between them. +package scheme diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsint/doc.go b/vendor/k8s.io/client-go/scale/scheme/extensionsint/doc.go new file mode 100644 index 000000000..9aaac6086 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsint/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package extensionsint contains the necessary scaffolding of the +// internal version of extensions as required by conversion logic. +// It doesn't have any of its own types -- it's just necessary to +// get the expected behavior out of runtime.Scheme.ConvertToVersion +// and associated methods. +package extensionsint diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsint/register.go b/vendor/k8s.io/client-go/scale/scheme/extensionsint/register.go new file mode 100644 index 000000000..570a8a54a --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsint/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package extensionsint + +import ( + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + scalescheme "k8s.io/client-go/scale/scheme" +) + +// GroupName is the group name use in this package +const GroupName = extensionsv1beta1.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &scalescheme.Scale{}, + ) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/conversion.go b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/conversion.go new file mode 100644 index 000000000..1b6b9e610 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/conversion.go @@ -0,0 +1,87 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package extensionsv1beta1 + +import ( + "fmt" + + v1beta1 "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +// addConversions registers conversions between the internal version +// of Scale and supported external versions of Scale. +func addConversionFuncs(scheme *runtime.Scheme) error { + err := scheme.AddConversionFuncs( + Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus, + Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus, + ) + if err != nil { + return err + } + + return nil +} +func Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(in *scheme.ScaleStatus, out *v1beta1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + out.Selector = nil + out.TargetSelector = "" + if in.Selector != nil { + if in.Selector.MatchExpressions == nil || len(in.Selector.MatchExpressions) == 0 { + out.Selector = in.Selector.MatchLabels + } + + selector, err := metav1.LabelSelectorAsSelector(in.Selector) + if err != nil { + return fmt.Errorf("invalid label selector: %v", err) + } + out.TargetSelector = selector.String() + } + + return nil +} + +func Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(in *v1beta1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + + // Normally when 2 fields map to the same internal value we favor the old field, since + // old clients can't be expected to know about new fields but clients that know about the + // new field can be expected to know about the old field (though that's not quite true, due + // to kubectl apply). However, these fields are readonly, so any non-nil value should work. + if in.TargetSelector != "" { + labelSelector, err := metav1.ParseToLabelSelector(in.TargetSelector) + if err != nil { + out.Selector = nil + return fmt.Errorf("failed to parse target selector: %v", err) + } + out.Selector = labelSelector + } else if in.Selector != nil { + out.Selector = new(metav1.LabelSelector) + selector := make(map[string]string) + for key, val := range in.Selector { + selector[key] = val + } + out.Selector.MatchLabels = selector + } else { + out.Selector = nil + } + + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/doc.go b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/doc.go new file mode 100644 index 000000000..1e719884f --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/vendor/k8s.io/client-go/scale/scheme +// +k8s:conversion-gen-external-types=k8s.io/api/extensions/v1beta1 + +package extensionsv1beta1 // import "k8s.io/client-go/scale/scheme/extensionsv1beta1" diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/register.go b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/register.go new file mode 100644 index 000000000..aed1174e0 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/register.go @@ -0,0 +1,45 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package extensionsv1beta1 + +import ( + extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = extensionsapiv1beta1.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &extensionsapiv1beta1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addConversionFuncs) +} diff --git a/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..99aef8653 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/extensionsv1beta1/zz_generated.conversion.go @@ -0,0 +1,143 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package extensionsv1beta1 + +import ( + v1beta1 "k8s.io/api/extensions/v1beta1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + scheme "k8s.io/client-go/scale/scheme" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1beta1.Scale)(nil), (*scheme.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Scale_To_scheme_Scale(a.(*v1beta1.Scale), b.(*scheme.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.Scale)(nil), (*v1beta1.Scale)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_Scale_To_v1beta1_Scale(a.(*scheme.Scale), b.(*v1beta1.Scale), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ScaleSpec)(nil), (*scheme.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(a.(*v1beta1.ScaleSpec), b.(*scheme.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleSpec)(nil), (*v1beta1.ScaleSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(a.(*scheme.ScaleSpec), b.(*v1beta1.ScaleSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*scheme.ScaleStatus)(nil), (*v1beta1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(a.(*scheme.ScaleStatus), b.(*v1beta1.ScaleStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta1.ScaleStatus)(nil), (*scheme.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(a.(*v1beta1.ScaleStatus), b.(*scheme.ScaleStatus), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_Scale_To_scheme_Scale(in *v1beta1.Scale, out *scheme.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_Scale_To_scheme_Scale is an autogenerated conversion function. +func Convert_v1beta1_Scale_To_scheme_Scale(in *v1beta1.Scale, out *scheme.Scale, s conversion.Scope) error { + return autoConvert_v1beta1_Scale_To_scheme_Scale(in, out, s) +} + +func autoConvert_scheme_Scale_To_v1beta1_Scale(in *scheme.Scale, out *v1beta1.Scale, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_scheme_Scale_To_v1beta1_Scale is an autogenerated conversion function. +func Convert_scheme_Scale_To_v1beta1_Scale(in *scheme.Scale, out *v1beta1.Scale, s conversion.Scope) error { + return autoConvert_scheme_Scale_To_v1beta1_Scale(in, out, s) +} + +func autoConvert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in *v1beta1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec is an autogenerated conversion function. +func Convert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in *v1beta1.ScaleSpec, out *scheme.ScaleSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ScaleSpec_To_scheme_ScaleSpec(in, out, s) +} + +func autoConvert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in *scheme.ScaleSpec, out *v1beta1.ScaleSpec, s conversion.Scope) error { + out.Replicas = in.Replicas + return nil +} + +// Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec is an autogenerated conversion function. +func Convert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in *scheme.ScaleSpec, out *v1beta1.ScaleSpec, s conversion.Scope) error { + return autoConvert_scheme_ScaleSpec_To_v1beta1_ScaleSpec(in, out, s) +} + +func autoConvert_v1beta1_ScaleStatus_To_scheme_ScaleStatus(in *v1beta1.ScaleStatus, out *scheme.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (map[string]string vs *k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector) + // WARNING: in.TargetSelector requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_scheme_ScaleStatus_To_v1beta1_ScaleStatus(in *scheme.ScaleStatus, out *v1beta1.ScaleStatus, s conversion.Scope) error { + out.Replicas = in.Replicas + // WARNING: in.Selector requires manual conversion: inconvertible types (*k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector vs map[string]string) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/register.go b/vendor/k8s.io/client-go/scale/scheme/register.go new file mode 100644 index 000000000..4339e6173 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/register.go @@ -0,0 +1,54 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scheme + +import ( + autoscalingv1 "k8s.io/api/autoscaling/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = autoscalingv1.GroupName + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Scale{}, + ) + return nil +} diff --git a/vendor/k8s.io/client-go/scale/scheme/types.go b/vendor/k8s.io/client-go/scale/scheme/types.go new file mode 100644 index 000000000..5c5d0a6f2 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/types.go @@ -0,0 +1,60 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scheme + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// This file contains our own "internal" version of scale that we use for conversions, +// since we can't use the main Kubernetes internal versions. + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Scale represents a scaling request for a resource. +type Scale struct { + metav1.TypeMeta + // Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata. + // +optional + metav1.ObjectMeta + + // defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status. + // +optional + Spec ScaleSpec + + // current status of the scale. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status. Read-only. + // +optional + Status ScaleStatus +} + +// ScaleSpec describes the attributes of a scale subresource. +type ScaleSpec struct { + // desired number of instances for the scaled object. + // +optional + Replicas int32 +} + +// ScaleStatus represents the current status of a scale subresource. +type ScaleStatus struct { + // actual number of observed instances of the scaled object. + Replicas int32 + + // label query over pods that should match the replicas count. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + // +optional + Selector *metav1.LabelSelector +} diff --git a/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go b/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go new file mode 100644 index 000000000..3db708154 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/scheme/zz_generated.deepcopy.go @@ -0,0 +1,91 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package scheme + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Scale) DeepCopyInto(out *Scale) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scale. +func (in *Scale) DeepCopy() *Scale { + if in == nil { + return nil + } + out := new(Scale) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Scale) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaleSpec) DeepCopyInto(out *ScaleSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaleSpec. +func (in *ScaleSpec) DeepCopy() *ScaleSpec { + if in == nil { + return nil + } + out := new(ScaleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScaleStatus) DeepCopyInto(out *ScaleStatus) { + *out = *in + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaleStatus. +func (in *ScaleStatus) DeepCopy() *ScaleStatus { + if in == nil { + return nil + } + out := new(ScaleStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/k8s.io/client-go/scale/util.go b/vendor/k8s.io/client-go/scale/util.go new file mode 100644 index 000000000..2f43a7a79 --- /dev/null +++ b/vendor/k8s.io/client-go/scale/util.go @@ -0,0 +1,197 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scale + +import ( + "fmt" + "strings" + "sync" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/discovery" + scalescheme "k8s.io/client-go/scale/scheme" + scaleappsint "k8s.io/client-go/scale/scheme/appsint" + scaleappsv1beta1 "k8s.io/client-go/scale/scheme/appsv1beta1" + scaleappsv1beta2 "k8s.io/client-go/scale/scheme/appsv1beta2" + scaleautoscaling "k8s.io/client-go/scale/scheme/autoscalingv1" + scaleextint "k8s.io/client-go/scale/scheme/extensionsint" + scaleext "k8s.io/client-go/scale/scheme/extensionsv1beta1" +) + +// PreferredResourceMapper determines the preferred version of a resource to scale +type PreferredResourceMapper interface { + // ResourceFor takes a partial resource and returns the preferred resource. + ResourceFor(resource schema.GroupVersionResource) (preferredResource schema.GroupVersionResource, err error) +} + +// Ensure a RESTMapper satisfies the PreferredResourceMapper interface +var _ PreferredResourceMapper = meta.RESTMapper(nil) + +// ScaleKindResolver knows about the relationship between +// resources and the GroupVersionKind of their scale subresources. +type ScaleKindResolver interface { + // ScaleForResource returns the GroupVersionKind of the + // scale subresource for the given GroupVersionResource. + ScaleForResource(resource schema.GroupVersionResource) (scaleVersion schema.GroupVersionKind, err error) +} + +// discoveryScaleResolver is a ScaleKindResolver that uses +// a DiscoveryInterface to associate resources with their +// scale-kinds +type discoveryScaleResolver struct { + discoveryClient discovery.ServerResourcesInterface +} + +func (r *discoveryScaleResolver) ScaleForResource(inputRes schema.GroupVersionResource) (scaleVersion schema.GroupVersionKind, err error) { + groupVerResources, err := r.discoveryClient.ServerResourcesForGroupVersion(inputRes.GroupVersion().String()) + if err != nil { + return schema.GroupVersionKind{}, fmt.Errorf("unable to fetch discovery information for %s: %v", inputRes.String(), err) + } + + for _, resource := range groupVerResources.APIResources { + resourceParts := strings.SplitN(resource.Name, "/", 2) + if len(resourceParts) != 2 || resourceParts[0] != inputRes.Resource || resourceParts[1] != "scale" { + // skip non-scale resources, or scales for resources that we're not looking for + continue + } + + scaleGV := inputRes.GroupVersion() + if resource.Group != "" && resource.Version != "" { + scaleGV = schema.GroupVersion{ + Group: resource.Group, + Version: resource.Version, + } + } + + return scaleGV.WithKind(resource.Kind), nil + } + + return schema.GroupVersionKind{}, fmt.Errorf("could not find scale subresource for %s in discovery information", inputRes.String()) +} + +// cachedScaleKindResolver is a ScaleKindResolver that caches results +// from another ScaleKindResolver, re-fetching on cache misses. +type cachedScaleKindResolver struct { + base ScaleKindResolver + + cache map[schema.GroupVersionResource]schema.GroupVersionKind + mu sync.RWMutex +} + +func (r *cachedScaleKindResolver) ScaleForResource(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { + r.mu.RLock() + gvk, isCached := r.cache[resource] + r.mu.RUnlock() + if isCached { + return gvk, nil + } + + // we could have multiple fetches of the same resources, but that's probably + // better than limiting to only one reader at once (mu.Mutex), + // or blocking checks for other resources while we fetch + // (mu.Lock before fetch). + gvk, err := r.base.ScaleForResource(resource) + if err != nil { + return schema.GroupVersionKind{}, err + } + + r.mu.Lock() + defer r.mu.Unlock() + r.cache[resource] = gvk + + return gvk, nil +} + +// NewDiscoveryScaleKindResolver creates a new ScaleKindResolver which uses information from the given +// disovery client to resolve the correct Scale GroupVersionKind for different resources. +func NewDiscoveryScaleKindResolver(client discovery.ServerResourcesInterface) ScaleKindResolver { + base := &discoveryScaleResolver{ + discoveryClient: client, + } + + return &cachedScaleKindResolver{ + base: base, + cache: make(map[schema.GroupVersionResource]schema.GroupVersionKind), + } +} + +// ScaleConverter knows how to convert between external scale versions. +type ScaleConverter struct { + scheme *runtime.Scheme + codecs serializer.CodecFactory + internalVersioner runtime.GroupVersioner +} + +// NewScaleConverter creates a new ScaleConverter for converting between +// Scales in autoscaling/v1 and extensions/v1beta1. +func NewScaleConverter() *ScaleConverter { + scheme := runtime.NewScheme() + utilruntime.Must(scaleautoscaling.AddToScheme(scheme)) + utilruntime.Must(scalescheme.AddToScheme(scheme)) + utilruntime.Must(scaleext.AddToScheme(scheme)) + utilruntime.Must(scaleextint.AddToScheme(scheme)) + utilruntime.Must(scaleappsint.AddToScheme(scheme)) + utilruntime.Must(scaleappsv1beta1.AddToScheme(scheme)) + utilruntime.Must(scaleappsv1beta2.AddToScheme(scheme)) + + return &ScaleConverter{ + scheme: scheme, + codecs: serializer.NewCodecFactory(scheme), + internalVersioner: runtime.NewMultiGroupVersioner( + scalescheme.SchemeGroupVersion, + schema.GroupKind{Group: scaleext.GroupName, Kind: "Scale"}, + schema.GroupKind{Group: scaleautoscaling.GroupName, Kind: "Scale"}, + schema.GroupKind{Group: scaleappsv1beta1.GroupName, Kind: "Scale"}, + schema.GroupKind{Group: scaleappsv1beta2.GroupName, Kind: "Scale"}, + ), + } +} + +// Scheme returns the scheme used by this scale converter. +func (c *ScaleConverter) Scheme() *runtime.Scheme { + return c.scheme +} + +func (c *ScaleConverter) Codecs() serializer.CodecFactory { + return c.codecs +} + +func (c *ScaleConverter) ScaleVersions() []schema.GroupVersion { + return []schema.GroupVersion{ + scaleautoscaling.SchemeGroupVersion, + scalescheme.SchemeGroupVersion, + scaleext.SchemeGroupVersion, + scaleextint.SchemeGroupVersion, + scaleappsint.SchemeGroupVersion, + scaleappsv1beta1.SchemeGroupVersion, + scaleappsv1beta2.SchemeGroupVersion, + } +} + +// ConvertToVersion converts the given *external* input object to the given output *external* output group-version. +func (c *ScaleConverter) ConvertToVersion(in runtime.Object, outVersion schema.GroupVersion) (runtime.Object, error) { + scaleInt, err := c.scheme.ConvertToVersion(in, c.internalVersioner) + if err != nil { + return nil, err + } + + return c.scheme.ConvertToVersion(scaleInt, outVersion) +} diff --git a/vendor/k8s.io/client-go/tools/watch/informerwatcher.go b/vendor/k8s.io/client-go/tools/watch/informerwatcher.go new file mode 100644 index 000000000..4e0a400bb --- /dev/null +++ b/vendor/k8s.io/client-go/tools/watch/informerwatcher.go @@ -0,0 +1,150 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package watch + +import ( + "sync" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +func newEventProcessor(out chan<- watch.Event) *eventProcessor { + return &eventProcessor{ + out: out, + cond: sync.NewCond(&sync.Mutex{}), + done: make(chan struct{}), + } +} + +// eventProcessor buffers events and writes them to an out chan when a reader +// is waiting. Because of the requirement to buffer events, it synchronizes +// input with a condition, and synchronizes output with a channels. It needs to +// be able to yield while both waiting on an input condition and while blocked +// on writing to the output channel. +type eventProcessor struct { + out chan<- watch.Event + + cond *sync.Cond + buff []watch.Event + + done chan struct{} +} + +func (e *eventProcessor) run() { + for { + batch := e.takeBatch() + e.writeBatch(batch) + if e.stopped() { + return + } + } +} + +func (e *eventProcessor) takeBatch() []watch.Event { + e.cond.L.Lock() + defer e.cond.L.Unlock() + + for len(e.buff) == 0 && !e.stopped() { + e.cond.Wait() + } + + batch := e.buff + e.buff = nil + return batch +} + +func (e *eventProcessor) writeBatch(events []watch.Event) { + for _, event := range events { + select { + case e.out <- event: + case <-e.done: + return + } + } +} + +func (e *eventProcessor) push(event watch.Event) { + e.cond.L.Lock() + defer e.cond.L.Unlock() + defer e.cond.Signal() + e.buff = append(e.buff, event) +} + +func (e *eventProcessor) stopped() bool { + select { + case <-e.done: + return true + default: + return false + } +} + +func (e *eventProcessor) stop() { + close(e.done) + e.cond.Signal() +} + +// NewIndexerInformerWatcher will create an IndexerInformer and wrap it into watch.Interface +// so you can use it anywhere where you'd have used a regular Watcher returned from Watch method. +// it also returns a channel you can use to wait for the informers to fully shutdown. +func NewIndexerInformerWatcher(lw cache.ListerWatcher, objType runtime.Object) (cache.Indexer, cache.Controller, watch.Interface, <-chan struct{}) { + ch := make(chan watch.Event) + w := watch.NewProxyWatcher(ch) + e := newEventProcessor(ch) + + indexer, informer := cache.NewIndexerInformer(lw, objType, 0, cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + e.push(watch.Event{ + Type: watch.Added, + Object: obj.(runtime.Object), + }) + }, + UpdateFunc: func(old, new interface{}) { + e.push(watch.Event{ + Type: watch.Modified, + Object: new.(runtime.Object), + }) + }, + DeleteFunc: func(obj interface{}) { + staleObj, stale := obj.(cache.DeletedFinalStateUnknown) + if stale { + // We have no means of passing the additional information down using + // watch API based on watch.Event but the caller can filter such + // objects by checking if metadata.deletionTimestamp is set + obj = staleObj + } + + e.push(watch.Event{ + Type: watch.Deleted, + Object: obj.(runtime.Object), + }) + }, + }, cache.Indexers{}) + + go e.run() + + doneCh := make(chan struct{}) + go func() { + defer close(doneCh) + defer e.stop() + informer.Run(w.StopChan()) + }() + + return indexer, informer, w, doneCh +} diff --git a/vendor/k8s.io/client-go/tools/watch/retrywatcher.go b/vendor/k8s.io/client-go/tools/watch/retrywatcher.go new file mode 100644 index 000000000..47ae9df4a --- /dev/null +++ b/vendor/k8s.io/client-go/tools/watch/retrywatcher.go @@ -0,0 +1,287 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package watch + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "time" + + "github.com/davecgh/go-spew/spew" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/net" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" + "k8s.io/klog" +) + +// resourceVersionGetter is an interface used to get resource version from events. +// We can't reuse an interface from meta otherwise it would be a cyclic dependency and we need just this one method +type resourceVersionGetter interface { + GetResourceVersion() string +} + +// RetryWatcher will make sure that in case the underlying watcher is closed (e.g. due to API timeout or etcd timeout) +// it will get restarted from the last point without the consumer even knowing about it. +// RetryWatcher does that by inspecting events and keeping track of resourceVersion. +// Especially useful when using watch.UntilWithoutRetry where premature termination is causing issues and flakes. +// Please note that this is not resilient to etcd cache not having the resource version anymore - you would need to +// use Informers for that. +type RetryWatcher struct { + lastResourceVersion string + watcherClient cache.Watcher + resultChan chan watch.Event + stopChan chan struct{} + doneChan chan struct{} + minRestartDelay time.Duration +} + +// NewRetryWatcher creates a new RetryWatcher. +// It will make sure that watches gets restarted in case of recoverable errors. +// The initialResourceVersion will be given to watch method when first called. +func NewRetryWatcher(initialResourceVersion string, watcherClient cache.Watcher) (*RetryWatcher, error) { + return newRetryWatcher(initialResourceVersion, watcherClient, 1*time.Second) +} + +func newRetryWatcher(initialResourceVersion string, watcherClient cache.Watcher, minRestartDelay time.Duration) (*RetryWatcher, error) { + switch initialResourceVersion { + case "", "0": + // TODO: revisit this if we ever get WATCH v2 where it means start "now" + // without doing the synthetic list of objects at the beginning (see #74022) + return nil, fmt.Errorf("initial RV %q is not supported due to issues with underlying WATCH", initialResourceVersion) + default: + break + } + + rw := &RetryWatcher{ + lastResourceVersion: initialResourceVersion, + watcherClient: watcherClient, + stopChan: make(chan struct{}), + doneChan: make(chan struct{}), + resultChan: make(chan watch.Event, 0), + minRestartDelay: minRestartDelay, + } + + go rw.receive() + return rw, nil +} + +func (rw *RetryWatcher) send(event watch.Event) bool { + // Writing to an unbuffered channel is blocking operation + // and we need to check if stop wasn't requested while doing so. + select { + case rw.resultChan <- event: + return true + case <-rw.stopChan: + return false + } +} + +// doReceive returns true when it is done, false otherwise. +// If it is not done the second return value holds the time to wait before calling it again. +func (rw *RetryWatcher) doReceive() (bool, time.Duration) { + watcher, err := rw.watcherClient.Watch(metav1.ListOptions{ + ResourceVersion: rw.lastResourceVersion, + }) + // We are very unlikely to hit EOF here since we are just establishing the call, + // but it may happen that the apiserver is just shutting down (e.g. being restarted) + // This is consistent with how it is handled for informers + switch err { + case nil: + break + + case io.EOF: + // watch closed normally + return false, 0 + + case io.ErrUnexpectedEOF: + klog.V(1).Infof("Watch closed with unexpected EOF: %v", err) + return false, 0 + + default: + msg := "Watch failed: %v" + if net.IsProbableEOF(err) { + klog.V(5).Infof(msg, err) + // Retry + return false, 0 + } + + klog.Errorf(msg, err) + // Retry + return false, 0 + } + + if watcher == nil { + klog.Error("Watch returned nil watcher") + // Retry + return false, 0 + } + + ch := watcher.ResultChan() + defer watcher.Stop() + + for { + select { + case <-rw.stopChan: + klog.V(4).Info("Stopping RetryWatcher.") + return true, 0 + case event, ok := <-ch: + if !ok { + klog.V(4).Infof("Failed to get event! Re-creating the watcher. Last RV: %s", rw.lastResourceVersion) + return false, 0 + } + + // We need to inspect the event and get ResourceVersion out of it + switch event.Type { + case watch.Added, watch.Modified, watch.Deleted, watch.Bookmark: + metaObject, ok := event.Object.(resourceVersionGetter) + if !ok { + _ = rw.send(watch.Event{ + Type: watch.Error, + Object: &apierrors.NewInternalError(errors.New("retryWatcher: doesn't support resourceVersion")).ErrStatus, + }) + // We have to abort here because this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data! + return true, 0 + } + + resourceVersion := metaObject.GetResourceVersion() + if resourceVersion == "" { + _ = rw.send(watch.Event{ + Type: watch.Error, + Object: &apierrors.NewInternalError(fmt.Errorf("retryWatcher: object %#v doesn't support resourceVersion", event.Object)).ErrStatus, + }) + // We have to abort here because this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data! + return true, 0 + } + + // All is fine; send the event and update lastResourceVersion + ok = rw.send(event) + if !ok { + return true, 0 + } + rw.lastResourceVersion = resourceVersion + + continue + + case watch.Error: + // This round trip allows us to handle unstructured status + errObject := apierrors.FromObject(event.Object) + statusErr, ok := errObject.(*apierrors.StatusError) + if !ok { + klog.Error(spew.Sprintf("Received an error which is not *metav1.Status but %#+v", event.Object)) + // Retry unknown errors + return false, 0 + } + + status := statusErr.ErrStatus + + statusDelay := time.Duration(0) + if status.Details != nil { + statusDelay = time.Duration(status.Details.RetryAfterSeconds) * time.Second + } + + switch status.Code { + case http.StatusGone: + // Never retry RV too old errors + _ = rw.send(event) + return true, 0 + + case http.StatusGatewayTimeout, http.StatusInternalServerError: + // Retry + return false, statusDelay + + default: + // We retry by default. RetryWatcher is meant to proceed unless it is certain + // that it can't. If we are not certain, we proceed with retry and leave it + // up to the user to timeout if needed. + + // Log here so we have a record of hitting the unexpected error + // and we can whitelist some error codes if we missed any that are expected. + klog.V(5).Info(spew.Sprintf("Retrying after unexpected error: %#+v", event.Object)) + + // Retry + return false, statusDelay + } + + default: + klog.Errorf("Failed to recognize Event type %q", event.Type) + _ = rw.send(watch.Event{ + Type: watch.Error, + Object: &apierrors.NewInternalError(fmt.Errorf("retryWatcher failed to recognize Event type %q", event.Type)).ErrStatus, + }) + // We are unable to restart the watch and have to stop the loop or this might cause lastResourceVersion inconsistency by skipping a potential RV with valid data! + return true, 0 + } + } + } +} + +// receive reads the result from a watcher, restarting it if necessary. +func (rw *RetryWatcher) receive() { + defer close(rw.doneChan) + defer close(rw.resultChan) + + klog.V(4).Info("Starting RetryWatcher.") + defer klog.V(4).Info("Stopping RetryWatcher.") + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + select { + case <-rw.stopChan: + cancel() + return + case <-ctx.Done(): + return + } + }() + + // We use non sliding until so we don't introduce delays on happy path when WATCH call + // timeouts or gets closed and we need to reestablish it while also avoiding hot loops. + wait.NonSlidingUntilWithContext(ctx, func(ctx context.Context) { + done, retryAfter := rw.doReceive() + if done { + cancel() + return + } + + time.Sleep(retryAfter) + + klog.V(4).Infof("Restarting RetryWatcher at RV=%q", rw.lastResourceVersion) + }, rw.minRestartDelay) +} + +// ResultChan implements Interface. +func (rw *RetryWatcher) ResultChan() <-chan watch.Event { + return rw.resultChan +} + +// Stop implements Interface. +func (rw *RetryWatcher) Stop() { + close(rw.stopChan) +} + +// Done allows the caller to be notified when Retry watcher stops. +func (rw *RetryWatcher) Done() <-chan struct{} { + return rw.doneChan +} diff --git a/vendor/k8s.io/client-go/tools/watch/until.go b/vendor/k8s.io/client-go/tools/watch/until.go new file mode 100644 index 000000000..e12d82aca --- /dev/null +++ b/vendor/k8s.io/client-go/tools/watch/until.go @@ -0,0 +1,236 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package watch + +import ( + "context" + "errors" + "fmt" + "time" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" + "k8s.io/klog" +) + +// PreconditionFunc returns true if the condition has been reached, false if it has not been reached yet, +// or an error if the condition failed or detected an error state. +type PreconditionFunc func(store cache.Store) (bool, error) + +// ConditionFunc returns true if the condition has been reached, false if it has not been reached yet, +// or an error if the condition cannot be checked and should terminate. In general, it is better to define +// level driven conditions over edge driven conditions (pod has ready=true, vs pod modified and ready changed +// from false to true). +type ConditionFunc func(event watch.Event) (bool, error) + +// ErrWatchClosed is returned when the watch channel is closed before timeout in UntilWithoutRetry. +var ErrWatchClosed = errors.New("watch closed before UntilWithoutRetry timeout") + +// UntilWithoutRetry reads items from the watch until each provided condition succeeds, and then returns the last watch +// encountered. The first condition that returns an error terminates the watch (and the event is also returned). +// If no event has been received, the returned event will be nil. +// Conditions are satisfied sequentially so as to provide a useful primitive for higher level composition. +// Waits until context deadline or until context is canceled. +// +// Warning: Unless you have a very specific use case (probably a special Watcher) don't use this function!!! +// Warning: This will fail e.g. on API timeouts and/or 'too old resource version' error. +// Warning: You are most probably looking for a function *Until* or *UntilWithSync* below, +// Warning: solving such issues. +// TODO: Consider making this function private to prevent misuse when the other occurrences in our codebase are gone. +func UntilWithoutRetry(ctx context.Context, watcher watch.Interface, conditions ...ConditionFunc) (*watch.Event, error) { + ch := watcher.ResultChan() + defer watcher.Stop() + var lastEvent *watch.Event + for _, condition := range conditions { + // check the next condition against the previous event and short circuit waiting for the next watch + if lastEvent != nil { + done, err := condition(*lastEvent) + if err != nil { + return lastEvent, err + } + if done { + continue + } + } + ConditionSucceeded: + for { + select { + case event, ok := <-ch: + if !ok { + return lastEvent, ErrWatchClosed + } + lastEvent = &event + + done, err := condition(event) + if err != nil { + return lastEvent, err + } + if done { + break ConditionSucceeded + } + + case <-ctx.Done(): + return lastEvent, wait.ErrWaitTimeout + } + } + } + return lastEvent, nil +} + +// Until wraps the watcherClient's watch function with RetryWatcher making sure that watcher gets restarted in case of errors. +// The initialResourceVersion will be given to watch method when first called. It shall not be "" or "0" +// given the underlying WATCH call issues (#74022). If you want the initial list ("", "0") done for you use ListWatchUntil instead. +// Remaining behaviour is identical to function UntilWithoutRetry. (See above.) +// Until can deal with API timeouts and lost connections. +// It guarantees you to see all events and in the order they happened. +// Due to this guarantee there is no way it can deal with 'Resource version too old error'. It will fail in this case. +// (See `UntilWithSync` if you'd prefer to recover from all the errors including RV too old by re-listing +// those items. In normal code you should care about being level driven so you'd not care about not seeing all the edges.) +// The most frequent usage for Until would be a test where you want to verify exact order of events ("edges"). +func Until(ctx context.Context, initialResourceVersion string, watcherClient cache.Watcher, conditions ...ConditionFunc) (*watch.Event, error) { + w, err := NewRetryWatcher(initialResourceVersion, watcherClient) + if err != nil { + return nil, err + } + + return UntilWithoutRetry(ctx, w, conditions...) +} + +// UntilWithSync creates an informer from lw, optionally checks precondition when the store is synced, +// and watches the output until each provided condition succeeds, in a way that is identical +// to function UntilWithoutRetry. (See above.) +// UntilWithSync can deal with all errors like API timeout, lost connections and 'Resource version too old'. +// It is the only function that can recover from 'Resource version too old', Until and UntilWithoutRetry will +// just fail in that case. On the other hand it can't provide you with guarantees as strong as using simple +// Watch method with Until. It can skip some intermediate events in case of watch function failing but it will +// re-list to recover and you always get an event, if there has been a change, after recovery. +// Also with the current implementation based on DeltaFIFO, order of the events you receive is guaranteed only for +// particular object, not between more of them even it's the same resource. +// The most frequent usage would be a command that needs to watch the "state of the world" and should't fail, like: +// waiting for object reaching a state, "small" controllers, ... +func UntilWithSync(ctx context.Context, lw cache.ListerWatcher, objType runtime.Object, precondition PreconditionFunc, conditions ...ConditionFunc) (*watch.Event, error) { + indexer, informer, watcher, done := NewIndexerInformerWatcher(lw, objType) + // We need to wait for the internal informers to fully stop so it's easier to reason about + // and it works with non-thread safe clients. + defer func() { <-done }() + // Proxy watcher can be stopped multiple times so it's fine to use defer here to cover alternative branches and + // let UntilWithoutRetry to stop it + defer watcher.Stop() + + if precondition != nil { + if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) { + return nil, fmt.Errorf("UntilWithSync: unable to sync caches: %v", ctx.Err()) + } + + done, err := precondition(indexer) + if err != nil { + return nil, err + } + + if done { + return nil, nil + } + } + + return UntilWithoutRetry(ctx, watcher, conditions...) +} + +// ContextWithOptionalTimeout wraps context.WithTimeout and handles infinite timeouts expressed as 0 duration. +func ContextWithOptionalTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { + if timeout < 0 { + // This should be handled in validation + klog.Errorf("Timeout for context shall not be negative!") + timeout = 0 + } + + if timeout == 0 { + return context.WithCancel(parent) + } + + return context.WithTimeout(parent, timeout) +} + +// ListWatchUntil first lists objects, converts them into synthetic ADDED events +// and checks conditions for those synthetic events. If the conditions have not been reached so far +// it continues by calling Until which establishes a watch from resourceVersion of the list call +// to evaluate those conditions based on new events. +// ListWatchUntil provides the same guarantees as Until and replaces the old WATCH from RV "" (or "0") +// which was mixing list and watch calls internally and having severe design issues. (see #74022) +// There is no resourceVersion order guarantee for the initial list and those synthetic events. +func ListWatchUntil(ctx context.Context, lw cache.ListerWatcher, conditions ...ConditionFunc) (*watch.Event, error) { + if len(conditions) == 0 { + return nil, nil + } + + list, err := lw.List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + initialItems, err := meta.ExtractList(list) + if err != nil { + return nil, err + } + + // use the initial items as simulated "adds" + var lastEvent *watch.Event + currIndex := 0 + passedConditions := 0 + for _, condition := range conditions { + // check the next condition against the previous event and short circuit waiting for the next watch + if lastEvent != nil { + done, err := condition(*lastEvent) + if err != nil { + return lastEvent, err + } + if done { + passedConditions = passedConditions + 1 + continue + } + } + + ConditionSucceeded: + for currIndex < len(initialItems) { + lastEvent = &watch.Event{Type: watch.Added, Object: initialItems[currIndex]} + currIndex++ + + done, err := condition(*lastEvent) + if err != nil { + return lastEvent, err + } + if done { + passedConditions = passedConditions + 1 + break ConditionSucceeded + } + } + } + if passedConditions == len(conditions) { + return lastEvent, nil + } + remainingConditions := conditions[passedConditions:] + + metaObj, err := meta.ListAccessor(list) + if err != nil { + return nil, err + } + currResourceVersion := metaObj.GetResourceVersion() + + return Until(ctx, currResourceVersion, lw, remainingConditions...) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go new file mode 100644 index 000000000..b1aa8c008 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/errors.go @@ -0,0 +1,79 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "fmt" +) + +type errors struct { + errors []error +} + +func (e *errors) Errors() []error { + return e.errors +} + +func (e *errors) AppendErrors(err ...error) { + e.errors = append(e.errors, err...) +} + +type ValidationError struct { + Path string + Err error +} + +func (e ValidationError) Error() string { + return fmt.Sprintf("ValidationError(%s): %v", e.Path, e.Err) +} + +type InvalidTypeError struct { + Path string + Expected string + Actual string +} + +func (e InvalidTypeError) Error() string { + return fmt.Sprintf("invalid type for %s: got %q, expected %q", e.Path, e.Actual, e.Expected) +} + +type MissingRequiredFieldError struct { + Path string + Field string +} + +func (e MissingRequiredFieldError) Error() string { + return fmt.Sprintf("missing required field %q in %s", e.Field, e.Path) +} + +type UnknownFieldError struct { + Path string + Field string +} + +func (e UnknownFieldError) Error() string { + return fmt.Sprintf("unknown field %q in %s", e.Field, e.Path) +} + +type InvalidObjectTypeError struct { + Path string + Type string +} + +func (e InvalidObjectTypeError) Error() string { + return fmt.Sprintf("unknown object type %q in %s", e.Type, e.Path) +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go new file mode 100644 index 000000000..6a9f68c0d --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/types.go @@ -0,0 +1,299 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "reflect" + "sort" + + "k8s.io/kube-openapi/pkg/util/proto" +) + +type validationItem interface { + proto.SchemaVisitor + + Errors() []error + Path() *proto.Path +} + +type baseItem struct { + errors errors + path proto.Path +} + +// Errors returns the list of errors found for this item. +func (item *baseItem) Errors() []error { + return item.errors.Errors() +} + +// AddValidationError wraps the given error into a ValidationError and +// attaches it to this item. +func (item *baseItem) AddValidationError(err error) { + item.errors.AppendErrors(ValidationError{Path: item.path.String(), Err: err}) +} + +// AddError adds a regular (non-validation related) error to the list. +func (item *baseItem) AddError(err error) { + item.errors.AppendErrors(err) +} + +// CopyErrors adds a list of errors to this item. This is useful to copy +// errors from subitems. +func (item *baseItem) CopyErrors(errs []error) { + item.errors.AppendErrors(errs...) +} + +// Path returns the path of this item, helps print useful errors. +func (item *baseItem) Path() *proto.Path { + return &item.path +} + +// mapItem represents a map entry in the yaml. +type mapItem struct { + baseItem + + Map map[string]interface{} +} + +func (item *mapItem) sortedKeys() []string { + sortedKeys := []string{} + for key := range item.Map { + sortedKeys = append(sortedKeys, key) + } + sort.Strings(sortedKeys) + return sortedKeys +} + +var _ validationItem = &mapItem{} + +func (item *mapItem) VisitPrimitive(schema *proto.Primitive) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "map"}) +} + +func (item *mapItem) VisitArray(schema *proto.Array) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: "map"}) +} + +func (item *mapItem) VisitMap(schema *proto.Map) { + for _, key := range item.sortedKeys() { + subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key]) + if err != nil { + item.AddError(err) + continue + } + schema.SubType.Accept(subItem) + item.CopyErrors(subItem.Errors()) + } +} + +func (item *mapItem) VisitKind(schema *proto.Kind) { + // Verify each sub-field. + for _, key := range item.sortedKeys() { + if item.Map[key] == nil { + continue + } + subItem, err := itemFactory(item.Path().FieldPath(key), item.Map[key]) + if err != nil { + item.AddError(err) + continue + } + if _, ok := schema.Fields[key]; !ok { + item.AddValidationError(UnknownFieldError{Path: schema.GetPath().String(), Field: key}) + continue + } + schema.Fields[key].Accept(subItem) + item.CopyErrors(subItem.Errors()) + } + + // Verify that all required fields are present. + for _, required := range schema.RequiredFields { + if v, ok := item.Map[required]; !ok || v == nil { + item.AddValidationError(MissingRequiredFieldError{Path: schema.GetPath().String(), Field: required}) + } + } +} + +func (item *mapItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *mapItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// arrayItem represents a yaml array. +type arrayItem struct { + baseItem + + Array []interface{} +} + +var _ validationItem = &arrayItem{} + +func (item *arrayItem) VisitPrimitive(schema *proto.Primitive) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: "array"}) +} + +func (item *arrayItem) VisitArray(schema *proto.Array) { + for i, v := range item.Array { + path := item.Path().ArrayPath(i) + if v == nil { + item.AddValidationError(InvalidObjectTypeError{Type: "nil", Path: path.String()}) + continue + } + subItem, err := itemFactory(path, v) + if err != nil { + item.AddError(err) + continue + } + schema.SubType.Accept(subItem) + item.CopyErrors(subItem.Errors()) + } +} + +func (item *arrayItem) VisitMap(schema *proto.Map) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"}) +} + +func (item *arrayItem) VisitKind(schema *proto.Kind) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: "array"}) +} + +func (item *arrayItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *arrayItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// primitiveItem represents a yaml value. +type primitiveItem struct { + baseItem + + Value interface{} + Kind string +} + +var _ validationItem = &primitiveItem{} + +func (item *primitiveItem) VisitPrimitive(schema *proto.Primitive) { + // Some types of primitives can match more than one (a number + // can be a string, but not the other way around). Return from + // the switch if we have a valid possible type conversion + // NOTE(apelisse): This logic is blindly copied from the + // existing swagger logic, and I'm not sure I agree with it. + switch schema.Type { + case proto.Boolean: + switch item.Kind { + case proto.Boolean: + return + } + case proto.Integer: + switch item.Kind { + case proto.Integer, proto.Number: + return + } + case proto.Number: + switch item.Kind { + case proto.Number: + return + } + case proto.String: + return + } + // TODO(wrong): this misses "null" + + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: schema.Type, Actual: item.Kind}) +} + +func (item *primitiveItem) VisitArray(schema *proto.Array) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "array", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitMap(schema *proto.Map) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitKind(schema *proto.Kind) { + item.AddValidationError(InvalidTypeError{Path: schema.GetPath().String(), Expected: "map", Actual: item.Kind}) +} + +func (item *primitiveItem) VisitArbitrary(schema *proto.Arbitrary) { +} + +func (item *primitiveItem) VisitReference(schema proto.Reference) { + // passthrough + schema.SubSchema().Accept(item) +} + +// itemFactory creates the relevant item type/visitor based on the current yaml type. +func itemFactory(path proto.Path, v interface{}) (validationItem, error) { + // We need to special case for no-type fields in yaml (e.g. empty item in list) + if v == nil { + return nil, InvalidObjectTypeError{Type: "nil", Path: path.String()} + } + kind := reflect.TypeOf(v).Kind() + switch kind { + case reflect.Bool: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Boolean, + }, nil + case reflect.Int, + reflect.Int8, + reflect.Int16, + reflect.Int32, + reflect.Int64, + reflect.Uint, + reflect.Uint8, + reflect.Uint16, + reflect.Uint32, + reflect.Uint64: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Integer, + }, nil + case reflect.Float32, + reflect.Float64: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.Number, + }, nil + case reflect.String: + return &primitiveItem{ + baseItem: baseItem{path: path}, + Value: v, + Kind: proto.String, + }, nil + case reflect.Array, + reflect.Slice: + return &arrayItem{ + baseItem: baseItem{path: path}, + Array: v.([]interface{}), + }, nil + case reflect.Map: + return &mapItem{ + baseItem: baseItem{path: path}, + Map: v.(map[string]interface{}), + }, nil + } + return nil, InvalidObjectTypeError{Type: kind.String(), Path: path.String()} +} diff --git a/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go new file mode 100644 index 000000000..35310f637 --- /dev/null +++ b/vendor/k8s.io/kube-openapi/pkg/util/proto/validation/validation.go @@ -0,0 +1,30 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "k8s.io/kube-openapi/pkg/util/proto" +) + +func ValidateModel(obj interface{}, schema proto.Schema, name string) []error { + rootValidation, err := itemFactory(proto.NewPath(name), obj) + if err != nil { + return []error{err} + } + schema.Accept(rootValidation) + return rootValidation.Errors() +} diff --git a/vendor/k8s.io/kubectl/LICENSE b/vendor/k8s.io/kubectl/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/vendor/k8s.io/kubectl/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn.go b/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn.go new file mode 100644 index 000000000..af99c3f64 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn.go @@ -0,0 +1,260 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "bufio" + "bytes" + "fmt" + "io" + "reflect" + "regexp" + "strings" + + "github.com/liggitt/tabwriter" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/client-go/util/jsonpath" +) + +var jsonRegexp = regexp.MustCompile(`^\{\.?([^{}]+)\}$|^\.?([^{}]+)$`) + +// RelaxedJSONPathExpression attempts to be flexible with JSONPath expressions, it accepts: +// * metadata.name (no leading '.' or curly braces '{...}' +// * {metadata.name} (no leading '.') +// * .metadata.name (no curly braces '{...}') +// * {.metadata.name} (complete expression) +// And transforms them all into a valid jsonpath expression: +// {.metadata.name} +func RelaxedJSONPathExpression(pathExpression string) (string, error) { + if len(pathExpression) == 0 { + return pathExpression, nil + } + submatches := jsonRegexp.FindStringSubmatch(pathExpression) + if submatches == nil { + return "", fmt.Errorf("unexpected path string, expected a 'name1.name2' or '.name1.name2' or '{name1.name2}' or '{.name1.name2}'") + } + if len(submatches) != 3 { + return "", fmt.Errorf("unexpected submatch list: %v", submatches) + } + var fieldSpec string + if len(submatches[1]) != 0 { + fieldSpec = submatches[1] + } else { + fieldSpec = submatches[2] + } + return fmt.Sprintf("{.%s}", fieldSpec), nil +} + +// NewCustomColumnsPrinterFromSpec creates a custom columns printer from a comma separated list of
: pairs. +// e.g. NAME:metadata.name,API_VERSION:apiVersion creates a printer that prints: +// +// NAME API_VERSION +// foo bar +func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder, noHeaders bool) (*CustomColumnsPrinter, error) { + if len(spec) == 0 { + return nil, fmt.Errorf("custom-columns format specified but no custom columns given") + } + parts := strings.Split(spec, ",") + columns := make([]Column, len(parts)) + for ix := range parts { + colSpec := strings.SplitN(parts[ix], ":", 2) + if len(colSpec) != 2 { + return nil, fmt.Errorf("unexpected custom-columns spec: %s, expected
:", parts[ix]) + } + spec, err := RelaxedJSONPathExpression(colSpec[1]) + if err != nil { + return nil, err + } + columns[ix] = Column{Header: colSpec[0], FieldSpec: spec} + } + return &CustomColumnsPrinter{Columns: columns, Decoder: decoder, NoHeaders: noHeaders}, nil +} + +func splitOnWhitespace(line string) []string { + lineScanner := bufio.NewScanner(bytes.NewBufferString(line)) + lineScanner.Split(bufio.ScanWords) + result := []string{} + for lineScanner.Scan() { + result = append(result, lineScanner.Text()) + } + return result +} + +// NewCustomColumnsPrinterFromTemplate creates a custom columns printer from a template stream. The template is expected +// to consist of two lines, whitespace separated. The first line is the header line, the second line is the jsonpath field spec +// For example, the template below: +// NAME API_VERSION +// {metadata.name} {apiVersion} +func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader, decoder runtime.Decoder) (*CustomColumnsPrinter, error) { + scanner := bufio.NewScanner(templateReader) + if !scanner.Scan() { + return nil, fmt.Errorf("invalid template, missing header line. Expected format is one line of space separated headers, one line of space separated column specs.") + } + headers := splitOnWhitespace(scanner.Text()) + + if !scanner.Scan() { + return nil, fmt.Errorf("invalid template, missing spec line. Expected format is one line of space separated headers, one line of space separated column specs.") + } + specs := splitOnWhitespace(scanner.Text()) + + if len(headers) != len(specs) { + return nil, fmt.Errorf("number of headers (%d) and field specifications (%d) don't match", len(headers), len(specs)) + } + + columns := make([]Column, len(headers)) + for ix := range headers { + spec, err := RelaxedJSONPathExpression(specs[ix]) + if err != nil { + return nil, err + } + columns[ix] = Column{ + Header: headers[ix], + FieldSpec: spec, + } + } + return &CustomColumnsPrinter{Columns: columns, Decoder: decoder, NoHeaders: false}, nil +} + +// Column represents a user specified column +type Column struct { + // The header to print above the column, general style is ALL_CAPS + Header string + // The pointer to the field in the object to print in JSONPath form + // e.g. {.ObjectMeta.Name}, see pkg/util/jsonpath for more details. + FieldSpec string +} + +// CustomColumnPrinter is a printer that knows how to print arbitrary columns +// of data from templates specified in the `Columns` array +type CustomColumnsPrinter struct { + Columns []Column + Decoder runtime.Decoder + NoHeaders bool + // lastType records type of resource printed last so that we don't repeat + // header while printing same type of resources. + lastType reflect.Type +} + +func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if printers.InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(printers.InternalObjectPrinterErr) + } + + if w, found := out.(*tabwriter.Writer); !found { + w = printers.GetNewTabWriter(out) + out = w + defer w.Flush() + } + + t := reflect.TypeOf(obj) + if !s.NoHeaders && t != s.lastType { + headers := make([]string, len(s.Columns)) + for ix := range s.Columns { + headers[ix] = s.Columns[ix].Header + } + fmt.Fprintln(out, strings.Join(headers, "\t")) + s.lastType = t + } + parsers := make([]*jsonpath.JSONPath, len(s.Columns)) + for ix := range s.Columns { + parsers[ix] = jsonpath.New(fmt.Sprintf("column%d", ix)).AllowMissingKeys(true) + if err := parsers[ix].Parse(s.Columns[ix].FieldSpec); err != nil { + return err + } + } + + if meta.IsListType(obj) { + objs, err := meta.ExtractList(obj) + if err != nil { + return err + } + for ix := range objs { + if err := s.printOneObject(objs[ix], parsers, out); err != nil { + return err + } + } + } else { + if err := s.printOneObject(obj, parsers, out); err != nil { + return err + } + } + return nil +} + +func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jsonpath.JSONPath, out io.Writer) error { + columns := make([]string, len(parsers)) + switch u := obj.(type) { + case *metav1.WatchEvent: + if printers.InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(u.Object.Object)).Type().PkgPath()) { + return fmt.Errorf(printers.InternalObjectPrinterErr) + } + unstructuredObject, err := runtime.DefaultUnstructuredConverter.ToUnstructured(u.Object.Object) + if err != nil { + return err + } + obj = &unstructured.Unstructured{ + Object: map[string]interface{}{ + "type": u.Type, + "object": unstructuredObject, + }, + } + + case *runtime.Unknown: + if len(u.Raw) > 0 { + var err error + if obj, err = runtime.Decode(s.Decoder, u.Raw); err != nil { + return fmt.Errorf("can't decode object for printing: %v (%s)", err, u.Raw) + } + } + } + + for ix := range parsers { + parser := parsers[ix] + + var values [][]reflect.Value + var err error + if unstructured, ok := obj.(runtime.Unstructured); ok { + values, err = parser.FindResults(unstructured.UnstructuredContent()) + } else { + values, err = parser.FindResults(reflect.ValueOf(obj).Elem().Interface()) + } + + if err != nil { + return err + } + valueStrings := []string{} + if len(values) == 0 || len(values[0]) == 0 { + valueStrings = append(valueStrings, "") + } + for arrIx := range values { + for valIx := range values[arrIx] { + valueStrings = append(valueStrings, fmt.Sprintf("%v", values[arrIx][valIx].Interface())) + } + } + columns[ix] = strings.Join(valueStrings, ",") + } + fmt.Fprintln(out, strings.Join(columns, "\t")) + return nil +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn_flags.go b/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn_flags.go new file mode 100644 index 000000000..eee919b49 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/customcolumn_flags.go @@ -0,0 +1,111 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/kubectl/pkg/scheme" +) + +var columnsFormats = map[string]bool{ + "custom-columns-file": true, + "custom-columns": true, +} + +// CustomColumnsPrintFlags provides default flags necessary for printing +// custom resource columns from an inline-template or file. +type CustomColumnsPrintFlags struct { + NoHeaders bool + TemplateArgument string +} + +func (f *CustomColumnsPrintFlags) AllowedFormats() []string { + formats := make([]string, 0, len(columnsFormats)) + for format := range columnsFormats { + formats = append(formats, format) + } + return formats +} + +// ToPrinter receives an templateFormat and returns a printer capable of +// handling custom-column printing. +// Returns false if the specified templateFormat does not match a supported format. +// Supported format types can be found in pkg/printers/printers.go +func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (printers.ResourcePrinter, error) { + if len(templateFormat) == 0 { + return nil, genericclioptions.NoCompatiblePrinterError{} + } + + templateValue := "" + + if len(f.TemplateArgument) == 0 { + for format := range columnsFormats { + format = format + "=" + if strings.HasPrefix(templateFormat, format) { + templateValue = templateFormat[len(format):] + templateFormat = format[:len(format)-1] + break + } + } + } else { + templateValue = f.TemplateArgument + } + + if _, supportedFormat := columnsFormats[templateFormat]; !supportedFormat { + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &templateFormat, AllowedFormats: f.AllowedFormats()} + } + + if len(templateValue) == 0 { + return nil, fmt.Errorf("custom-columns format specified but no custom columns given") + } + + // UniversalDecoder call must specify parameter versions; otherwise it will decode to internal versions. + decoder := scheme.Codecs.UniversalDecoder(scheme.Scheme.PrioritizedVersionsAllGroups()...) + + if templateFormat == "custom-columns-file" { + file, err := os.Open(templateValue) + if err != nil { + return nil, fmt.Errorf("error reading template %s, %v\n", templateValue, err) + } + defer file.Close() + p, err := NewCustomColumnsPrinterFromTemplate(file, decoder) + return p, err + } + + return NewCustomColumnsPrinterFromSpec(templateValue, decoder, f.NoHeaders) +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to custom-columns printing +func (f *CustomColumnsPrintFlags) AddFlags(c *cobra.Command) {} + +// NewCustomColumnsPrintFlags returns flags associated with +// custom-column printing, with default values set. +// NoHeaders and TemplateArgument should be set by callers. +func NewCustomColumnsPrintFlags() *CustomColumnsPrintFlags { + return &CustomColumnsPrintFlags{ + NoHeaders: false, + TemplateArgument: "", + } +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/get.go b/vendor/k8s.io/kubectl/pkg/cmd/get/get.go new file mode 100644 index 000000000..8c148316d --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/get.go @@ -0,0 +1,853 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/url" + + "github.com/spf13/cobra" + + corev1 "k8s.io/api/core/v1" + kapierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/cli-runtime/pkg/resource" + kubernetesscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + watchtools "k8s.io/client-go/tools/watch" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/rawhttp" + "k8s.io/kubectl/pkg/scheme" + "k8s.io/kubectl/pkg/util/i18n" + "k8s.io/kubectl/pkg/util/interrupt" + "k8s.io/kubectl/pkg/util/templates" + utilpointer "k8s.io/utils/pointer" +) + +// GetOptions contains the input to the get command. +type GetOptions struct { + PrintFlags *PrintFlags + ToPrinter func(*meta.RESTMapping, *bool, bool, bool) (printers.ResourcePrinterFunc, error) + IsHumanReadablePrinter bool + PrintWithOpenAPICols bool + + CmdParent string + + resource.FilenameOptions + + Raw string + Watch bool + WatchOnly bool + ChunkSize int64 + + OutputWatchEvents bool + + LabelSelector string + FieldSelector string + AllNamespaces bool + Namespace string + ExplicitNamespace bool + + ServerPrint bool + + NoHeaders bool + Sort bool + IgnoreNotFound bool + Export bool + + genericclioptions.IOStreams +} + +var ( + getLong = templates.LongDesc(` + Display one or many resources + + Prints a table of the most important information about the specified resources. + You can filter the list using a label selector and the --selector flag. If the + desired resource type is namespaced you will only see results in your current + namespace unless you pass --all-namespaces. + + Uninitialized objects are not shown unless --include-uninitialized is passed. + + 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.`) + + getExample = templates.Examples(i18n.T(` + # List all pods in ps output format. + kubectl get pods + + # List all pods in ps output format with more information (such as node name). + kubectl get pods -o wide + + # List a single replication controller with specified NAME in ps output format. + kubectl get replicationcontroller web + + # List deployments in JSON output format, in the "v1" version of the "apps" API group: + kubectl get deployments.v1.apps -o json + + # List a single pod in JSON output format. + kubectl get -o json pod web-pod-13je7 + + # List a pod identified by type and name specified in "pod.yaml" in JSON output format. + kubectl get -f pod.yaml -o json + + # List resources from a directory with kustomization.yaml - e.g. dir/kustomization.yaml. + kubectl get -k dir/ + + # Return only the phase value of the specified pod. + kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}} + + # List resource information in custom columns. + kubectl get pod test-pod -o custom-columns=CONTAINER:.spec.containers[0].name,IMAGE:.spec.containers[0].image + + # List all replication controllers and services together in ps output format. + kubectl get rc,services + + # List one or more resources by their type and names. + kubectl get rc/web service/frontend pods/web-pod-13je7`)) +) + +const ( + useOpenAPIPrintColumnFlagLabel = "use-openapi-print-columns" + useServerPrintColumns = "server-print" +) + +// NewGetOptions returns a GetOptions with default chunk size 500. +func NewGetOptions(parent string, streams genericclioptions.IOStreams) *GetOptions { + return &GetOptions{ + PrintFlags: NewGetPrintFlags(), + CmdParent: parent, + + IOStreams: streams, + ChunkSize: 500, + ServerPrint: true, + } +} + +// NewCmdGet creates a command object for the generic "get" action, which +// retrieves one or more resources from a server. +func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewGetOptions(parent, streams) + + cmd := &cobra.Command{ + Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags]", + DisableFlagsInUseLine: true, + Short: i18n.T("Display one or many resources"), + Long: getLong + "\n\n" + cmdutil.SuggestAPIResources(parent), + Example: getExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate(cmd)) + cmdutil.CheckErr(o.Run(f, cmd, args)) + }, + SuggestFor: []string{"list", "ps"}, + } + + o.PrintFlags.AddFlags(cmd) + + cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.") + cmd.Flags().BoolVarP(&o.Watch, "watch", "w", o.Watch, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.") + cmd.Flags().BoolVar(&o.WatchOnly, "watch-only", o.WatchOnly, "Watch for changes to the requested object(s), without listing/getting first.") + cmd.Flags().BoolVar(&o.OutputWatchEvents, "output-watch-events", o.OutputWatchEvents, "Output watch event objects when --watch or --watch-only is used. Existing objects are output as initial ADDED events.") + cmd.Flags().Int64Var(&o.ChunkSize, "chunk-size", o.ChunkSize, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.") + cmd.Flags().BoolVar(&o.IgnoreNotFound, "ignore-not-found", o.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") + cmd.Flags().StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") + cmd.Flags().StringVar(&o.FieldSelector, "field-selector", o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") + cmd.Flags().BoolVarP(&o.AllNamespaces, "all-namespaces", "A", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") + addOpenAPIPrintColumnFlags(cmd, o) + addServerPrintColumnFlags(cmd, o) + cmd.Flags().BoolVar(&o.Export, "export", o.Export, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.") + cmd.Flags().MarkDeprecated("export", "This flag is deprecated and will be removed in future.") + cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to get from a server.") + return cmd +} + +// Complete takes the command arguments and factory and infers any remaining options. +func (o *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + if len(o.Raw) > 0 { + if len(args) > 0 { + return fmt.Errorf("arguments may not be passed when --raw is specified") + } + return nil + } + + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + if o.AllNamespaces { + o.ExplicitNamespace = false + } + + sortBy, err := cmd.Flags().GetString("sort-by") + if err != nil { + return err + } + o.Sort = len(sortBy) > 0 + + o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers") + + // TODO (soltysh): currently we don't support custom columns + // with server side print. So in these cases force the old behavior. + outputOption := cmd.Flags().Lookup("output").Value.String() + if outputOption == "custom-columns" { + o.ServerPrint = false + } + + templateArg := "" + if o.PrintFlags.TemplateFlags != nil && o.PrintFlags.TemplateFlags.TemplateArgument != nil { + templateArg = *o.PrintFlags.TemplateFlags.TemplateArgument + } + + // human readable printers have special conversion rules, so we determine if we're using one. + if (len(*o.PrintFlags.OutputFormat) == 0 && len(templateArg) == 0) || *o.PrintFlags.OutputFormat == "wide" { + o.IsHumanReadablePrinter = true + } + + o.ToPrinter = func(mapping *meta.RESTMapping, outputObjects *bool, withNamespace bool, withKind bool) (printers.ResourcePrinterFunc, error) { + // make a new copy of current flags / opts before mutating + printFlags := o.PrintFlags.Copy() + + if mapping != nil { + if !cmdSpecifiesOutputFmt(cmd) && o.PrintWithOpenAPICols { + if apiSchema, err := f.OpenAPISchema(); err == nil { + printFlags.UseOpenAPIColumns(apiSchema, mapping) + } + } + printFlags.SetKind(mapping.GroupVersionKind.GroupKind()) + } + if withNamespace { + printFlags.EnsureWithNamespace() + } + if withKind { + printFlags.EnsureWithKind() + } + + printer, err := printFlags.ToPrinter() + if err != nil { + return nil, err + } + printer, err = printers.NewTypeSetter(scheme.Scheme).WrapToPrinter(printer, nil) + if err != nil { + return nil, err + } + + if o.Sort { + printer = &SortingPrinter{Delegate: printer, SortField: sortBy} + } + if outputObjects != nil { + printer = &skipPrinter{delegate: printer, output: outputObjects} + } + if o.ServerPrint { + printer = &TablePrinter{Delegate: printer} + } + return printer.PrintObj, nil + } + + switch { + case o.Watch || o.WatchOnly: + if o.Sort { + fmt.Fprintf(o.IOStreams.ErrOut, "warning: --watch or --watch-only requested, --sort-by will be ignored\n") + } + default: + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) { + fmt.Fprintf(o.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.SuggestAPIResources(o.CmdParent)) + fullCmdName := cmd.Parent().CommandPath() + usageString := "Required resource not specified." + if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { + usageString = fmt.Sprintf("%s\nUse \"%s explain \" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) + } + + return cmdutil.UsageErrorf(cmd, usageString) + } + } + + // openapi printing is mutually exclusive with server side printing + if o.PrintWithOpenAPICols && o.ServerPrint { + fmt.Fprintf(o.IOStreams.ErrOut, "warning: --%s requested, --%s will be ignored\n", useOpenAPIPrintColumnFlagLabel, useServerPrintColumns) + } + + return nil +} + +// Validate checks the set of flags provided by the user. +func (o *GetOptions) Validate(cmd *cobra.Command) error { + if len(o.Raw) > 0 { + if o.Watch || o.WatchOnly || len(o.LabelSelector) > 0 || o.Export { + return fmt.Errorf("--raw may not be specified with other flags that filter the server request or alter the output") + } + if len(cmdutil.GetFlagString(cmd, "output")) > 0 { + return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") + } + if _, err := url.ParseRequestURI(o.Raw); err != nil { + return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) + } + } + if cmdutil.GetFlagBool(cmd, "show-labels") { + outputOption := cmd.Flags().Lookup("output").Value.String() + if outputOption != "" && outputOption != "wide" { + return fmt.Errorf("--show-labels option cannot be used with %s printer", outputOption) + } + } + if o.OutputWatchEvents && !(o.Watch || o.WatchOnly) { + return cmdutil.UsageErrorf(cmd, "--output-watch-events option can only be used with --watch or --watch-only") + } + return nil +} + +// OriginalPositioner and NopPositioner is required for swap/sort operations of data in table format +type OriginalPositioner interface { + OriginalPosition(int) int +} + +// NopPositioner and OriginalPositioner is required for swap/sort operations of data in table format +type NopPositioner struct{} + +// OriginalPosition returns the original position from NopPositioner object +func (t *NopPositioner) OriginalPosition(ix int) int { + return ix +} + +// RuntimeSorter holds the required objects to perform sorting of runtime objects +type RuntimeSorter struct { + field string + decoder runtime.Decoder + objects []runtime.Object + positioner OriginalPositioner +} + +// Sort performs the sorting of runtime objects +func (r *RuntimeSorter) Sort() error { + // a list is only considered "sorted" if there are 0 or 1 items in it + // AND (if 1 item) the item is not a Table object + if len(r.objects) == 0 { + return nil + } + if len(r.objects) == 1 { + _, isTable := r.objects[0].(*metav1beta1.Table) + if !isTable { + return nil + } + } + + includesTable := false + includesRuntimeObjs := false + + for _, obj := range r.objects { + switch t := obj.(type) { + case *metav1beta1.Table: + includesTable = true + + if sorter, err := NewTableSorter(t, r.field); err != nil { + return err + } else if err := sorter.Sort(); err != nil { + return err + } + default: + includesRuntimeObjs = true + } + } + + // we use a NopPositioner when dealing with Table objects + // because the objects themselves are not swapped, but rather + // the rows in each object are swapped / sorted. + r.positioner = &NopPositioner{} + + if includesRuntimeObjs && includesTable { + return fmt.Errorf("sorting is not supported on mixed Table and non-Table object lists") + } + if includesTable { + return nil + } + + // if not dealing with a Table response from the server, assume + // all objects are runtime.Object as usual, and sort using old method. + var err error + if r.positioner, err = SortObjects(r.decoder, r.objects, r.field); err != nil { + return err + } + return nil +} + +// OriginalPosition returns the original position of a runtime object +func (r *RuntimeSorter) OriginalPosition(ix int) int { + if r.positioner == nil { + return 0 + } + return r.positioner.OriginalPosition(ix) +} + +// WithDecoder allows custom decoder to be set for testing +func (r *RuntimeSorter) WithDecoder(decoder runtime.Decoder) *RuntimeSorter { + r.decoder = decoder + return r +} + +// NewRuntimeSorter returns a new instance of RuntimeSorter +func NewRuntimeSorter(objects []runtime.Object, sortBy string) *RuntimeSorter { + parsedField, err := RelaxedJSONPathExpression(sortBy) + if err != nil { + parsedField = sortBy + } + + return &RuntimeSorter{ + field: parsedField, + decoder: kubernetesscheme.Codecs.UniversalDecoder(), + objects: objects, + } +} + +func (o *GetOptions) transformRequests(req *rest.Request) { + // We need full objects if printing with openapi columns + if o.PrintWithOpenAPICols { + return + } + if !o.ServerPrint || !o.IsHumanReadablePrinter { + return + } + + group := metav1beta1.GroupName + version := metav1beta1.SchemeGroupVersion.Version + + tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group) + req.SetHeader("Accept", tableParam) + + // if sorting, ensure we receive the full object in order to introspect its fields via jsonpath + if o.Sort { + req.Param("includeObject", "Object") + } +} + +// Run performs the get operation. +// TODO: remove the need to pass these arguments, like other commands. +func (o *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + if len(o.Raw) > 0 { + restClient, err := f.RESTClient() + if err != nil { + return err + } + return rawhttp.RawGet(restClient, o.IOStreams, o.Raw) + } + if o.Watch || o.WatchOnly { + return o.watch(f, cmd, args) + } + + chunkSize := o.ChunkSize + if o.Sort { + // TODO(juanvallejo): in the future, we could have the client use chunking + // to gather all results, then sort them all at the end to reduce server load. + chunkSize = 0 + } + + r := f.NewBuilder(). + Unstructured(). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). + ExportParam(o.Export). + RequestChunksOf(chunkSize). + ResourceTypeOrNameArgs(true, args...). + ContinueOnError(). + Latest(). + Flatten(). + TransformRequests(o.transformRequests). + Do() + + if o.IgnoreNotFound { + r.IgnoreErrors(kapierrors.IsNotFound) + } + if err := r.Err(); err != nil { + return err + } + + if !o.IsHumanReadablePrinter { + return o.printGeneric(r) + } + + allErrs := []error{} + errs := sets.NewString() + infos, err := r.Infos() + if err != nil { + allErrs = append(allErrs, err) + } + printWithKind := multipleGVKsRequested(infos) + + objs := make([]runtime.Object, len(infos)) + for ix := range infos { + objs[ix] = infos[ix].Object + } + + sorting, err := cmd.Flags().GetString("sort-by") + if err != nil { + return err + } + + var positioner OriginalPositioner + if o.Sort { + sorter := NewRuntimeSorter(objs, sorting) + if err := sorter.Sort(); err != nil { + return err + } + positioner = sorter + } + + var printer printers.ResourcePrinter + var lastMapping *meta.RESTMapping + + // track if we write any output + trackingWriter := &trackingWriterWrapper{Delegate: o.Out} + // output an empty line separating output + separatorWriter := &separatorWriterWrapper{Delegate: trackingWriter} + + w := printers.GetNewTabWriter(separatorWriter) + for ix := range objs { + var mapping *meta.RESTMapping + var info *resource.Info + if positioner != nil { + info = infos[positioner.OriginalPosition(ix)] + mapping = info.Mapping + } else { + info = infos[ix] + mapping = info.Mapping + } + + printWithNamespace := o.AllNamespaces + + if mapping != nil && mapping.Scope.Name() == meta.RESTScopeNameRoot { + printWithNamespace = false + } + + if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) { + w.Flush() + w.SetRememberedWidths(nil) + + // add linebreaks between resource groups (if there is more than one) + // when it satisfies all following 3 conditions: + // 1) it's not the first resource group + // 2) it has row header + // 3) we've written output since the last time we started a new set of headers + if lastMapping != nil && !o.NoHeaders && trackingWriter.Written > 0 { + separatorWriter.SetReady(true) + } + + printer, err = o.ToPrinter(mapping, nil, printWithNamespace, printWithKind) + if err != nil { + if !errs.Has(err.Error()) { + errs.Insert(err.Error()) + allErrs = append(allErrs, err) + } + continue + } + + lastMapping = mapping + } + + // ensure a versioned object is passed to the custom-columns printer + // if we are using OpenAPI columns to print + if o.PrintWithOpenAPICols { + printer.PrintObj(info.Object, w) + continue + } + + printer.PrintObj(info.Object, w) + } + w.Flush() + if trackingWriter.Written == 0 && !o.IgnoreNotFound && len(allErrs) == 0 { + // if we wrote no output, and had no errors, and are not ignoring NotFound, be sure we output something + if !o.AllNamespaces { + fmt.Fprintln(o.ErrOut, fmt.Sprintf("No resources found in %s namespace.", o.Namespace)) + } else { + fmt.Fprintln(o.ErrOut, fmt.Sprintf("No resources found")) + } + } + return utilerrors.NewAggregate(allErrs) +} + +type trackingWriterWrapper struct { + Delegate io.Writer + Written int +} + +func (t *trackingWriterWrapper) Write(p []byte) (n int, err error) { + t.Written += len(p) + return t.Delegate.Write(p) +} + +type separatorWriterWrapper struct { + Delegate io.Writer + Ready bool +} + +func (s *separatorWriterWrapper) Write(p []byte) (n int, err error) { + // If we're about to write non-empty bytes and `s` is ready, + // we prepend an empty line to `p` and reset `s.Read`. + if len(p) != 0 && s.Ready { + fmt.Fprintln(s.Delegate) + s.Ready = false + } + return s.Delegate.Write(p) +} + +func (s *separatorWriterWrapper) SetReady(state bool) { + s.Ready = state +} + +// watch starts a client-side watch of one or more resources. +// TODO: remove the need for arguments here. +func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error { + r := f.NewBuilder(). + Unstructured(). + NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + LabelSelectorParam(o.LabelSelector). + FieldSelectorParam(o.FieldSelector). + ExportParam(o.Export). + RequestChunksOf(o.ChunkSize). + ResourceTypeOrNameArgs(true, args...). + SingleResourceType(). + Latest(). + TransformRequests(o.transformRequests). + Do() + if err := r.Err(); err != nil { + return err + } + infos, err := r.Infos() + if err != nil { + return err + } + if multipleGVKsRequested(infos) { + return i18n.Errorf("watch is only supported on individual resources and resource collections - more than 1 resource was found") + } + + info := infos[0] + mapping := info.ResourceMapping() + outputObjects := utilpointer.BoolPtr(!o.WatchOnly) + printer, err := o.ToPrinter(mapping, outputObjects, o.AllNamespaces, false) + if err != nil { + return err + } + obj, err := r.Object() + if err != nil { + return err + } + + // watching from resourceVersion 0, starts the watch at ~now and + // will return an initial watch event. Starting form ~now, rather + // the rv of the object will insure that we start the watch from + // inside the watch window, which the rv of the object might not be. + rv := "0" + isList := meta.IsListType(obj) + if isList { + // the resourceVersion of list objects is ~now but won't return + // an initial watch event + rv, err = meta.NewAccessor().ResourceVersion(obj) + if err != nil { + return err + } + } + + writer := printers.GetNewTabWriter(o.Out) + + // print the current object + var objsToPrint []runtime.Object + if isList { + objsToPrint, _ = meta.ExtractList(obj) + } else { + objsToPrint = append(objsToPrint, obj) + } + for _, objToPrint := range objsToPrint { + if o.OutputWatchEvents { + objToPrint = &metav1.WatchEvent{Type: string(watch.Added), Object: runtime.RawExtension{Object: objToPrint}} + } + if err := printer.PrintObj(objToPrint, writer); err != nil { + return fmt.Errorf("unable to output the provided object: %v", err) + } + } + writer.Flush() + if isList { + // we can start outputting objects now, watches started from lists don't emit synthetic added events + *outputObjects = true + } else { + // suppress output, since watches started for individual items emit a synthetic ADDED event first + *outputObjects = false + } + + // print watched changes + w, err := r.Watch(rv) + if err != nil { + return err + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + intr := interrupt.New(nil, cancel) + intr.Run(func() error { + _, err := watchtools.UntilWithoutRetry(ctx, w, func(e watch.Event) (bool, error) { + objToPrint := e.Object + if o.OutputWatchEvents { + objToPrint = &metav1.WatchEvent{Type: string(e.Type), Object: runtime.RawExtension{Object: objToPrint}} + } + if err := printer.PrintObj(objToPrint, writer); err != nil { + return false, err + } + writer.Flush() + // after processing at least one event, start outputting objects + *outputObjects = true + return false, nil + }) + return err + }) + return nil +} + +func (o *GetOptions) printGeneric(r *resource.Result) error { + // we flattened the data from the builder, so we have individual items, but now we'd like to either: + // 1. if there is more than one item, combine them all into a single list + // 2. if there is a single item and that item is a list, leave it as its specific list + // 3. if there is a single item and it is not a list, leave it as a single item + var errs []error + singleItemImplied := false + infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + if singleItemImplied { + return err + } + errs = append(errs, err) + } + + if len(infos) == 0 && o.IgnoreNotFound { + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) + } + + printer, err := o.ToPrinter(nil, nil, false, false) + if err != nil { + return err + } + + var obj runtime.Object + if !singleItemImplied || len(infos) != 1 { + // we have zero or multple items, so coerce all items into a list. + // we don't want an *unstructured.Unstructured list yet, as we + // may be dealing with non-unstructured objects. Compose all items + // into an corev1.List, and then decode using an unstructured scheme. + list := corev1.List{ + TypeMeta: metav1.TypeMeta{ + Kind: "List", + APIVersion: "v1", + }, + ListMeta: metav1.ListMeta{}, + } + for _, info := range infos { + list.Items = append(list.Items, runtime.RawExtension{Object: info.Object}) + } + + listData, err := json.Marshal(list) + if err != nil { + return err + } + + converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, listData) + if err != nil { + return err + } + + obj = converted + } else { + obj = infos[0].Object + } + + isList := meta.IsListType(obj) + if isList { + items, err := meta.ExtractList(obj) + if err != nil { + return err + } + + // take the items and create a new list for display + list := &unstructured.UnstructuredList{ + Object: map[string]interface{}{ + "kind": "List", + "apiVersion": "v1", + "metadata": map[string]interface{}{}, + }, + } + if listMeta, err := meta.ListAccessor(obj); err == nil { + list.Object["metadata"] = map[string]interface{}{ + "selfLink": listMeta.GetSelfLink(), + "resourceVersion": listMeta.GetResourceVersion(), + } + } + + for _, item := range items { + list.Items = append(list.Items, *item.(*unstructured.Unstructured)) + } + if err := printer.PrintObj(list, o.Out); err != nil { + errs = append(errs, err) + } + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) + } + + if printErr := printer.PrintObj(obj, o.Out); printErr != nil { + errs = append(errs, printErr) + } + + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) +} + +func addOpenAPIPrintColumnFlags(cmd *cobra.Command, opt *GetOptions) { + cmd.Flags().BoolVar(&opt.PrintWithOpenAPICols, useOpenAPIPrintColumnFlagLabel, opt.PrintWithOpenAPICols, "If true, use x-kubernetes-print-column metadata (if present) from the OpenAPI schema for displaying a resource.") + cmd.Flags().MarkDeprecated(useOpenAPIPrintColumnFlagLabel, "deprecated in favor of server-side printing") +} + +func addServerPrintColumnFlags(cmd *cobra.Command, opt *GetOptions) { + cmd.Flags().BoolVar(&opt.ServerPrint, useServerPrintColumns, opt.ServerPrint, "If true, have the server return the appropriate table output. Supports extension APIs and CRDs.") +} + +func shouldGetNewPrinterForMapping(printer printers.ResourcePrinter, lastMapping, mapping *meta.RESTMapping) bool { + return printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource +} + +func cmdSpecifiesOutputFmt(cmd *cobra.Command) bool { + return cmdutil.GetFlagString(cmd, "output") != "" +} + +func multipleGVKsRequested(infos []*resource.Info) bool { + if len(infos) < 2 { + return false + } + gvk := infos[0].Mapping.GroupVersionKind + for _, info := range infos { + if info.Mapping.GroupVersionKind != gvk { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/get_flags.go b/vendor/k8s.io/kubectl/pkg/cmd/get/get_flags.go new file mode 100644 index 000000000..9a53449b8 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/get_flags.go @@ -0,0 +1,187 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "strings" + + "github.com/spf13/cobra" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/kubectl/pkg/util/openapi" +) + +// PrintFlags composes common printer flag structs +// used in the Get command. +type PrintFlags struct { + JSONYamlPrintFlags *genericclioptions.JSONYamlPrintFlags + NamePrintFlags *genericclioptions.NamePrintFlags + CustomColumnsFlags *CustomColumnsPrintFlags + HumanReadableFlags *HumanPrintFlags + TemplateFlags *genericclioptions.KubeTemplatePrintFlags + + NoHeaders *bool + OutputFormat *string +} + +// SetKind sets the Kind option of humanreadable flags +func (f *PrintFlags) SetKind(kind schema.GroupKind) { + f.HumanReadableFlags.SetKind(kind) +} + +// EnsureWithNamespace ensures that humanreadable flags return +// a printer capable of printing with a "namespace" column. +func (f *PrintFlags) EnsureWithNamespace() error { + return f.HumanReadableFlags.EnsureWithNamespace() +} + +// EnsureWithKind ensures that humanreadable flags return +// a printer capable of including resource kinds. +func (f *PrintFlags) EnsureWithKind() error { + return f.HumanReadableFlags.EnsureWithKind() +} + +// Copy returns a copy of PrintFlags for mutation +func (f *PrintFlags) Copy() PrintFlags { + printFlags := *f + return printFlags +} + +// AllowedFormats is the list of formats in which data can be displayed +func (f *PrintFlags) AllowedFormats() []string { + formats := f.JSONYamlPrintFlags.AllowedFormats() + formats = append(formats, f.NamePrintFlags.AllowedFormats()...) + formats = append(formats, f.TemplateFlags.AllowedFormats()...) + formats = append(formats, f.CustomColumnsFlags.AllowedFormats()...) + formats = append(formats, f.HumanReadableFlags.AllowedFormats()...) + return formats +} + +// UseOpenAPIColumns modifies the output format, as well as the +// "allowMissingKeys" option for template printers, to values +// defined in the OpenAPI schema of a resource. +func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error { + // Found openapi metadata for this resource + schema := api.LookupResource(mapping.GroupVersionKind) + if schema == nil { + // Schema not found, return empty columns + return nil + } + + columns, found := openapi.GetPrintColumns(schema.GetExtensions()) + if !found { + // Extension not found, return empty columns + return nil + } + + parts := strings.SplitN(columns, "=", 2) + if len(parts) < 2 { + return nil + } + + allowMissingKeys := true + f.OutputFormat = &parts[0] + f.TemplateFlags.TemplateArgument = &parts[1] + f.TemplateFlags.AllowMissingKeys = &allowMissingKeys + return nil +} + +// ToPrinter attempts to find a composed set of PrintFlags suitable for +// returning a printer based on current flag values. +func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) { + outputFormat := "" + if f.OutputFormat != nil { + outputFormat = *f.OutputFormat + } + + noHeaders := false + if f.NoHeaders != nil { + noHeaders = *f.NoHeaders + } + f.HumanReadableFlags.NoHeaders = noHeaders + f.CustomColumnsFlags.NoHeaders = noHeaders + + // for "get.go" we want to support a --template argument given, even when no --output format is provided + if f.TemplateFlags.TemplateArgument != nil && len(*f.TemplateFlags.TemplateArgument) > 0 && len(outputFormat) == 0 { + outputFormat = "go-template" + } + + if p, err := f.TemplateFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if f.TemplateFlags.TemplateArgument != nil { + f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument + } + + if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !genericclioptions.IsNoCompatiblePrinterError(err) { + return p, err + } + + return nil, genericclioptions.NoCompatiblePrinterError{OutputFormat: &outputFormat, AllowedFormats: f.AllowedFormats()} +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to humanreadable and template printing. +func (f *PrintFlags) AddFlags(cmd *cobra.Command) { + f.JSONYamlPrintFlags.AddFlags(cmd) + f.NamePrintFlags.AddFlags(cmd) + f.TemplateFlags.AddFlags(cmd) + f.HumanReadableFlags.AddFlags(cmd) + f.CustomColumnsFlags.AddFlags(cmd) + + if f.OutputFormat != nil { + cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].") + } + if f.NoHeaders != nil { + cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).") + } +} + +// NewGetPrintFlags returns flags associated with humanreadable, +// template, and "name" printing, with default values set. +func NewGetPrintFlags() *PrintFlags { + outputFormat := "" + noHeaders := false + + return &PrintFlags{ + OutputFormat: &outputFormat, + NoHeaders: &noHeaders, + + JSONYamlPrintFlags: genericclioptions.NewJSONYamlPrintFlags(), + NamePrintFlags: genericclioptions.NewNamePrintFlags(""), + TemplateFlags: genericclioptions.NewKubeTemplatePrintFlags(), + + HumanReadableFlags: NewHumanPrintFlags(), + CustomColumnsFlags: NewCustomColumnsPrintFlags(), + } +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/humanreadable_flags.go b/vendor/k8s.io/kubectl/pkg/cmd/get/humanreadable_flags.go new file mode 100644 index 000000000..5fcf34d8c --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/humanreadable_flags.go @@ -0,0 +1,138 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericclioptions" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/cli-runtime/pkg/printers" +) + +// HumanPrintFlags provides default flags necessary for printing. +// Given the following flag values, a printer can be requested that knows +// how to handle printing based on these values. +type HumanPrintFlags struct { + ShowKind *bool + ShowLabels *bool + SortBy *string + ColumnLabels *[]string + + // get.go-specific values + NoHeaders bool + + Kind schema.GroupKind + WithNamespace bool +} + +// SetKind sets the Kind option +func (f *HumanPrintFlags) SetKind(kind schema.GroupKind) { + f.Kind = kind +} + +// EnsureWithKind sets the "Showkind" humanreadable option to true. +func (f *HumanPrintFlags) EnsureWithKind() error { + showKind := true + f.ShowKind = &showKind + return nil +} + +// EnsureWithNamespace sets the "WithNamespace" humanreadable option to true. +func (f *HumanPrintFlags) EnsureWithNamespace() error { + f.WithNamespace = true + return nil +} + +// AllowedFormats returns more customized formating options +func (f *HumanPrintFlags) AllowedFormats() []string { + return []string{"wide"} +} + +// ToPrinter receives an outputFormat and returns a printer capable of +// handling human-readable output. +func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) { + if len(outputFormat) > 0 && outputFormat != "wide" { + return nil, genericclioptions.NoCompatiblePrinterError{Options: f, AllowedFormats: f.AllowedFormats()} + } + + showKind := false + if f.ShowKind != nil { + showKind = *f.ShowKind + } + + showLabels := false + if f.ShowLabels != nil { + showLabels = *f.ShowLabels + } + + columnLabels := []string{} + if f.ColumnLabels != nil { + columnLabels = *f.ColumnLabels + } + + p := printers.NewTablePrinter(printers.PrintOptions{ + Kind: f.Kind, + WithKind: showKind, + NoHeaders: f.NoHeaders, + Wide: outputFormat == "wide", + WithNamespace: f.WithNamespace, + ColumnLabels: columnLabels, + ShowLabels: showLabels, + }) + + // TODO(juanvallejo): handle sorting here + + return p, nil +} + +// AddFlags receives a *cobra.Command reference and binds +// flags related to human-readable printing to it +func (f *HumanPrintFlags) AddFlags(c *cobra.Command) { + if f.ShowLabels != nil { + c.Flags().BoolVar(f.ShowLabels, "show-labels", *f.ShowLabels, "When printing, show all labels as the last column (default hide labels column)") + } + if f.SortBy != nil { + c.Flags().StringVar(f.SortBy, "sort-by", *f.SortBy, "If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.") + } + if f.ColumnLabels != nil { + c.Flags().StringSliceVarP(f.ColumnLabels, "label-columns", "L", *f.ColumnLabels, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2...") + } + if f.ShowKind != nil { + c.Flags().BoolVar(f.ShowKind, "show-kind", *f.ShowKind, "If present, list the resource type for the requested object(s).") + } +} + +// NewHumanPrintFlags returns flags associated with +// human-readable printing, with default values set. +func NewHumanPrintFlags() *HumanPrintFlags { + showLabels := false + sortBy := "" + showKind := false + columnLabels := []string{} + + return &HumanPrintFlags{ + NoHeaders: false, + WithNamespace: false, + ColumnLabels: &columnLabels, + + Kind: schema.GroupKind{}, + ShowLabels: &showLabels, + SortBy: &sortBy, + ShowKind: &showKind, + } +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/skip_printer.go b/vendor/k8s.io/kubectl/pkg/cmd/get/skip_printer.go new file mode 100644 index 000000000..f02883cb1 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/skip_printer.go @@ -0,0 +1,48 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "io" + + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" +) + +// skipPrinter allows conditionally suppressing object output via the output field. +// table objects are suppressed by setting their Rows to nil (allowing column definitions to propagate to the delegate). +// non-table objects are suppressed by not calling the delegate at all. +type skipPrinter struct { + delegate printers.ResourcePrinter + output *bool +} + +func (p *skipPrinter) PrintObj(obj runtime.Object, writer io.Writer) error { + if *p.output { + return p.delegate.PrintObj(obj, writer) + } + + table, isTable := obj.(*metav1beta1.Table) + if !isTable { + return nil + } + + table = table.DeepCopy() + table.Rows = nil + return p.delegate.PrintObj(table, writer) +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/sorter.go b/vendor/k8s.io/kubectl/pkg/cmd/get/sorter.go new file mode 100644 index 000000000..599b4acd1 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/sorter.go @@ -0,0 +1,400 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "fmt" + "io" + "reflect" + "sort" + + "k8s.io/klog" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/client-go/util/jsonpath" + "k8s.io/utils/integer" + + "vbom.ml/util/sortorder" +) + +// SortingPrinter sorts list types before delegating to another printer. +// Non-list types are simply passed through +type SortingPrinter struct { + SortField string + Delegate printers.ResourcePrinter + Decoder runtime.Decoder +} + +func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error { + if table, isTable := obj.(*metav1beta1.Table); isTable && len(table.Rows) > 1 { + parsedField, err := RelaxedJSONPathExpression(s.SortField) + if err != nil { + parsedField = s.SortField + } + + if sorter, err := NewTableSorter(table, parsedField); err != nil { + return err + } else if err := sorter.Sort(); err != nil { + return err + } + return s.Delegate.PrintObj(table, out) + } + + if meta.IsListType(obj) { + if err := s.sortObj(obj); err != nil { + return err + } + return s.Delegate.PrintObj(obj, out) + } + + return s.Delegate.PrintObj(obj, out) +} + +func (s *SortingPrinter) sortObj(obj runtime.Object) error { + objs, err := meta.ExtractList(obj) + if err != nil { + return err + } + if len(objs) == 0 { + return nil + } + + sorter, err := SortObjects(s.Decoder, objs, s.SortField) + if err != nil { + return err + } + + switch list := obj.(type) { + case *corev1.List: + outputList := make([]runtime.RawExtension, len(objs)) + for ix := range objs { + outputList[ix] = list.Items[sorter.OriginalPosition(ix)] + } + list.Items = outputList + return nil + } + return meta.SetList(obj, objs) +} + +func SortObjects(decoder runtime.Decoder, objs []runtime.Object, fieldInput string) (*RuntimeSort, error) { + for ix := range objs { + item := objs[ix] + switch u := item.(type) { + case *runtime.Unknown: + var err error + // decode runtime.Unknown to runtime.Unstructured for sorting. + // we don't actually want the internal versions of known types. + if objs[ix], _, err = decoder.Decode(u.Raw, nil, &unstructured.Unstructured{}); err != nil { + return nil, err + } + } + } + + field, err := RelaxedJSONPathExpression(fieldInput) + if err != nil { + return nil, err + } + + parser := jsonpath.New("sorting").AllowMissingKeys(true) + if err := parser.Parse(field); err != nil { + return nil, err + } + + // We don't do any model validation here, so we traverse all objects to be sorted + // and, if the field is valid to at least one of them, we consider it to be a + // valid field; otherwise error out. + // Note that this requires empty fields to be considered later, when sorting. + var fieldFoundOnce bool + for _, obj := range objs { + values, err := findJSONPathResults(parser, obj) + if err != nil { + return nil, err + } + if len(values) > 0 && len(values[0]) > 0 { + fieldFoundOnce = true + break + } + } + if !fieldFoundOnce { + return nil, fmt.Errorf("couldn't find any field with path %q in the list of objects", field) + } + + sorter := NewRuntimeSort(field, objs) + sort.Sort(sorter) + return sorter, nil +} + +// RuntimeSort is an implementation of the golang sort interface that knows how to sort +// lists of runtime.Object +type RuntimeSort struct { + field string + objs []runtime.Object + origPosition []int +} + +func NewRuntimeSort(field string, objs []runtime.Object) *RuntimeSort { + sorter := &RuntimeSort{field: field, objs: objs, origPosition: make([]int, len(objs))} + for ix := range objs { + sorter.origPosition[ix] = ix + } + return sorter +} + +func (r *RuntimeSort) Len() int { + return len(r.objs) +} + +func (r *RuntimeSort) Swap(i, j int) { + r.objs[i], r.objs[j] = r.objs[j], r.objs[i] + r.origPosition[i], r.origPosition[j] = r.origPosition[j], r.origPosition[i] +} + +func isLess(i, j reflect.Value) (bool, error) { + switch i.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return i.Int() < j.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return i.Uint() < j.Uint(), nil + case reflect.Float32, reflect.Float64: + return i.Float() < j.Float(), nil + case reflect.String: + return sortorder.NaturalLess(i.String(), j.String()), nil + case reflect.Ptr: + return isLess(i.Elem(), j.Elem()) + case reflect.Struct: + // sort metav1.Time + in := i.Interface() + if t, ok := in.(metav1.Time); ok { + time := j.Interface().(metav1.Time) + return t.Before(&time), nil + } + // fallback to the fields comparison + for idx := 0; idx < i.NumField(); idx++ { + less, err := isLess(i.Field(idx), j.Field(idx)) + if err != nil || !less { + return less, err + } + } + return true, nil + case reflect.Array, reflect.Slice: + // note: the length of i and j may be different + for idx := 0; idx < integer.IntMin(i.Len(), j.Len()); idx++ { + less, err := isLess(i.Index(idx), j.Index(idx)) + if err != nil || !less { + return less, err + } + } + return true, nil + + case reflect.Interface: + switch itype := i.Interface().(type) { + case uint8: + if jtype, ok := j.Interface().(uint8); ok { + return itype < jtype, nil + } + case uint16: + if jtype, ok := j.Interface().(uint16); ok { + return itype < jtype, nil + } + case uint32: + if jtype, ok := j.Interface().(uint32); ok { + return itype < jtype, nil + } + case uint64: + if jtype, ok := j.Interface().(uint64); ok { + return itype < jtype, nil + } + case int8: + if jtype, ok := j.Interface().(int8); ok { + return itype < jtype, nil + } + case int16: + if jtype, ok := j.Interface().(int16); ok { + return itype < jtype, nil + } + case int32: + if jtype, ok := j.Interface().(int32); ok { + return itype < jtype, nil + } + case int64: + if jtype, ok := j.Interface().(int64); ok { + return itype < jtype, nil + } + case uint: + if jtype, ok := j.Interface().(uint); ok { + return itype < jtype, nil + } + case int: + if jtype, ok := j.Interface().(int); ok { + return itype < jtype, nil + } + case float32: + if jtype, ok := j.Interface().(float32); ok { + return itype < jtype, nil + } + case float64: + if jtype, ok := j.Interface().(float64); ok { + return itype < jtype, nil + } + case string: + if jtype, ok := j.Interface().(string); ok { + return sortorder.NaturalLess(itype, jtype), nil + } + default: + return false, fmt.Errorf("unsortable type: %T", itype) + } + return false, fmt.Errorf("unsortable interface: %v", i.Kind()) + + default: + return false, fmt.Errorf("unsortable type: %v", i.Kind()) + } +} + +func (r *RuntimeSort) Less(i, j int) bool { + iObj := r.objs[i] + jObj := r.objs[j] + + var iValues [][]reflect.Value + var jValues [][]reflect.Value + var err error + + parser := jsonpath.New("sorting").AllowMissingKeys(true) + err = parser.Parse(r.field) + if err != nil { + panic(err) + } + + iValues, err = findJSONPathResults(parser, iObj) + if err != nil { + klog.Fatalf("Failed to get i values for %#v using %s (%#v)", iObj, r.field, err) + } + + jValues, err = findJSONPathResults(parser, jObj) + if err != nil { + klog.Fatalf("Failed to get j values for %#v using %s (%v)", jObj, r.field, err) + } + + if len(iValues) == 0 || len(iValues[0]) == 0 { + return true + } + if len(jValues) == 0 || len(jValues[0]) == 0 { + return false + } + iField := iValues[0][0] + jField := jValues[0][0] + + less, err := isLess(iField, jField) + if err != nil { + klog.Fatalf("Field %s in %T is an unsortable type: %s, err: %v", r.field, iObj, iField.Kind().String(), err) + } + return less +} + +// OriginalPosition returns the starting (original) position of a particular index. +// e.g. If OriginalPosition(0) returns 5 than the +// the item currently at position 0 was at position 5 in the original unsorted array. +func (r *RuntimeSort) OriginalPosition(ix int) int { + if ix < 0 || ix > len(r.origPosition) { + return -1 + } + return r.origPosition[ix] +} + +type TableSorter struct { + field string + obj *metav1beta1.Table + parsedRows [][][]reflect.Value +} + +func (t *TableSorter) Len() int { + return len(t.obj.Rows) +} + +func (t *TableSorter) Swap(i, j int) { + t.obj.Rows[i], t.obj.Rows[j] = t.obj.Rows[j], t.obj.Rows[i] + t.parsedRows[i], t.parsedRows[j] = t.parsedRows[j], t.parsedRows[i] +} + +func (t *TableSorter) Less(i, j int) bool { + iValues := t.parsedRows[i] + jValues := t.parsedRows[j] + + if len(iValues) == 0 || len(iValues[0]) == 0 { + return true + } + if len(jValues) == 0 || len(jValues[0]) == 0 { + return false + } + + iField := iValues[0][0] + jField := jValues[0][0] + + less, err := isLess(iField, jField) + if err != nil { + klog.Fatalf("Field %s in %T is an unsortable type: %s, err: %v", t.field, t.parsedRows, iField.Kind().String(), err) + } + return less +} + +func (t *TableSorter) Sort() error { + sort.Sort(t) + return nil +} + +func NewTableSorter(table *metav1beta1.Table, field string) (*TableSorter, error) { + var parsedRows [][][]reflect.Value + + parser := jsonpath.New("sorting").AllowMissingKeys(true) + err := parser.Parse(field) + if err != nil { + return nil, fmt.Errorf("sorting error: %v", err) + } + + fieldFoundOnce := false + for i := range table.Rows { + parsedRow, err := findJSONPathResults(parser, table.Rows[i].Object.Object) + if err != nil { + return nil, fmt.Errorf("Failed to get values for %#v using %s (%#v)", parsedRow, field, err) + } + parsedRows = append(parsedRows, parsedRow) + if len(parsedRow) > 0 && len(parsedRow[0]) > 0 { + fieldFoundOnce = true + } + } + + if len(table.Rows) > 0 && !fieldFoundOnce { + return nil, fmt.Errorf("couldn't find any field with path %q in the list of objects", field) + } + + return &TableSorter{ + obj: table, + field: field, + parsedRows: parsedRows, + }, nil +} +func findJSONPathResults(parser *jsonpath.JSONPath, from runtime.Object) ([][]reflect.Value, error) { + if unstructuredObj, ok := from.(*unstructured.Unstructured); ok { + return parser.FindResults(unstructuredObj.Object) + } + return parser.FindResults(reflect.ValueOf(from).Elem().Interface()) +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/get/table_printer.go b/vendor/k8s.io/kubectl/pkg/cmd/get/table_printer.go new file mode 100644 index 000000000..1534c3d7f --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/get/table_printer.go @@ -0,0 +1,87 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package get + +import ( + "fmt" + "io" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/printers" + "k8s.io/klog" +) + +// TablePrinter decodes table objects into typed objects before delegating to another printer. +// Non-table types are simply passed through +type TablePrinter struct { + Delegate printers.ResourcePrinter +} + +func (t *TablePrinter) PrintObj(obj runtime.Object, writer io.Writer) error { + table, err := decodeIntoTable(obj) + if err == nil { + return t.Delegate.PrintObj(table, writer) + } + // if we are unable to decode server response into a v1beta1.Table, + // fallback to client-side printing with whatever info the server returned. + klog.V(2).Infof("Unable to decode server response into a Table. Falling back to hardcoded types: %v", err) + return t.Delegate.PrintObj(obj, writer) +} + +func decodeIntoTable(obj runtime.Object) (runtime.Object, error) { + event, isEvent := obj.(*metav1.WatchEvent) + if isEvent { + obj = event.Object.Object + } + + if obj.GetObjectKind().GroupVersionKind().Group != metav1beta1.GroupName { + return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") + } + if obj.GetObjectKind().GroupVersionKind().Kind != "Table" { + return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") + } + + unstr, ok := obj.(*unstructured.Unstructured) + if !ok { + return nil, fmt.Errorf("attempt to decode non-Unstructured object") + } + table := &metav1beta1.Table{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, table); err != nil { + return nil, err + } + + for i := range table.Rows { + row := &table.Rows[i] + if row.Object.Raw == nil || row.Object.Object != nil { + continue + } + converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, row.Object.Raw) + if err != nil { + return nil, err + } + row.Object.Object = converted + } + + if isEvent { + event.Object.Object = table + return event, nil + } + return table, nil +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/crdfinder.go b/vendor/k8s.io/kubectl/pkg/cmd/util/crdfinder.go new file mode 100644 index 000000000..aaf309dca --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/crdfinder.go @@ -0,0 +1,109 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + "reflect" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" +) + +// CRDGetter is a function that can download the list of GVK for all +// CRDs. +type CRDGetter func() ([]schema.GroupKind, error) + +func CRDFromDynamic(client dynamic.Interface) CRDGetter { + return func() ([]schema.GroupKind, error) { + list, err := client.Resource(schema.GroupVersionResource{ + Group: "apiextensions.k8s.io", + Version: "v1beta1", + Resource: "customresourcedefinitions", + }).List(metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to list CRDs: %v", err) + } + if list == nil { + return nil, nil + } + + gks := []schema.GroupKind{} + + // We need to parse the list to get the gvk, I guess that's fine. + for _, crd := range (*list).Items { + // Look for group, version, and kind + group, _, _ := unstructured.NestedString(crd.Object, "spec", "group") + kind, _, _ := unstructured.NestedString(crd.Object, "spec", "names", "kind") + + gks = append(gks, schema.GroupKind{ + Group: group, + Kind: kind, + }) + } + + return gks, nil + } +} + +// CRDFinder keeps a cache of known CRDs and finds a given GVK in the +// list. +type CRDFinder interface { + HasCRD(gvk schema.GroupKind) (bool, error) +} + +func NewCRDFinder(getter CRDGetter) CRDFinder { + return &crdFinder{ + getter: getter, + } +} + +type crdFinder struct { + getter CRDGetter + cache *[]schema.GroupKind +} + +func (f *crdFinder) cacheCRDs() error { + if f.cache != nil { + return nil + } + + list, err := f.getter() + if err != nil { + return err + } + f.cache = &list + return nil +} + +func (f *crdFinder) findCRD(gvk schema.GroupKind) bool { + for _, crd := range *f.cache { + if reflect.DeepEqual(gvk, crd) { + return true + } + } + return false +} + +func (f *crdFinder) HasCRD(gvk schema.GroupKind) (bool, error) { + if err := f.cacheCRDs(); err != nil { + return false, err + } + return f.findCRD(gvk), nil +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/factory.go b/vendor/k8s.io/kubectl/pkg/cmd/util/factory.go new file mode 100644 index 000000000..d9df0bf3b --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/factory.go @@ -0,0 +1,66 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/kubectl/pkg/util/openapi" + "k8s.io/kubectl/pkg/validation" +) + +// Factory provides abstractions that allow the Kubectl command to be extended across multiple types +// of resources and different API sets. +// The rings are here for a reason. In order for composers to be able to provide alternative factory implementations +// they need to provide low level pieces of *certain* functions so that when the factory calls back into itself +// it uses the custom version of the function. Rather than try to enumerate everything that someone would want to override +// we split the factory into rings, where each ring can depend on methods in an earlier ring, but cannot depend +// upon peer methods in its own ring. +// TODO: make the functions interfaces +// TODO: pass the various interfaces on the factory directly into the command constructors (so the +// commands are decoupled from the factory). +type Factory interface { + genericclioptions.RESTClientGetter + + // DynamicClient returns a dynamic client ready for use + DynamicClient() (dynamic.Interface, error) + + // KubernetesClientSet gives you back an external clientset + KubernetesClientSet() (*kubernetes.Clientset, error) + + // Returns a RESTClient for accessing Kubernetes resources or an error. + RESTClient() (*restclient.RESTClient, error) + + // NewBuilder returns an object that assists in loading objects from both disk and the server + // and which implements the common patterns for CLI interactions with generic resources. + NewBuilder() *resource.Builder + + // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended + // for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer. + ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) + // Returns a RESTClient for working with Unstructured objects. + UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) + + // Returns a schema that can validate objects stored on disk. + Validator(validate bool) (validation.Schema, error) + // OpenAPISchema returns the schema openapi schema definition + OpenAPISchema() (openapi.Resources, error) +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/factory_client_access.go b/vendor/k8s.io/kubectl/pkg/cmd/util/factory_client_access.go new file mode 100644 index 000000000..e4cf2da07 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/factory_client_access.go @@ -0,0 +1,177 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// this file contains factories with no other dependencies + +package util + +import ( + "sync" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/kubectl/pkg/util/openapi" + openapivalidation "k8s.io/kubectl/pkg/util/openapi/validation" + "k8s.io/kubectl/pkg/validation" +) + +type factoryImpl struct { + clientGetter genericclioptions.RESTClientGetter + + // openAPIGetter loads and caches openapi specs + openAPIGetter openAPIGetter +} + +type openAPIGetter struct { + once sync.Once + getter openapi.Getter +} + +func NewFactory(clientGetter genericclioptions.RESTClientGetter) Factory { + if clientGetter == nil { + panic("attempt to instantiate client_access_factory with nil clientGetter") + } + + f := &factoryImpl{ + clientGetter: clientGetter, + } + + return f +} + +func (f *factoryImpl) ToRESTConfig() (*restclient.Config, error) { + return f.clientGetter.ToRESTConfig() +} + +func (f *factoryImpl) ToRESTMapper() (meta.RESTMapper, error) { + return f.clientGetter.ToRESTMapper() +} + +func (f *factoryImpl) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + return f.clientGetter.ToDiscoveryClient() +} + +func (f *factoryImpl) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return f.clientGetter.ToRawKubeConfigLoader() +} + +func (f *factoryImpl) KubernetesClientSet() (*kubernetes.Clientset, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + return kubernetes.NewForConfig(clientConfig) +} + +func (f *factoryImpl) DynamicClient() (dynamic.Interface, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + return dynamic.NewForConfig(clientConfig) +} + +// NewBuilder returns a new resource builder for structured api objects. +func (f *factoryImpl) NewBuilder() *resource.Builder { + return resource.NewBuilder(f.clientGetter) +} + +func (f *factoryImpl) RESTClient() (*restclient.RESTClient, error) { + clientConfig, err := f.ToRESTConfig() + if err != nil { + return nil, err + } + setKubernetesDefaults(clientConfig) + return restclient.RESTClientFor(clientConfig) +} + +func (f *factoryImpl) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { + cfg, err := f.clientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + if err := setKubernetesDefaults(cfg); err != nil { + return nil, err + } + gvk := mapping.GroupVersionKind + switch gvk.Group { + case corev1.GroupName: + cfg.APIPath = "/api" + default: + cfg.APIPath = "/apis" + } + gv := gvk.GroupVersion() + cfg.GroupVersion = &gv + return restclient.RESTClientFor(cfg) +} + +func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { + cfg, err := f.clientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + if err := restclient.SetKubernetesDefaults(cfg); err != nil { + return nil, err + } + cfg.APIPath = "/apis" + if mapping.GroupVersionKind.Group == corev1.GroupName { + cfg.APIPath = "/api" + } + gv := mapping.GroupVersionKind.GroupVersion() + cfg.ContentConfig = resource.UnstructuredPlusDefaultContentConfig() + cfg.GroupVersion = &gv + return restclient.RESTClientFor(cfg) +} + +func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) { + if !validate { + return validation.NullSchema{}, nil + } + + resources, err := f.OpenAPISchema() + if err != nil { + return nil, err + } + + return validation.ConjunctiveSchema{ + openapivalidation.NewSchemaValidation(resources), + validation.NoDoubleKeySchema{}, + }, nil +} + +// OpenAPISchema returns metadata and structural information about Kubernetes object definitions. +func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) { + discovery, err := f.clientGetter.ToDiscoveryClient() + if err != nil { + return nil, err + } + + // Lazily initialize the OpenAPIGetter once + f.openAPIGetter.once.Do(func() { + // Create the caching OpenAPIGetter + f.openAPIGetter.getter = openapi.NewOpenAPIGetter(discovery) + }) + + // Delegate to the OpenAPIGetter + return f.openAPIGetter.getter.Get() +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go b/vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go new file mode 100644 index 000000000..5d1b76f06 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/helpers.go @@ -0,0 +1,661 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "bytes" + "errors" + "fmt" + "io" + "net/url" + "os" + "strings" + "time" + + jsonpatch "github.com/evanphx/json-patch" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + "k8s.io/client-go/scale" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog" + utilexec "k8s.io/utils/exec" +) + +const ( + ApplyAnnotationsFlag = "save-config" + DefaultErrorExitCode = 1 +) + +type debugError interface { + DebugError() (msg string, args []interface{}) +} + +// AddSourceToErr adds handleResourcePrefix and source string to error message. +// verb is the string like "creating", "deleting" etc. +// source is the filename or URL to the template file(*.json or *.yaml), or stdin to use to handle the resource. +func AddSourceToErr(verb string, source string, err error) error { + if source != "" { + if statusError, ok := err.(kerrors.APIStatus); ok { + status := statusError.Status() + status.Message = fmt.Sprintf("error when %s %q: %v", verb, source, status.Message) + return &kerrors.StatusError{ErrStatus: status} + } + return fmt.Errorf("error when %s %q: %v", verb, source, err) + } + return err +} + +var fatalErrHandler = fatal + +// BehaviorOnFatal allows you to override the default behavior when a fatal +// error occurs, which is to call os.Exit(code). You can pass 'panic' as a function +// here if you prefer the panic() over os.Exit(1). +func BehaviorOnFatal(f func(string, int)) { + fatalErrHandler = f +} + +// DefaultBehaviorOnFatal allows you to undo any previous override. Useful in +// tests. +func DefaultBehaviorOnFatal() { + fatalErrHandler = fatal +} + +// fatal prints the message (if provided) and then exits. If V(2) or greater, +// klog.Fatal is invoked for extended information. +func fatal(msg string, code int) { + if klog.V(2) { + klog.FatalDepth(2, msg) + } + if len(msg) > 0 { + // add newline if needed + if !strings.HasSuffix(msg, "\n") { + msg += "\n" + } + fmt.Fprint(os.Stderr, msg) + } + os.Exit(code) +} + +// ErrExit may be passed to CheckError to instruct it to output nothing but exit with +// status code 1. +var ErrExit = fmt.Errorf("exit") + +// CheckErr prints a user friendly error to STDERR and exits with a non-zero +// exit code. Unrecognized errors will be printed with an "error: " prefix. +// +// This method is generic to the command in use and may be used by non-Kubectl +// commands. +func CheckErr(err error) { + checkErr(err, fatalErrHandler) +} + +// checkErr formats a given error as a string and calls the passed handleErr +// func with that string and an kubectl exit code. +func checkErr(err error, handleErr func(string, int)) { + // unwrap aggregates of 1 + if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) == 1 { + err = agg.Errors()[0] + } + + if err == nil { + return + } + + switch { + case err == ErrExit: + handleErr("", DefaultErrorExitCode) + case kerrors.IsInvalid(err): + details := err.(*kerrors.StatusError).Status().Details + s := "The request is invalid" + if details == nil { + handleErr(s, DefaultErrorExitCode) + return + } + if len(details.Kind) != 0 || len(details.Name) != 0 { + s = fmt.Sprintf("The %s %q is invalid", details.Kind, details.Name) + } + if len(details.Causes) > 0 { + errs := statusCausesToAggrError(details.Causes) + handleErr(MultilineError(s+": ", errs), DefaultErrorExitCode) + } else { + handleErr(s, DefaultErrorExitCode) + } + case clientcmd.IsConfigurationInvalid(err): + handleErr(MultilineError("Error in configuration: ", err), DefaultErrorExitCode) + default: + switch err := err.(type) { + case *meta.NoResourceMatchError: + switch { + case len(err.PartialResource.Group) > 0 && len(err.PartialResource.Version) > 0: + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q and version %q", err.PartialResource.Resource, err.PartialResource.Group, err.PartialResource.Version), DefaultErrorExitCode) + case len(err.PartialResource.Group) > 0: + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q", err.PartialResource.Resource, err.PartialResource.Group), DefaultErrorExitCode) + case len(err.PartialResource.Version) > 0: + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in version %q", err.PartialResource.Resource, err.PartialResource.Version), DefaultErrorExitCode) + default: + handleErr(fmt.Sprintf("the server doesn't have a resource type %q", err.PartialResource.Resource), DefaultErrorExitCode) + } + case utilerrors.Aggregate: + handleErr(MultipleErrors(``, err.Errors()), DefaultErrorExitCode) + case utilexec.ExitError: + handleErr(err.Error(), err.ExitStatus()) + default: // for any other error type + msg, ok := StandardErrorMessage(err) + if !ok { + msg = err.Error() + if !strings.HasPrefix(msg, "error: ") { + msg = fmt.Sprintf("error: %s", msg) + } + } + handleErr(msg, DefaultErrorExitCode) + } + } +} + +func statusCausesToAggrError(scs []metav1.StatusCause) utilerrors.Aggregate { + errs := make([]error, 0, len(scs)) + errorMsgs := sets.NewString() + for _, sc := range scs { + // check for duplicate error messages and skip them + msg := fmt.Sprintf("%s: %s", sc.Field, sc.Message) + if errorMsgs.Has(msg) { + continue + } + errorMsgs.Insert(msg) + errs = append(errs, errors.New(msg)) + } + return utilerrors.NewAggregate(errs) +} + +// StandardErrorMessage translates common errors into a human readable message, or returns +// false if the error is not one of the recognized types. It may also log extended +// information to klog. +// +// This method is generic to the command in use and may be used by non-Kubectl +// commands. +func StandardErrorMessage(err error) (string, bool) { + if debugErr, ok := err.(debugError); ok { + klog.V(4).Infof(debugErr.DebugError()) + } + status, isStatus := err.(kerrors.APIStatus) + switch { + case isStatus: + switch s := status.Status(); { + case s.Reason == metav1.StatusReasonUnauthorized: + return fmt.Sprintf("error: You must be logged in to the server (%s)", s.Message), true + case len(s.Reason) > 0: + return fmt.Sprintf("Error from server (%s): %s", s.Reason, err.Error()), true + default: + return fmt.Sprintf("Error from server: %s", err.Error()), true + } + case kerrors.IsUnexpectedObjectError(err): + return fmt.Sprintf("Server returned an unexpected response: %s", err.Error()), true + } + switch t := err.(type) { + case *url.Error: + klog.V(4).Infof("Connection error: %s %s: %v", t.Op, t.URL, t.Err) + switch { + case strings.Contains(t.Err.Error(), "connection refused"): + host := t.URL + if server, err := url.Parse(t.URL); err == nil { + host = server.Host + } + return fmt.Sprintf("The connection to the server %s was refused - did you specify the right host or port?", host), true + } + return fmt.Sprintf("Unable to connect to the server: %v", t.Err), true + } + return "", false +} + +// MultilineError returns a string representing an error that splits sub errors into their own +// lines. The returned string will end with a newline. +func MultilineError(prefix string, err error) string { + if agg, ok := err.(utilerrors.Aggregate); ok { + errs := utilerrors.Flatten(agg).Errors() + buf := &bytes.Buffer{} + switch len(errs) { + case 0: + return fmt.Sprintf("%s%v\n", prefix, err) + case 1: + return fmt.Sprintf("%s%v\n", prefix, messageForError(errs[0])) + default: + fmt.Fprintln(buf, prefix) + for _, err := range errs { + fmt.Fprintf(buf, "* %v\n", messageForError(err)) + } + return buf.String() + } + } + return fmt.Sprintf("%s%s\n", prefix, err) +} + +// PrintErrorWithCauses prints an error's kind, name, and each of the error's causes in a new line. +// The returned string will end with a newline. +// Returns true if a case exists to handle the error type, or false otherwise. +func PrintErrorWithCauses(err error, errOut io.Writer) bool { + switch t := err.(type) { + case *kerrors.StatusError: + errorDetails := t.Status().Details + if errorDetails != nil { + fmt.Fprintf(errOut, "error: %s %q is invalid\n\n", errorDetails.Kind, errorDetails.Name) + for _, cause := range errorDetails.Causes { + fmt.Fprintf(errOut, "* %s: %s\n", cause.Field, cause.Message) + } + return true + } + } + + fmt.Fprintf(errOut, "error: %v\n", err) + return false +} + +// MultipleErrors returns a newline delimited string containing +// the prefix and referenced errors in standard form. +func MultipleErrors(prefix string, errs []error) string { + buf := &bytes.Buffer{} + for _, err := range errs { + fmt.Fprintf(buf, "%s%v\n", prefix, messageForError(err)) + } + return buf.String() +} + +// messageForError returns the string representing the error. +func messageForError(err error) string { + msg, ok := StandardErrorMessage(err) + if !ok { + msg = err.Error() + } + return msg +} + +func UsageErrorf(cmd *cobra.Command, format string, args ...interface{}) error { + msg := fmt.Sprintf(format, args...) + return fmt.Errorf("%s\nSee '%s -h' for help and examples", msg, cmd.CommandPath()) +} + +func IsFilenameSliceEmpty(filenames []string, directory string) bool { + return len(filenames) == 0 && directory == "" +} + +func GetFlagString(cmd *cobra.Command, flag string) string { + s, err := cmd.Flags().GetString(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return s +} + +// GetFlagStringSlice can be used to accept multiple argument with flag repetition (e.g. -f arg1,arg2 -f arg3 ...) +func GetFlagStringSlice(cmd *cobra.Command, flag string) []string { + s, err := cmd.Flags().GetStringSlice(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return s +} + +// GetFlagStringArray can be used to accept multiple argument with flag repetition (e.g. -f arg1 -f arg2 ...) +func GetFlagStringArray(cmd *cobra.Command, flag string) []string { + s, err := cmd.Flags().GetStringArray(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return s +} + +func GetFlagBool(cmd *cobra.Command, flag string) bool { + b, err := cmd.Flags().GetBool(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return b +} + +// Assumes the flag has a default value. +func GetFlagInt(cmd *cobra.Command, flag string) int { + i, err := cmd.Flags().GetInt(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return i +} + +// Assumes the flag has a default value. +func GetFlagInt32(cmd *cobra.Command, flag string) int32 { + i, err := cmd.Flags().GetInt32(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return i +} + +// Assumes the flag has a default value. +func GetFlagInt64(cmd *cobra.Command, flag string) int64 { + i, err := cmd.Flags().GetInt64(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return i +} + +func GetFlagDuration(cmd *cobra.Command, flag string) time.Duration { + d, err := cmd.Flags().GetDuration(flag) + if err != nil { + klog.Fatalf("error accessing flag %s for command %s: %v", flag, cmd.Name(), err) + } + return d +} + +func GetPodRunningTimeoutFlag(cmd *cobra.Command) (time.Duration, error) { + timeout := GetFlagDuration(cmd, "pod-running-timeout") + if timeout <= 0 { + return timeout, fmt.Errorf("--pod-running-timeout must be higher than zero") + } + return timeout, nil +} + +func AddValidateFlags(cmd *cobra.Command) { + cmd.Flags().Bool("validate", true, "If true, use a schema to validate the input before sending it") +} + +func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) { + cmd.Flags().BoolVar(&options.EnableValidation, "validate", options.EnableValidation, "If true, use a schema to validate the input before sending it") +} + +func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) { + AddJsonFilenameFlag(cmd.Flags(), &options.Filenames, "Filename, directory, or URL to files "+usage) + AddKustomizeFlag(cmd.Flags(), &options.Kustomize) + cmd.Flags().BoolVarP(&options.Recursive, "recursive", "R", options.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") +} + +func AddJsonFilenameFlag(flags *pflag.FlagSet, value *[]string, usage string) { + flags.StringSliceVarP(value, "filename", "f", *value, usage) + annotations := make([]string, 0, len(resource.FileExtensions)) + for _, ext := range resource.FileExtensions { + annotations = append(annotations, strings.TrimLeft(ext, ".")) + } + flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations) +} + +// AddKustomizeFlag adds kustomize flag to a command +func AddKustomizeFlag(flags *pflag.FlagSet, value *string) { + flags.StringVarP(value, "kustomize", "k", *value, "Process the kustomization directory. This flag can't be used together with -f or -R.") +} + +// AddDryRunFlag adds dry-run flag to a command. Usually used by mutations. +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 AddServerSideApplyFlags(cmd *cobra.Command) { + cmd.Flags().Bool("server-side", false, "If true, apply runs in the server instead of the client.") + cmd.Flags().Bool("force-conflicts", false, "If true, server-side apply will force the changes against conflicts.") + cmd.Flags().String("field-manager", "kubectl", "Name of the manager used to track field ownership.") +} + +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") +} + +func AddApplyAnnotationFlags(cmd *cobra.Command) { + cmd.Flags().Bool(ApplyAnnotationsFlag, false, "If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.") +} + +func AddApplyAnnotationVarFlags(cmd *cobra.Command, applyAnnotation *bool) { + cmd.Flags().BoolVar(applyAnnotation, ApplyAnnotationsFlag, *applyAnnotation, "If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.") +} + +// AddGeneratorFlags adds flags common to resource generation commands +// TODO: need to take a pass at other generator commands to use this set of flags +func AddGeneratorFlags(cmd *cobra.Command, defaultGenerator string) { + cmd.Flags().String("generator", defaultGenerator, "The name of the API generator to use.") + AddDryRunFlag(cmd) +} + +type ValidateOptions struct { + EnableValidation bool +} + +// Merge requires JSON serialization +// TODO: merge assumes JSON serialization, and does not properly abstract API retrieval +func Merge(codec runtime.Codec, dst runtime.Object, fragment string) (runtime.Object, error) { + // encode dst into versioned json and apply fragment directly too it + target, err := runtime.Encode(codec, dst) + if err != nil { + return nil, err + } + patched, err := jsonpatch.MergePatch(target, []byte(fragment)) + if err != nil { + return nil, err + } + out, err := runtime.Decode(codec, patched) + if err != nil { + return nil, err + } + return out, nil +} + +// DumpReaderToFile writes all data from the given io.Reader to the specified file +// (usually for temporary use). +func DumpReaderToFile(reader io.Reader, filename string) error { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return err + } + defer f.Close() + + buffer := make([]byte, 1024) + for { + count, err := reader.Read(buffer) + if err == io.EOF { + break + } + if err != nil { + return err + } + _, err = f.Write(buffer[:count]) + if err != nil { + return err + } + } + return nil +} + +func GetServerSideApplyFlag(cmd *cobra.Command) bool { + return GetFlagBool(cmd, "server-side") +} + +func GetForceConflictsFlag(cmd *cobra.Command) bool { + return GetFlagBool(cmd, "force-conflicts") +} + +func GetFieldManagerFlag(cmd *cobra.Command) string { + return GetFlagString(cmd, "field-manager") +} + +func GetDryRunFlag(cmd *cobra.Command) bool { + return GetFlagBool(cmd, "dry-run") +} + +// GetResourcesAndPairs retrieves resources and "KEY=VALUE or KEY-" pair args from given args +func GetResourcesAndPairs(args []string, pairType string) (resources []string, pairArgs []string, err error) { + foundPair := false + for _, s := range args { + nonResource := (strings.Contains(s, "=") && s[0] != '=') || (strings.HasSuffix(s, "-") && s != "-") + switch { + case !foundPair && nonResource: + foundPair = true + fallthrough + case foundPair && nonResource: + pairArgs = append(pairArgs, s) + case !foundPair && !nonResource: + resources = append(resources, s) + case foundPair && !nonResource: + err = fmt.Errorf("all resources must be specified before %s changes: %s", pairType, s) + return + } + } + return +} + +// ParsePairs retrieves new and remove pairs (if supportRemove is true) from "KEY=VALUE or KEY-" pair args +func ParsePairs(pairArgs []string, pairType string, supportRemove bool) (newPairs map[string]string, removePairs []string, err error) { + newPairs = map[string]string{} + if supportRemove { + removePairs = []string{} + } + var invalidBuf bytes.Buffer + var invalidBufNonEmpty bool + for _, pairArg := range pairArgs { + if strings.Contains(pairArg, "=") && pairArg[0] != '=' { + parts := strings.SplitN(pairArg, "=", 2) + if len(parts) != 2 { + if invalidBufNonEmpty { + invalidBuf.WriteString(", ") + } + invalidBuf.WriteString(pairArg) + invalidBufNonEmpty = true + } else { + newPairs[parts[0]] = parts[1] + } + } else if supportRemove && strings.HasSuffix(pairArg, "-") && pairArg != "-" { + removePairs = append(removePairs, pairArg[:len(pairArg)-1]) + } else { + if invalidBufNonEmpty { + invalidBuf.WriteString(", ") + } + invalidBuf.WriteString(pairArg) + invalidBufNonEmpty = true + } + } + if invalidBufNonEmpty { + err = fmt.Errorf("invalid %s format: %s", pairType, invalidBuf.String()) + return + } + + return +} + +// IsSiblingCommandExists receives a pointer to a cobra command and a target string. +// Returns true if the target string is found in the list of sibling commands. +func IsSiblingCommandExists(cmd *cobra.Command, targetCmdName string) bool { + for _, c := range cmd.Parent().Commands() { + if c.Name() == targetCmdName { + return true + } + } + + return false +} + +// DefaultSubCommandRun prints a command's help string to the specified output if no +// arguments (sub-commands) are provided, or a usage error otherwise. +func DefaultSubCommandRun(out io.Writer) func(c *cobra.Command, args []string) { + return func(c *cobra.Command, args []string) { + c.SetOutput(out) + RequireNoArguments(c, args) + c.Help() + CheckErr(ErrExit) + } +} + +// RequireNoArguments exits with a usage error if extra arguments are provided. +func RequireNoArguments(c *cobra.Command, args []string) { + if len(args) > 0 { + CheckErr(UsageErrorf(c, "unknown command %q", strings.Join(args, " "))) + } +} + +// StripComments will transform a YAML file into JSON, thus dropping any comments +// in it. Note that if the given file has a syntax error, the transformation will +// fail and we will manually drop all comments from the file. +func StripComments(file []byte) []byte { + stripped := file + stripped, err := yaml.ToJSON(stripped) + if err != nil { + stripped = ManualStrip(file) + } + return stripped +} + +// ManualStrip is used for dropping comments from a YAML file +func ManualStrip(file []byte) []byte { + stripped := []byte{} + lines := bytes.Split(file, []byte("\n")) + for i, line := range lines { + if bytes.HasPrefix(bytes.TrimSpace(line), []byte("#")) { + continue + } + stripped = append(stripped, line...) + if i < len(lines)-1 { + stripped = append(stripped, '\n') + } + } + return stripped +} + +// ScaleClientFunc provides a ScalesGetter +type ScaleClientFunc func(genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) + +// ScaleClientFn gives a way to easily override the function for unit testing if needed. +var ScaleClientFn ScaleClientFunc = scaleClient + +// scaleClient gives you back scale getter +func scaleClient(restClientGetter genericclioptions.RESTClientGetter) (scale.ScalesGetter, error) { + discoveryClient, err := restClientGetter.ToDiscoveryClient() + if err != nil { + return nil, err + } + + clientConfig, err := restClientGetter.ToRESTConfig() + if err != nil { + return nil, err + } + + setKubernetesDefaults(clientConfig) + restClient, err := rest.RESTClientFor(clientConfig) + if err != nil { + return nil, err + } + resolver := scale.NewDiscoveryScaleKindResolver(discoveryClient) + mapper, err := restClientGetter.ToRESTMapper() + if err != nil { + return nil, err + } + + return scale.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil +} + +func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { + fmt.Fprintf(cmdErr, "WARNING: New generator %q specified, "+ + "but it isn't available. "+ + "Falling back to %q.\n", + newGeneratorName, + oldGeneratorName, + ) +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/kubectl_match_version.go b/vendor/k8s.io/kubectl/pkg/cmd/util/kubectl_match_version.go new file mode 100644 index 000000000..74308bc5d --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/kubectl_match_version.go @@ -0,0 +1,129 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "sync" + + "github.com/spf13/pflag" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/kubectl/pkg/scheme" + + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/component-base/version" +) + +const ( + flagMatchBinaryVersion = "match-server-version" +) + +// MatchVersionFlags is for setting the "match server version" function. +type MatchVersionFlags struct { + Delegate genericclioptions.RESTClientGetter + + RequireMatchedServerVersion bool + checkServerVersion sync.Once + matchesServerVersionErr error +} + +var _ genericclioptions.RESTClientGetter = &MatchVersionFlags{} + +func (f *MatchVersionFlags) checkMatchingServerVersion() error { + f.checkServerVersion.Do(func() { + if !f.RequireMatchedServerVersion { + return + } + discoveryClient, err := f.Delegate.ToDiscoveryClient() + if err != nil { + f.matchesServerVersionErr = err + return + } + f.matchesServerVersionErr = discovery.MatchesServerVersion(version.Get(), discoveryClient) + }) + + return f.matchesServerVersionErr +} + +// ToRESTConfig implements RESTClientGetter. +// Returns a REST client configuration based on a provided path +// to a .kubeconfig file, loading rules, and config flag overrides. +// Expects the AddFlags method to have been called. +func (f *MatchVersionFlags) ToRESTConfig() (*rest.Config, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + clientConfig, err := f.Delegate.ToRESTConfig() + if err != nil { + return nil, err + } + // TODO we should not have to do this. It smacks of something going wrong. + setKubernetesDefaults(clientConfig) + return clientConfig, nil +} + +func (f *MatchVersionFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return f.Delegate.ToRawKubeConfigLoader() +} + +func (f *MatchVersionFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + return f.Delegate.ToDiscoveryClient() +} + +// ToRESTMapper returns a mapper. +func (f *MatchVersionFlags) ToRESTMapper() (meta.RESTMapper, error) { + if err := f.checkMatchingServerVersion(); err != nil { + return nil, err + } + return f.Delegate.ToRESTMapper() +} + +func (f *MatchVersionFlags) AddFlags(flags *pflag.FlagSet) { + flags.BoolVar(&f.RequireMatchedServerVersion, flagMatchBinaryVersion, f.RequireMatchedServerVersion, "Require server version to match client version") +} + +func NewMatchVersionFlags(delegate genericclioptions.RESTClientGetter) *MatchVersionFlags { + return &MatchVersionFlags{ + Delegate: delegate, + } +} + +// setKubernetesDefaults sets default values on the provided client config for accessing the +// Kubernetes API or returns an error if any of the defaults are impossible or invalid. +// TODO this isn't what we want. Each clientset should be setting defaults as it sees fit. +func setKubernetesDefaults(config *rest.Config) error { + // TODO remove this hack. This is allowing the GetOptions to be serialized. + config.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"} + + if config.APIPath == "" { + config.APIPath = "/api" + } + if config.NegotiatedSerializer == nil { + // This codec factory ensures the resources are not converted. Therefore, resources + // will not be round-tripped through internal versions. Defaulting does not happen + // on the client. + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + } + return rest.SetKubernetesDefaults(config) +} diff --git a/vendor/k8s.io/kubectl/pkg/cmd/util/printing.go b/vendor/k8s.io/kubectl/pkg/cmd/util/printing.go new file mode 100644 index 000000000..ebd228821 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/cmd/util/printing.go @@ -0,0 +1,29 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "fmt" + + "k8s.io/kubectl/pkg/util/templates" +) + +// SuggestAPIResources returns a suggestion to use the "api-resources" command +// to retrieve a supported list of resources +func SuggestAPIResources(parent string) string { + return templates.LongDesc(fmt.Sprintf("Use \"%s api-resources\" for a complete list of supported resources.", parent)) +} diff --git a/vendor/k8s.io/kubectl/pkg/generated/bindata.go b/vendor/k8s.io/kubectl/pkg/generated/bindata.go new file mode 100644 index 000000000..6d49fa1f6 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/generated/bindata.go @@ -0,0 +1,22850 @@ +// Package generated Code generated by go-bindata. (@generated) DO NOT EDIT. +// sources: +// translations/OWNERS +// translations/extract.py +// translations/kubectl/OWNERS +// translations/kubectl/de_DE/LC_MESSAGES/k8s.mo +// translations/kubectl/de_DE/LC_MESSAGES/k8s.po +// translations/kubectl/default/LC_MESSAGES/k8s.mo +// translations/kubectl/default/LC_MESSAGES/k8s.po +// translations/kubectl/en_US/LC_MESSAGES/k8s.mo +// translations/kubectl/en_US/LC_MESSAGES/k8s.po +// translations/kubectl/fr_FR/LC_MESSAGES/k8s.mo +// translations/kubectl/fr_FR/LC_MESSAGES/k8s.po +// translations/kubectl/it_IT/LC_MESSAGES/k8s.mo +// translations/kubectl/it_IT/LC_MESSAGES/k8s.po +// translations/kubectl/ja_JP/LC_MESSAGES/k8s.mo +// translations/kubectl/ja_JP/LC_MESSAGES/k8s.po +// translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo +// translations/kubectl/ko_KR/LC_MESSAGES/k8s.po +// translations/kubectl/template.pot +// translations/kubectl/zh_CN/LC_MESSAGES/k8s.mo +// translations/kubectl/zh_CN/LC_MESSAGES/k8s.po +// translations/kubectl/zh_TW/LC_MESSAGES/k8s.mo +// translations/kubectl/zh_TW/LC_MESSAGES/k8s.po +// translations/test/default/LC_MESSAGES/k8s.mo +// translations/test/default/LC_MESSAGES/k8s.po +// translations/test/en_US/LC_MESSAGES/k8s.mo +// translations/test/en_US/LC_MESSAGES/k8s.po +package generated + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// Mode return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _translationsOwners = []byte(`# See the OWNERS docs at https://go.k8s.io/owners + +reviewers: + - brendandburns +approvers: + - brendandburns +`) + +func translationsOwnersBytes() ([]byte, error) { + return _translationsOwners, nil +} + +func translationsOwners() (*asset, error) { + bytes, err := translationsOwnersBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/OWNERS", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsExtractPy = []byte(`#!/usr/bin/env python + +# Copyright 2017 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Extract strings from command files and externalize into translation files. +Expects to be run from the root directory of the repository. + +Usage: + extract.py pkg/kubectl/cmd/apply.go + +""" +import fileinput +import sys +import re + +class MatchHandler(object): + """ Simple holder for a regular expression and a function + to run if that regular expression matches a line. + The function should expect (re.match, file, linenumber) as parameters + """ + def __init__(self, regex, replace_fn): + self.regex = re.compile(regex) + self.replace_fn = replace_fn + +def short_replace(match, file, line_number): + """Replace a Short: ... cobra command description with an internationalization + """ + sys.stdout.write('{}i18n.T({}),\n'.format(match.group(1), match.group(2))) + +SHORT_MATCH = MatchHandler(r'(\s+Short:\s+)("[^"]+"),', short_replace) + +def import_replace(match, file, line_number): + """Add an extra import for the i18n library. + Doesn't try to be smart and detect if it's already present, assumes a + gofmt round wil fix things. + """ + sys.stdout.write('{}\n"k8s.io/kubectl/pkg/util/i18n"\n'.format(match.group(1))) + +IMPORT_MATCH = MatchHandler('(.*"k8s.io/kubectl/pkg/cmd/util")', import_replace) + + +def string_flag_replace(match, file, line_number): + """Replace a cmd.Flags().String("...", "", "...") with an internationalization + """ + sys.stdout.write('{}i18n.T("{})"))\n'.format(match.group(1), match.group(2))) + +STRING_FLAG_MATCH = MatchHandler('(\s+cmd\.Flags\(\).String\("[^"]*", "[^"]*", )"([^"]*)"\)', string_flag_replace) + + +def long_string_replace(match, file, line_number): + return '{}i18n.T({}){}'.format(match.group(1), match.group(2), match.group(3)) + +LONG_DESC_MATCH = MatchHandler('(LongDesc\()(` + "`" + `[^` + "`" + `]+` + "`" + `)([^\n]\n)', long_string_replace) + +EXAMPLE_MATCH = MatchHandler('(Examples\()(` + "`" + `[^` + "`" + `]+` + "`" + `)([^\n]\n)', long_string_replace) + +def replace(filename, matchers, multiline_matchers): + """Given a file and a set of matchers, run those matchers + across the file and replace it with the results. + """ + # Run all the matchers + line_number = 0 + for line in fileinput.input(filename, inplace=True): + line_number += 1 + matched = False + for matcher in matchers: + match = matcher.regex.match(line) + if match: + matcher.replace_fn(match, filename, line_number) + matched = True + break + if not matched: + sys.stdout.write(line) + sys.stdout.flush() + with open(filename, 'r') as datafile: + content = datafile.read() + for matcher in multiline_matchers: + match = matcher.regex.search(content) + while match: + rep = matcher.replace_fn(match, filename, 0) + # Escape back references in the replacement string + # (And escape for Python) + # (And escape for regex) + rep = re.sub('\\\\(\\d)', '\\\\\\\\\\1', rep) + content = matcher.regex.sub(rep, content, 1) + match = matcher.regex.search(content) + sys.stdout.write(content) + + # gofmt the file again + from subprocess import call + call(["goimports", "-w", filename]) + +replace(sys.argv[1], [SHORT_MATCH, IMPORT_MATCH, STRING_FLAG_MATCH], [LONG_DESC_MATCH, EXAMPLE_MATCH]) +`) + +func translationsExtractPyBytes() ([]byte, error) { + return _translationsExtractPy, nil +} + +func translationsExtractPy() (*asset, error) { + bytes, err := translationsExtractPyBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/extract.py", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlOwners = []byte(`# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- sig-cli-maintainers +reviewers: +- sig-cli +`) + +func translationsKubectlOwnersBytes() ([]byte, error) { + return _translationsKubectlOwners, nil +} + +func translationsKubectlOwners() (*asset, error) { + bytes, err := translationsKubectlOwnersBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/OWNERS", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlDe_deLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xd5\x00\x00\x00\x1c\x00\x00\x00\xc4\x06\x00\x00%\x01\x00\x00l\r\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\xdc\x00\x00\x00\x01\x12\x00\x00\xb6\x00\x00\x00\xde\x12\x00\x00\v\x02\x00\x00\x95\x13\x00\x00\x1f\x01\x00\x00\xa1\x15\x00\x00z\x00\x00\x00\xc1\x16\x00\x00_\x02\x00\x00<\x17\x00\x00\u007f\x01\x00\x00\x9c\x19\x00\x00\x8f\x01\x00\x00\x1c\x1b\x00\x00k\x01\x00\x00\xac\x1c\x00\x00k\x01\x00\x00\x18\x1e\x00\x00>\x01\x00\x00\x84\x1f\x00\x00\x03\x02\x00\x00\xc3 \x00\x00o\x01\x00\x00\xc7\"\x00\x00H\x05\x00\x007$\x00\x00g\x02\x00\x00\x80)\x00\x00\x1b\x02\x00\x00\xe8+\x00\x00q\x01\x00\x00\x04.\x00\x00\xa8\x01\x00\x00v/\x00\x00\xd4\x01\x00\x00\x1f1\x00\x00\x02\x02\x00\x00\xf42\x00\x00\xb4\x00\x00\x00\xf74\x00\x00\xb7\x02\x00\x00\xac5\x00\x00\x92\x03\x00\x00d8\x00\x00\xbf\x01\x00\x00\xf7;\x00\x00=\x00\x00\x00\xb7=\x00\x00;\x00\x00\x00\xf5=\x00\x00\xcd\x02\x00\x001>\x00\x00<\x00\x00\x00\xff@\x00\x00P\x00\x00\x00\xa1\x00\x009\x00\x00\x00Y\xa1\x00\x00\x13\x00\x00\x00\x93\xa1\x00\x00\x1b\x00\x00\x00\xa7\xa1\x00\x00@\x00\x00\x00\u00e1\x00\x00,\x00\x00\x00\x04\xa2\x00\x00*\x00\x00\x001\xa2\x00\x007\x00\x00\x00\\\xa2\x00\x00'\x00\x00\x00\x94\xa2\x00\x00&\x00\x00\x00\xbc\xa2\x00\x00.\x00\x00\x00\xe3\xa2\x00\x00=\x00\x00\x00\x12\xa3\x00\x00*\x00\x00\x00P\xa3\x00\x000\x00\x00\x00{\xa3\x00\x00,\x00\x00\x00\xac\xa3\x00\x00\x1f\x00\x00\x00\u0663\x00\x00]\x00\x00\x00\xf9\xa3\x00\x000\x00\x00\x00W\xa4\x00\x000\x00\x00\x00\x88\xa4\x00\x00\"\x00\x00\x00\xb9\xa4\x00\x00?\x00\x00\x00\u0724\x00\x00\x1d\x00\x00\x00\x1c\xa5\x00\x00,\x00\x00\x00:\xa5\x00\x00+\x00\x00\x00g\xa5\x00\x00$\x00\x00\x00\x93\xa5\x00\x00\x14\x00\x00\x00\xb8\xa5\x00\x00*\x00\x00\x00\u0365\x00\x00A\x00\x00\x00\xf8\xa5\x00\x00\x1d\x00\x00\x00:\xa6\x00\x00\x1c\x00\x00\x00X\xa6\x00\x00\x1a\x00\x00\x00u\xa6\x00\x00)\x00\x00\x00\x90\xa6\x00\x006\x00\x00\x00\xba\xa6\x00\x00\x1d\x00\x00\x00\xf1\xa6\x00\x00\x19\x00\x00\x00\x0f\xa7\x00\x00 \x00\x00\x00)\xa7\x00\x00v\x00\x00\x00J\xa7\x00\x00(\x00\x00\x00\xc1\xa7\x00\x00\x16\x00\x00\x00\xea\xa7\x00\x00p\x00\x00\x00\x01\xa8\x00\x00\x1b\x00\x00\x00r\xa8\x00\x00\x18\x00\x00\x00\x8e\xa8\x00\x00\x1a\x00\x00\x00\xa7\xa8\x00\x00$\x00\x00\x00\u00a8\x00\x00\x1d\x00\x00\x00\xe7\xa8\x00\x00\x17\x00\x00\x00\x05\xa9\x00\x00a\x00\x00\x00\x1d\xa9\x00\x00s\x00\x00\x00\u007f\xa9\x00\x00B\x00\x00\x00\xf3\xa9\x00\x00+\x00\x00\x006\xaa\x00\x00+\x00\x00\x00b\xaa\x00\x006\x00\x00\x00\x8e\xaa\x00\x00;\x00\x00\x00\u016a\x00\x00q\x00\x00\x00\x01\xab\x00\x00/\x00\x00\x00s\xab\x00\x001\x00\x00\x00\xa3\xab\x00\x00'\x00\x00\x00\u056b\x00\x00'\x00\x00\x00\xfd\xab\x00\x00\x18\x00\x00\x00%\xac\x00\x00&\x00\x00\x00>\xac\x00\x00%\x00\x00\x00e\xac\x00\x00(\x00\x00\x00\x8b\xac\x00\x00K\x00\x00\x00\xb4\xac\x00\x00 \x00\x00\x00\x00\xad\x00\x00_\x00\x00\x00!\xad\x00\x00\x1e\x00\x00\x00\x81\xad\x00\x00\"\x00\x00\x00\xa0\xad\x00\x00\"\x00\x00\x00\u00ed\x00\x00\x1f\x00\x00\x00\xe6\xad\x00\x00-\x00\x00\x00\x06\xae\x00\x00-\x00\x00\x004\xae\x00\x009\x00\x00\x00b\xae\x00\x00\x1e\x00\x00\x00\x9c\xae\x00\x00\x19\x00\x00\x00\xbb\xae\x00\x00c\x00\x00\x00\u056e\x00\x00#\x00\x00\x009\xaf\x00\x00\x82\x00\x00\x00]\xaf\x00\x00H\x00\x00\x00\xe0\xaf\x00\x00&\x00\x00\x00)\xb0\x00\x00e\x00\x00\x00P\xb0\x00\x00z\x00\x00\x00\xb6\xb0\x00\x00J\x00\x00\x001\xb1\x00\x00\xe5\x00\x00\x00|\xb1\x00\x00W\x00\x00\x00b\xb2\x00\x00E\x00\x00\x00\xba\xb2\x00\x00a\x00\x00\x00\x00\xb3\x00\x00v\x00\x00\x00b\xb3\x00\x00\x1c\x00\x00\x00\u0673\x00\x00T\x00\x00\x00\xf6\xb3\x00\x00\x17\x00\x00\x00K\xb4\x00\x009\x00\x00\x00c\xb4\x00\x00\x1e\x00\x00\x00\x9d\xb4\x00\x00=\x00\x00\x00\xbc\xb4\x00\x00$\x00\x00\x00\xfa\xb4\x00\x00\x1f\x00\x00\x00\x1f\xb5\x00\x00&\x00\x00\x00?\xb5\x00\x00+\x00\x00\x00f\xb5\x00\x00G\x00\x00\x00\x92\xb5\x00\x00\x14\x00\x00\x00\u06b5\x00\x00/\x00\x00\x00\xef\xb5\x00\x00\xd3\x01\x00\x00\x1f\xb6\x00\x00\xdd\x00\x00\x00\xf3\xb7\x00\x00\xb8\x00\x00\x00\u0478\x00\x00J\x02\x00\x00\x8a\xb9\x00\x00\x14\x01\x00\x00\u057b\x00\x00\x87\x00\x00\x00\xea\xbc\x00\x00y\x02\x00\x00r\xbd\x00\x00\xa7\x01\x00\x00\xec\xbf\x00\x00\xb2\x01\x00\x00\x94\xc1\x00\x00|\x01\x00\x00G\xc3\x00\x00\u007f\x01\x00\x00\xc4\xc4\x00\x00>\x01\x00\x00D\xc6\x00\x00\x1b\x02\x00\x00\x83\xc7\x00\x00\x89\x01\x00\x00\x9f\xc9\x00\x00\xc9\x05\x00\x00)\xcb\x00\x00\x82\x02\x00\x00\xf3\xd0\x00\x009\x02\x00\x00v\xd3\x00\x00\xbc\x01\x00\x00\xb0\xd5\x00\x00\xc3\x01\x00\x00m\xd7\x00\x00\xf8\x01\x00\x001\xd9\x00\x00 \x02\x00\x00*\xdb\x00\x00\xc1\x00\x00\x00K\xdd\x00\x00\xc9\x02\x00\x00\r\xde\x00\x00\xa6\x03\x00\x00\xd7\xe0\x00\x00\xed\x01\x00\x00~\xe4\x00\x00D\x00\x00\x00l\xe6\x00\x00B\x00\x00\x00\xb1\xe6\x00\x00\xee\x02\x00\x00\xf4\xe6\x00\x00N\x00\x00\x00\xe3\xe9\x00\x00U\x00\x00\x002\xea\x00\x00W\x00\x00\x00\x88\xea\x00\x00E\x00\x00\x00\xe0\xea\x00\x00\xbf\x01\x00\x00&\xeb\x00\x000\x03\x00\x00\xe6\xec\x00\x00\x1d\x02\x00\x00\x17\xf0\x00\x00\xf9\x01\x00\x005\xf2\x00\x00\xd7\x01\x00\x00/\xf4\x00\x00k\x01\x00\x00\a\xf6\x00\x00N\x01\x00\x00s\xf7\x00\x00\xed\x06\x00\x00\xc2\xf8\x00\x00.\x02\x00\x00\xb0\xff\x00\x00\x1c\x03\x00\x00\xdf\x01\x01\x00-\x03\x00\x00\xfc\x04\x01\x00\b\x01\x00\x00*\b\x01\x00\xc7\x01\x00\x003\t\x01\x00\xef\x01\x00\x00\xfb\n\x01\x00\x1d\x00\x00\x00\xeb\f\x01\x00C\x00\x00\x00\t\r\x01\x00<\x00\x00\x00M\r\x01\x00\xd9\x00\x00\x00\x8a\r\x01\x00\xa8\x02\x00\x00d\x0e\x01\x004\x00\x00\x00\r\x11\x01\x00\x9c\x03\x00\x00B\x11\x01\x00{\x00\x00\x00\xdf\x14\x01\x00a\x00\x00\x00[\x15\x01\x00V\x00\x00\x00\xbd\x15\x01\x00/\x00\x00\x00\x14\x16\x01\x00\x97\x02\x00\x00D\x16\x01\x009\x00\x00\x00\xdc\x18\x01\x00\x9b\x00\x00\x00\x16\x19\x01\x00m\x01\x00\x00\xb2\x19\x01\x00\r\b\x00\x00 \x1b\x01\x00\x94\x01\x00\x00.#\x01\x00\x90\x00\x00\x00\xc3$\x01\x00\x0f\x01\x00\x00T%\x01\x00\xf7\x00\x00\x00d&\x01\x00\x9e\x05\x00\x00\\'\x01\x00\xaa\x05\x00\x00\xfb,\x01\x00#\x00\x00\x00\xa62\x01\x00%\x00\x00\x00\xca2\x01\x00\xed\x02\x00\x00\xf02\x01\x00\xd1\x01\x00\x00\xde5\x01\x00\xd1\x01\x00\x00\xb07\x01\x00\x8b\x01\x00\x00\x829\x01\x00\xfe\x00\x00\x00\x0e;\x01\x00\x04\x02\x00\x00\r<\x01\x00)\x01\x00\x00\x12>\x01\x00\xa5\x00\x00\x00\x00\x00\x00gI\x01\x005\x00\x00\x00\xa6I\x01\x00=\x00\x00\x00\xdcI\x01\x00\xc0\x00\x00\x00\x1aJ\x01\x00p\x00\x00\x00\xdbJ\x01\x00Z\x00\x00\x00LK\x01\x00{\x00\x00\x00\xa7K\x01\x00\xe0\x00\x00\x00#L\x01\x006\x00\x00\x00\x04M\x01\x00\xfe\x00\x00\x00;M\x01\x00M\x00\x00\x00:N\x01\x00*\x00\x00\x00\x88N\x01\x00m\x00\x00\x00\xb3N\x01\x00\"\x00\x00\x00!O\x01\x00C\x00\x00\x00DO\x01\x00\x8e\x00\x00\x00\x88O\x01\x00:\x00\x00\x00\x17P\x01\x003\x00\x00\x00RP\x01\x00\xb7\x00\x00\x00\x86P\x01\x00?\x00\x00\x00>Q\x01\x00/\x00\x00\x00~Q\x01\x00?\x00\x00\x00\xaeQ\x01\x00$\x00\x00\x00\xeeQ\x01\x00 \x00\x00\x00\x13R\x01\x00B\x00\x00\x004R\x01\x00\x17\x00\x00\x00wR\x01\x00 \x00\x00\x00\x8fR\x01\x00L\x00\x00\x00\xb0R\x01\x000\x00\x00\x00\xfdR\x01\x000\x00\x00\x00.S\x01\x00;\x00\x00\x00_S\x01\x00,\x00\x00\x00\x9bS\x01\x001\x00\x00\x00\xc8S\x01\x00@\x00\x00\x00\xfaS\x01\x00P\x00\x00\x00;T\x01\x002\x00\x00\x00\x8cT\x01\x005\x00\x00\x00\xbfT\x01\x005\x00\x00\x00\xf5T\x01\x00$\x00\x00\x00+U\x01\x00f\x00\x00\x00PU\x01\x001\x00\x00\x00\xb7U\x01\x002\x00\x00\x00\xe9U\x01\x00)\x00\x00\x00\x1cV\x01\x00R\x00\x00\x00FV\x01\x00&\x00\x00\x00\x99V\x01\x00.\x00\x00\x00\xc0V\x01\x00,\x00\x00\x00\xefV\x01\x00$\x00\x00\x00\x1cW\x01\x00\x12\x00\x00\x00AW\x01\x003\x00\x00\x00TW\x01\x00L\x00\x00\x00\x88W\x01\x00!\x00\x00\x00\xd5W\x01\x00\x1b\x00\x00\x00\xf7W\x01\x00\x1c\x00\x00\x00\x13X\x01\x00+\x00\x00\x000X\x01\x00?\x00\x00\x00\\X\x01\x00&\x00\x00\x00\x9cX\x01\x00\x1b\x00\x00\x00\xc3X\x01\x00$\x00\x00\x00\xdfX\x01\x00\x8a\x00\x00\x00\x04Y\x01\x009\x00\x00\x00\x8fY\x01\x00\x17\x00\x00\x00\xc9Y\x01\x00\x81\x00\x00\x00\xe1Y\x01\x00\x1f\x00\x00\x00cZ\x01\x00\x1f\x00\x00\x00\x83Z\x01\x00!\x00\x00\x00\xa3Z\x01\x00+\x00\x00\x00\xc5Z\x01\x00 \x00\x00\x00\xf1Z\x01\x00\x1d\x00\x00\x00\x12[\x01\x00\\\x00\x00\x000[\x01\x00\x90\x00\x00\x00\x8d[\x01\x00E\x00\x00\x00\x1e\\\x01\x00;\x00\x00\x00d\\\x01\x00.\x00\x00\x00\xa0\\\x01\x009\x00\x00\x00\xcf\\\x01\x00B\x00\x00\x00\t]\x01\x00w\x00\x00\x00L]\x01\x003\x00\x00\x00\xc4]\x01\x007\x00\x00\x00\xf8]\x01\x003\x00\x00\x000^\x01\x005\x00\x00\x00d^\x01\x00\"\x00\x00\x00\x9a^\x01\x00/\x00\x00\x00\xbd^\x01\x00+\x00\x00\x00\xed^\x01\x00,\x00\x00\x00\x19_\x01\x00W\x00\x00\x00F_\x01\x00%\x00\x00\x00\x9e_\x01\x00a\x00\x00\x00\xc4_\x01\x00%\x00\x00\x00&`\x01\x00-\x00\x00\x00L`\x01\x00-\x00\x00\x00z`\x01\x00*\x00\x00\x00\xa8`\x01\x005\x00\x00\x00\xd3`\x01\x005\x00\x00\x00\ta\x01\x00D\x00\x00\x00?a\x01\x00\x1c\x00\x00\x00\x84a\x01\x00\x1a\x00\x00\x00\xa1a\x01\x00n\x00\x00\x00\xbca\x01\x008\x00\x00\x00+b\x01\x00\x80\x00\x00\x00db\x01\x00W\x00\x00\x00\xe5b\x01\x00$\x00\x00\x00=c\x01\x00g\x00\x00\x00bc\x01\x00\x8d\x00\x00\x00\xcac\x01\x00R\x00\x00\x00Xd\x01\x00\xee\x00\x00\x00\xabd\x01\x00p\x00\x00\x00\x9ae\x01\x00L\x00\x00\x00\vf\x01\x00j\x00\x00\x00Xf\x01\x00}\x00\x00\x00\xc3f\x01\x00#\x00\x00\x00Ag\x01\x00Y\x00\x00\x00eg\x01\x00 \x00\x00\x00\xbfg\x01\x00B\x00\x00\x00\xe0g\x01\x00)\x00\x00\x00#h\x01\x00E\x00\x00\x00Mh\x01\x000\x00\x00\x00\x93h\x01\x00*\x00\x00\x00\xc4h\x01\x006\x00\x00\x00\xefh\x01\x007\x00\x00\x00&i\x01\x00V\x00\x00\x00^i\x01\x00\x15\x00\x00\x00\xb5i\x01\x003\x00\x00\x00\xcbi\x01\x00\x01\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x87\x00\x00\x00\u007f\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00e\x00\x00\x00a\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x17\x00\x00\x00\xcc\x00\x00\x00\x0e\x00\x00\x00r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x00\x00\x00c\x00\x00\x00\x8f\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00Y\x00\x00\x00\xc4\x00\x00\x00>\x00\x00\x00\x8a\x00\x00\x00\xb3\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\x9c\x00\x00\x00\r\x00\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\xbb\x00\x00\x00\x95\x00\x00\x00j\x00\x00\x00\xc5\x00\x00\x00p\x00\x00\x00t\x00\x00\x00A\x00\x00\x00\x93\x00\x00\x00\x0f\x00\x00\x00`\x00\x00\x00s\x00\x00\x00\xc3\x00\x00\x00\x83\x00\x00\x00\x00\x00\x00\x00\x96\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00\x9d\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x92\x00\x00\x003\x00\x00\x00\xa3\x00\x00\x008\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00G\x00\x00\x00\xba\x00\x00\x00\x8e\x00\x00\x00}\x00\x00\x00\x9b\x00\x00\x00%\x00\x00\x00\xa8\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00\xa2\x00\x00\x00H\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x84\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00m\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\t\x00\x00\x00^\x00\x00\x00\xa9\x00\x00\x00\xc7\x00\x00\x00k\x00\x00\x00\xc2\x00\x00\x00\x94\x00\x00\x007\x00\x00\x00~\x00\x00\x00{\x00\x00\x00N\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcf\x00\x00\x00\x00\x00\x00\x00\x97\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\xb7\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\xd3\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00f\x00\x00\x00n\x00\x00\x00Q\x00\x00\x00\x1f\x00\x00\x00\xaa\x00\x00\x00b\x00\x00\x00\xc8\x00\x00\x00\n\x00\x00\x00O\x00\x00\x00y\x00\x00\x00\xa5\x00\x00\x00\x05\x00\x00\x00\x15\x00\x00\x00-\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00/\x00\x00\x00\x91\x00\x00\x00\x81\x00\x00\x00)\x00\x00\x009\x00\x00\x00\x8c\x00\x00\x00i\x00\x00\x00\xab\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00+\x00\x00\x00g\x00\x00\x00\xbd\x00\x00\x00\xa0\x00\x00\x00W\x00\x00\x00\x00\x00\x00\x00\x99\x00\x00\x00\xae\x00\x00\x00\x8d\x00\x00\x00\x00\x00\x00\x00\xcd\x00\x00\x00\\\x00\x00\x00\xc1\x00\x00\x004\x00\x00\x006\x00\x00\x00D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x98\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x00\x00\x00\x00\xb5\x00\x00\x00\x1b\x00\x00\x00u\x00\x00\x00\xbc\x00\x00\x00\xbe\x00\x00\x00[\x00\x00\x00\x00\x00\x00\x00\xa6\x00\x00\x00q\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00x\x00\x00\x00l\x00\x00\x00F\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x00\x00\x00\xad\x00\x00\x00\xd4\x00\x00\x005\x00\x00\x00\xca\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9e\x00\x00\x00o\x00\x00\x00\xac\x00\x00\x00\x00\x00\x00\x00\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcb\x00\x00\x00\x00\x00\x00\x00Z\x00\x00\x00\xc9\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\xbf\x00\x00\x00P\x00\x00\x00\x1d\x00\x00\x00\x88\x00\x00\x00\xb8\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00S\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\xa7\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00|\x00\x00\x00\x04\x00\x00\x00\x85\x00\x00\x00]\x00\x00\x00B\x00\x00\x00M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00w\x00\x00\x00K\x00\x00\x00_\x00\x00\x00\x89\x00\x00\x00\x19\x00\x00\x00\xd2\x00\x00\x00\xb9\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\xc0\x00\x00\x002\x00\x00\x00\xd5\x00\x00\x00h\x00\x00\x00\x18\x00\x00\x00\x9a\x00\x00\x00V\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x00\x00\x00?\x00\x00\x00L\x00\x00\x000\x00\x00\x00\x16\x00\x00\x00d\x00\x00\x00\x80\x00\x00\x00z\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: kubernetes\nReport-Msgid-Bugs-To: EMAIL\nPOT-Creation-Date: 2017-09-02 01:36+0200\nPO-Revision-Date: 2017-09-02 01:36+0200\nLanguage: de_DE\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n != 1);\nLast-Translator: Steffen Schmitz \nLanguage-Team: Steffen Schmitz \nX-Generator: Poedit 1.8.7.1\nX-Poedit-SourceCharset: UTF-8\n\x00\n\t\t # Erstellt ein ClusterRoleBinding f\u00fcr user1, user2 und group1 mit der ClusterRole cluster-admin\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Erstellt ein RoleBinding f\u00fcr user1, user2 und group1 mit der ClusterRole admin\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config basierend auf dem Ordner bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config mit den angegebenen Keys statt des Dateinamens auf der Festplatte.\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config mit key1=config1 und key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # Wenn keine .dockercfg Datei existiert, kann direkt ein dockercfg Secret erstellen mit:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Zeige Metriken f\u00fcr alle Nodes\n\t\t kubectl top node\n\n\t\t # Zeige Metriken f\u00fcr den gegebenen Node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Wende die Konfiguration in pod.json auf einen Pod an.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Wende die JSON-Daten von stdin auf einen Pod an.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Hinweis: --prune ist noch in Alpha\n\t\t# Wende die Konfiguration, mit dem Label app=nginx, im manifest.yaml an und l\u00f6sche alle Resourcen, die nicht in der Datei sind oder nicht das Label app=nginx besitzen.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Wende die Konfiguration im manifest.yaml an und l\u00f6sche alle ConfigMaps, die nicht in der Datei sind.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto-skaliere ein Deployment \"foo\", mit einer Anzahl an Pods zwischen 2 und 10, eine Ziel-CPU-Auslastung ist angegeben, sodass eine Standard-autoskalierungsregel verwendet wird:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto-skaliere einen Replication-Controller \"foo\", mit einer Anzahl an Pods zwischen 1 und 5, mit einer Ziel-CPU-Auslastung von 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Konvertiere 'pod.yaml' zur neuesten Version und schreibe auf stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Konvertiere den aktuellen Zustand der Resource, die in 'pod.yaml' angegeben ist, zur neuesten Version\n\t\t# und schreibe auf stdout im JSON-Format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Konvertiere alle Dateien im aktuellen Ordner zur neuesten Version und erstelle sie.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Erstellt eine ClusterRole \"pod-reader\", die es Nutzern erlaubt \"get\", \"watch\" und \"list\" auf den Pods auszuf\u00fchren\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Erstellt eine ClusterRole \"pod-reader\" mit dem angegebenen ResourceName\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Erstellt eine Role \"pod-reader\", die es dem Nutzer erlaubt \"get\", \"watch\" und \"list\" auf den Pods auszuf\u00fchren\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Erstellt eine Role \"pod-reader\" mit dem angegebenen ResourceName\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Erstellt eine neue ResourceQuota my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Erstellt eine neue ResourceQuota best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Erstellt ein Pod-Disruption-Budget my-pdb, dass alle Pods mit dem Label app=rails ausw\u00e4hlt\n\t\t# und sicherstellt, dass mindestens einer von ihnen zu jedem Zeitpunkt verf\u00fcgbar ist.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Erstellt ein Pod-Disruption-Budget my-pdb, dass alle Pods mit dem Label app=nginx ausw\u00e4hlt\n\t\t# und sicherstellt, dass mindestens die H\u00e4lfte der gew\u00e4hlten Pods zu jedem Zeitpunkt verf\u00fcgbar ist.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Erstellt einen Pod mit den Daten in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Erstellt einen Pod basierend auf den JSON-Daten von stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Ver\u00e4ndert die Daten in docker-registry.yaml in JSON mit dem v1 API Format und erstellt eine Resource mit den ver\u00e4nderten Daten.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Erstellt einen Service f\u00fcr einen replizierten nginx, der auf Port 80 h\u00f6rt und verbindet sich mit den Containern auf Port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Erstellt einen Service f\u00fcr einen Replication-Controller, der \u00fcber type und name in \"nginx-controller.yaml\" identifiziert wird, auf Port 80 h\u00f6rt und verbindet sich mit den Containern auf Port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Erstellt einen Service, mit dem Namen \"frontend\", f\u00fcr einen Pod valid-pod, der auf port 444 h\u00f6rt\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Erstellt einen zweiten Service basierend auf dem vorherigen Service, der den Container Port 8443 auf Port 443 mit dem Namen \"nginx-https\" anbietet\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Erstellt einen Service f\u00fcr eine Replicated-Streaming-Application auf Port 4100, die UDP-Traffic verarbeitet und 'video-stream' hei\u00dft.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Erstellt einen Service f\u00fcr einen replizierten nginx mit einem Replica-Set, dass auf Port 80 h\u00f6rt und verbindet sich mit den Containern auf Port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Erstellt einen Service f\u00fcr ein nginx Deployment, dass auf Port 80 h\u00f6rt und verbindet sich mit den Containern auf Port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# L\u00f6scht einen Pod mit type und name aus pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# L\u00f6scht einen Pod mit dem type und name aus den JSON-Daten von stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# L\u00f6scht Pods und Services mit den Namen \"baz\" und \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# L\u00f6scht Pods und Services mit dem Label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# L\u00f6scht einen Pod mit minimaler Verz\u00f6gerung\n\t\tkubectl delete pod foo --now\n\n\t\t# Erzwingt das L\u00f6schen eines Pods auf einem toten Node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# L\u00f6scht alle Pods\n\t\tkubectl delete pods --all\x00\n\t\t# Beschreibt einen Knoten\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Beschreibt einen Pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Beschreibt einen Pod mit type und name aus \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Beschreibt alle Pods\n\t\tkubectl describe pods\n\n\t\t# Beschreibt Pods mit dem Label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Beschreibt alle Pods, die vom ReplicationController 'frontend' verwaltet werden (rc-erstellte Pods\n\t\t# bekommen den Namen des rc als Prefix im Podnamen).\n\t\tkubectl describe pods frontend\x00\n\t\t# Leere den Knoten \"foo\", selbst wenn er Pods enth\u00e4lt, die nicht von einem ReplicationController, ReplicaSet, Job, DaemonSet oder StatefulSet verwaltet werden.\n\t\t$ kubectl drain foo --force\n\n\t\t# Wie zuvor, aber es wird abgebrochen, wenn er Pods enth\u00e4lt, die nicht von einem ReplicationController, ReplicaSet, Job, DaemonSet oder StatefulSet verwaltet werden und mit einer Schonfrist von 15 Minuten.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Bearbeite den Service 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Benutze einen anderen Editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Bearbeite den Job 'myjob' in JSON mit dem v1 API Format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Bearbeite das Deployment 'mydeployment' in YAML und speichere die ver\u00e4nderte Konfiguration in ihrer Annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Erhalte die Ausgabe vom Aufruf von 'date' auf dem Pod 123456-7890, mit dem ersten Container als Standard\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Erhalte die Ausgabe vom Aufruf von 'date' im Ruby-Container aus dem Pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Wechsle in den Terminal-Modus und sende stdin zu 'bash' im Ruby-Container aus dem Pod 123456-7890\n\t\t# und sende stdout/stderr von 'bash' zur\u00fcck zum Client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Erhalte die Ausgabe vom laufenden Pod 123456-7890, mit dem ersten Container als Standard\n\t\tkubectl attach 123456-7890\n\n\t\t# Erhalte die Ausgabe vom Ruby-Container aus dem Pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Wechsle in den Terminal-Modus und sende stdin zu 'bash' im Ruby-Container aus dem Pod 123456-7890\n\t\t# und sende stdout/stderr von 'bash' zur\u00fcck zum Client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Erhalte die Ausgabe vom ersten Pod eines ReplicaSets nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Erhalte die Dokumentation einer Resource und ihrer Felder\n\t\tkubectl explain pods\n\n\t\t# Erhalte die Dokumentation eines speziellen Felds einer Resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Installiere bash completion auf einem Mac mit homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Lade den kubectl-Completion-Code f\u00fcr bash in der aktuellen Shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Schreibe den Bash-Completion-Code in eine Datei und source sie im .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Lade den kubectl-Completion-Code f\u00fcr zsh[1] in die aktuelle Shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# Liste alle Pods im ps-Format auf.\n\t\tkubectl get pods\n\n\t\t# Liste alle Pods im ps-Format mit zus\u00e4tzlichen Informationen (wie dem Knotennamen) auf.\n\t\tkubectl get pods -o wide\n\n\t\t# Liste alle einzelnen ReplicationController mit dem angegebenen Namen im ps-Format auf.\n\t\tkubectl get replicationcontroller web\n\n\t\t# Liste einen einzelnen Pod im JSON-Format auf.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# Liste einen Pod mit Typ und Namen aus \"pod.yaml\" im JSON-Format auf.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Gib nur den phase-Wert des angegebenen Pods zur\u00fcck.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# Liste alle ReplicationController und Services im ps-Format auf.\n\t\tkubectl get rc,services\n\n\t\t# Liste eine oder mehrere Resourcen \u00fcber ihren Typ und Namen auf.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# Liste alle Resourcen mit verschiedenen Typen auf.\n\t\tkubectl get all\x00\n\t\t# H\u00f6rt lokal auf Port 5000 und 6000 und leitet Daten zum/vom Port 5000 und 6000 weiter an den Pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# H\u00f6rt lokal auf Port 8888 und leitet an Port 5000 des Pods weiter\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# H\u00f6rt auf einen zuf\u00e4lligen lokalen Port und leitet an Port 5000 des Pods weiter\n\t\tkubectl port-forward mypod :5000\n\n\t\t# H\u00f6rt auf einen zuf\u00e4lligen lokalen Port und leitet an Port 5000 des Pods weiter\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Markiere Knoten \"foo\" als schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Markiere Knoten \"foo\" als unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Aktualisiere einen Knoten teilweise mit einem Strategic-Merge-Patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Aktualisiere einen Knoten, mit type und name aus \"node.json\", mit einem Strategic-Merge-Patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Aktualisiere das Image eines Containers; spec.containers[*].name ist erforderlich, da es der Merge-Key ist\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Aktualisiere das Image eines Containers mit einem JSON-Patch mit Positional-Arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Gebe Optionen aus, die an alle Kommandos vererbt werden\n\t\tkubectl options\x00\n\t\t# Gebe die Adresse des Masters und des Cluster-Services aus\n\t\tkubectl cluster-info\x00\n\t\t# Gebe die Client- und Server-Versionen des aktuellen Kontexts aus\n\t\tkubectl version\x00\n\t\t# Gebe die unterst\u00fctzten API Versionen aus\n\t\tkubectl api-versions\x00\n\t\t# Ersetze einen Pod mit den Daten aus pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Ersetze einen Pod mit den JSON-Daten von stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Setze die Pod-Image-Version (tag) eines einzelnen Containers zu v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Erzwinge das Ersetzen, L\u00f6schen und Neu-Erstellen der Resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Gib die Snapshot-Logs des Pods nginx mit nur einem Container zur\u00fcck\n\t\tkubectl logs nginx\n\n\t\t# Gib die Snapshot-Logs f\u00fcr die Pods mit dem Label app=nginx zur\u00fcck\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Gib die Snapshot-Logs des zuvor gel\u00f6schten Ruby-Containers des Pods web-1 zur\u00fcck\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Starte das Streaming der Logs vom Ruby-Container im Pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Zeige die letzten 20 Zeilen der Ausgabe des Pods nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Zeige alle Logs der letzten Stunde des Pods nginx an\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Gib die Snapshot-Logs des ersten Containers des Jobs hello zur\u00fcck\n\t\tkubectl logs job/hello\n\n\t\t# Gib die Snapshot-Logs des Containers nginx-1 eines Deployments nginx zur\u00fcck\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Starte einen Proxy zum Kubernetes-Apiserver auf Port 8011 und sende statische Inhalte von ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Starte einen Proxy zum Kubernetes-Apiserver auf einem zuf\u00e4lligen lokalen Port.\n\t\t# Der gew\u00e4hlte Port f\u00fcr den Server wird im stdout zur\u00fcckgegeben.\n\t\tkubectl proxy --port=0\n\n\t\t# Starte einen Proxy zum Kubernetes-Apiserver und \u00e4ndere das API-Prefix zu k8s-api\n\t\t# Damit ist die Pods-API bspw. unter localhost:8001/k8s-api/v1/pods/ erreichbar\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Skaliere ein ReplicaSet 'foo' auf 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Skaliere eine Resource mit type und name aus \"foo.yaml\" auf 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# Wenn die aktuelle Gr\u00f6\u00dfe des Deployments mysql 2 ist, skaliere mysql auf 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Skaliere mehrere MultiplicationController.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Skaliere den Job cron auf 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Setze die Last-Applied-Configuration einer Resource auf den Inhalt einer Datei.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# F\u00fchre Set-Last-Applied auf jeder Konfigurationsdatei in einem Ordner aus.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Setze die Last-Applied-Configuration einer Resource auf den Inhalt einer Datei; erstellt die Annotation, wenn sie noch nicht existiert.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Zeige Metriken f\u00fcr alle Pods im Namespace default\n\t\tkubectl top pod\n\n\t\t# Zeige Metriken f\u00fcr alle Pods im gegebenen namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Zeige Metriken f\u00fcr den gebenen Pod und seine Container\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Zeige Metriken f\u00fcr Pods mit dem Label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Stoppe foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stoppe Pods und Services mit dem Label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Stoppe den in service.json definierten Service\n\t\tkubectl stop -f service.json\n\n\t\t# Stoppe alle Resourcen im Ordner path/to/resources\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Starte eine einzelne Instanz von nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Starte eine einzelne Instanz von hazelcast und \u00f6ffne Port 5701 auf dem Container.\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Starte eine einzelne Instanz von hazelcast und setze die Umgebungs-variablen \"DNS_DOMAIN=cluster\" und \"POD_NAMESPACE=default\" im Container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Starte eine replizierte Instanz von nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Testlauf. Zeige die zugeh\u00f6rigen API Objekte ohne sie zu erstellen.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Starte eine einzelne Instanz von nginx, aber \u00fcberlade die Spec des Deployments mit einer Teilmenge von JSON-Werten.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Starte einen busybox Pod und lass ihn im Vordergrund laufen; starte ihn nicht neu, wenn er existiert.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Starte einen nginx-Container mit dem Standardkommando, aber \u00fcbergebe die Parameter (arg1 .. argN) an das Kommando.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Starte den nginx-Container mit einem anderen Kommando und Parametern.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Starte den perl-Container, um \u03c0 auf 2000 Stellen zu berechnen und gib es aus.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Starte den cron-Job, um \u03c0 auf 2000 Stellen zu berechnen und gib sie alle 5 Minuten aus.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Aktualisiere Knoten 'foo' mit einem Taint mit dem Key 'dedicated', dem Value 'special-user' und dem Effect 'NoSchedule'.\n\t\t# Wenn ein Taint mit dem Key und Effect schon existiert, wird sein Value mit den gegebenen Werten ersetzt.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Entferne vom Knoten 'foo' den Taint mit dem Key 'dedicated' und dem Effect 'NoSchedule', wenn er existiert.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Entferne vom Knoten 'foo' alle Tains mit dem Key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Aktualisiere den Pod 'foo' mit dem Label 'unhealthy' und dem Value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Aktualisiere den Pod 'foo' mit dem Label 'status' und dem Value 'unhealthy' und \u00fcberschreibe alle bisherigen Values.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Aktualisiere alle Pods im Namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Aktualisiere den Pod mit type und name aus \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Aktualisiere den Pod 'foo', wenn die Resource sich nicht von version 1 unterscheidet.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Aktualisiere den Pod 'foo', indem das Label 'bar' gel\u00f6scht wird, wenn es existiert.\n\t\t# Ben\u00f6tigt kein --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Aktualisiere die Pods in frontend-v1 mit den neuen Replication-Controller Daten in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Aktualisiere die Pods in frontend-v1 mit den JSON-Daten von stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Aktualisiere die Pods von frontend-v1 auf frontend-v2, indem das Image ge\u00e4ndert wird und\n\t\t# der Name des ReplicationControllers.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Aktualisiere die Pods in frontend, indem das Image ge\u00e4ndert, aber der alte Name beibehalten wird.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Breche ein laufendes Rollout (von frontend-v1 zu frontend-v2) ab und mache es r\u00fcckg\u00e4ngig.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# Zeige die Annotation Last-Applied-Configuration mit type/name in YAML an.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# Zeige die Annotation Last-applied-configuration mit der Datei in JSON an\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tWende eine Konfiguration auf eine Resource mit Dateinamen oder stdin an.\n\t\tDie Resource wird erstellt, wenn sie noch nicht existiert.\n\t\tUm 'apply' zu benutzen, muss die Resource initital mit 'apply' oder 'create --save-config' erstellt werden.\n\n\t\tJSON- und YAML-Formate werden akzeptiert.\n\n\t\tAlpha Disclaimer: Die --prune Funktion ist noch nicht fertig. Benutze sie nicht, wenn der aktuelle Zustand nicht bekannt ist. Siehe https://issues.k8s.io/34274.\x00\n\t\tKonvertiere Konfigurationsdateien zwischen API Versionen. Sowohl YAML-\n\t\talsauch JSON-Formate werden akzeptiert.\n\n\t\tDer Befehlt akzeptiert Dateinamen, Ordner oder URL als Parameter und konvertiert es ins Format\n\t\tder mit --output-version gegebenen Version. Wenn die Zielversion nicht \n\t\tangegeben wird oder ung\u00fcltig ist, wird die neueste Version verwendet.\n\n\t\tDie Standardausgabe wird auf stdout im YAML-Format ausgegeben. Man kann die Option -o verwenden,\n\t\tum das Ausgabeziel festzulegen.\x00\n\t\tErstelle eine ClusterRole.\x00\n\t\tErstelle ein ClusterRoleBinding f\u00fcr eine bestimmte ClusterRole.\x00\n\t\tErstelle ein RoleBinding f\u00fcr eine bestimmte ClusterRole.\x00\n\t\tErstelle ein TLS-Secret vom gegebenen Public/Private-Schl\u00fcsselpaar.\n\n\t\tDas Public/Private-Schl\u00fcsselpaar muss vorab bestehen. Das Public-Key-Zertifikat muss im PEM-Format sein und zum gegebenen Private-Key passen.\x00\n\t\tErstelle eine ConfigMap basierend auf einer Datei, einem Order oder einem gegebenen Wert.\n\n\t\tEine einzelne ConfigMap kann eins oder mehr Key/Value-Paare beinhalten.\n\n\t\tWenn man eine ConfigMap von einer Datei erstellt, wird der Key standardm\u00e4\u00dfig der Name der Datei, und der Wert wird\n\t\tstandardm\u00e4\u00dfig der Dateiinhalt. Wenn der Dateiname ein ung\u00fcltiger Key ist, kann ein anderer Key angegeben werden.\n\n\t\tWenn man eine ConfigMap von einem Ordner erstellt, wird jede Datei, deren Name ein g\u00fcltiger Key ist\n\t\tin die ConfigMap aufgenommen. Jegliche Eintr\u00e4ge im Ordner, die keine regul\u00e4ren Dateien sind, werden ignoriert (z.B. SubDirectories, \n\t\tSymLinks, Devices, Pipes, usw).\x00\n\t\tErstelle einen Namespace mit dem gegebenen Namen.\x00\n\t\tErstelle ein Secret f\u00fcr die Benutzung mit Docker-Registries.\n\n\t\tDockercfg Secrets werden f\u00fcr die Authentifizierung bei Docker-Registries benutzt.\n\n\t\tWenn die Docker-command -line zum pushen von Images benutzt wird, kann man sich bei einer gegebenen Registry authentifizieren mit\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n Dies produziert eine ~/.dockercfg Datei, die f\u00fcr folgende 'docker push' und 'docker pull' Befehle genutzt wird,\n\t\tum sich an der Registry zu authentifizieren. Die E-Mail-Adresse ist optional.\n\n\t\tBei der Erstellung von Applikationen, kann eine Docker-Registry eine Authentifizierung verlangen. Damit\n\t\tdeine Knoten in deinem Namen Images herunterladen k\u00f6nnen, ben\u00f6tigen sie die Credentials. Man kann diese Information bereitstellen\n\t\tindem man ein dockercfg secret erstellt und zu seinem ServiceAccount hinzuf\u00fcgt.\x00\n\t\tErstelle ein Pod-Disruption-Budget mit dem gegebenen name, selector und der gew\u00fcnschten Mindestanzahl verf\u00fcgbarer Pods\x00\n\t\tErstelle eine Resource mit Dateinamen oder stdin.\n\n\t\tJSON- und YAML-Formate werden akzeptiert.\x00\n\t\tErstelle eine ResourceQuota mit dem gegebenen name, hard limits und optional scopes\x00\n\t\tErstelle eine Role mit einer einzelnen Rule.\x00\n\t\tErstelle ein Secret basierend auf einer Datei, einem Ordner oder einem gegebenen Wert.\n\n\t\tEin einzelnes Secret kann eins oder mehr Key/Value-Paare beinhalten.\n\n\t\tWenn man ein Secret von einer Datei erstellt, wird der Key standardm\u00e4\u00dfig der Name der Datei, und der Wert wird\n\t\tstandardm\u00e4\u00dfig der Dateiinhalt. Wenn der Dateiname ein ung\u00fcltiger Key ist, kann ein anderer Key angegeben werden.\n\n\t\tWenn man ein Secret von einem Ordner erstellt, wird jede Datei, deren Name ein g\u00fcltiger Key ist\n\t\tin das Secret aufgenommen. Jegliche Eintr\u00e4ge im Ordner, die keine regul\u00e4ren Dateien sind, werden ignoriert (z.B. SubDirectories, \n\t\tSymLinks, Devices, Pipes, usw).\x00\n\t\tErstelle einen ServiceAccount mit dem gegebenen Namen.\x00\n\t\tErstelle und starte ein bestimmtes Image, m\u00f6glicherweise repliziert.\n\n\t\tErstellt ein Deployment oder Job, um den/die erstellten Container zu verwalten.\x00\n\t\tErstellt einen AutoScaler der die Anzahl der Pods, die im Kubernetes-Cluster laufen, automatisch w\u00e4hlt und anpasst.\n\n\t\tSucht ein Deployment, ReplicaSet oder ReplicationController mit Namen name und erstellt einen AutoScaler, der die Resource als Referenz nimmt.\n\t\tEin AutoScaler kann die Anzahl der im System deployten Pods nach Bedarf erh\u00f6hen oder verringern.\x00\n\t\tL\u00f6scht die Resourcen mit Dateinamen, stdin, resources- und names- oder mit resources- und label-Selektor.\n\n\t\tJSON- und YAML-Formate werden akzeptiert. Nur einer der Parameter darf verwendet werden: Dateiname,\n\t\tresources- und names-, oder resources- und label-Selektor.\n\n\t\tManche Resourcen, zum Beispiel Pods, unterst\u00fctzen grazi\u00f6ses L\u00f6schen. Sie definieren einen Standardzeitraum\n\t\tbevor das L\u00f6schen erzwungen wird (grace-period), aber dieser Wert kann \u00fcberschrieben werden mit\n\t\tder --grace-period Option, oder mit --now, das die grace-period auf 1 setzt. Da diese Resourcen\n\t\th\u00e4ufig Einheiten im Cluster sind, kann das L\u00f6schen nicht immer direkt best\u00e4tigt werden. Wenn der Knoten\n\t\tauf dem der Pod l\u00e4uft nicht verf\u00fcgbar ist, oder den API Server nicht erreichen kann, kann das L\u00f6schen bedeutend l\u00e4nger dauern\n\t\tals die grace-period. Um das L\u00f6schen zu erzwingen, muss eine grace-period von 0 \u00fcbergeben werden\n\t\tund die --force Option gesetzt sein.\n\n\t\tWICHTIG: Ein erzwungenes L\u00f6schen wartet nicht auf die Best\u00e4tigung, dass der Prozess\n\t\tbeendet wurde, was den Prozess am Leben erhalten kann, bis der Knoten die L\u00f6schung erkennt\n\t\tund das grazi\u00f6se L\u00f6schen beendet. Wenn Prozesse Shared-Storage oder eine Remote-API verwenden und\n\t\tden Namen des Pods brauchen, um sich selbst zu identifizieren, kann das erzwungene L\u00f6schen dazu f\u00fchren, dass\n\t\tmehrere Prozesse auf der gleichen Maschine die gleiche Identit\u00e4t verwenden, was zu\n\t\tDatenkorruption oder Inkonsistenz f\u00fchren kann. Erzwinge nur ein L\u00f6schen, wenn sichergestellt ist, dass der Pod\n\t\tgel\u00f6scht ist, oder wenn die Anwendung mehrere gleichzeitig laufende Kopien verarbeiten kann.\n\t\tAu\u00dferdem kann es passieren, dass der Scheduler neue Pods auf dem Knoten plaziert, bevor der Knoten\n\t\tdie Resourcen freigegeben hat, sodass diese Pods direkt entfernt werden.\n\n\t\tBer\u00fccksichtige au\u00dferdem, dass der Delete-Befehl KEINE versionen pr\u00fcft, sodass, wenn jemand\n\t\tein Update einer Resource gleichzeitig mit Deinem delete anst\u00f6\u00dft, dessen Update\n\t\tmit dem Rest der Resource entfernt wird.\x00\n\t\tVeraltet: Fahre eine Resource mit Namen oder Dateinamen grazi\u00f6s heruter.\n\n\t\tDer Stop-Befehl ist veraltet und alle Funktioneren werden mit dem Delete-Befehl abgedeckt.\n\t\tSiehe 'kubectl delete --help' f\u00fcr mehr Details.\n\n\t\tVersucht eine Resource, die grazi\u00f6ses L\u00f6schen unterst\u00fctzt, herunterzufahren und zu l\u00f6schen.\n\t\tWenn die Resource skaliert werden kann, wird sie vor dem L\u00f6schen auf 0 skaliert.\x00\n\t\tZeigt die Resourcennutzung (CPU/Memory/Storage) von Knoten.\n\n\t\tDer top-node-Befehl erlaubt es, die Resourcennutzung von Knoten zu betrachten.\x00\n\t\tZeigt die Resourcennutzung (CPU/Memory/Storage) von Pods.\n\n\t\tDer 'top pod'-Befehl erlaubt es, die Resourcennutzung von Pods zu betrachten.\n\n\t\tAufgrund der Metrik-Pipeline-Verz\u00f6gerung, k\u00f6nnen sie f\u00fcr ein paar Minuten nicht verf\u00fcgbar sein,\n\t\tnach der Pod-Erstellung.\x00\n\t\tZeige Resourcennutzung (CPU/Memory/Storage).\n\n\t\tDer top-Befehl erlaubt es, die Resourcennutzung von Knoten oder Pods zu betrachten.\n\n\t\tDieser Befehl ben\u00f6tigt eine korrekt konfigurierte und funktionierende Heapster-Installation auf dem Server. \x00\n\t\tLeere Knoten, um eine Wartung vorzubereiten.\n\n\t\tDer gegebene Knoten wird als unschedulable markiert, um die Zuordnung von neuen Pods zu verhindern.\n\t\t'drain' entfernt den Pod, falls der API-Server die Entfernung unterst\u00fctzt\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Wenn nicht, wird ein normales DELETE verwendet,\n\t\tum die Pods zu l\u00f6schen.\n\t\t'drain' entfernt oder l\u00f6scht alle Pods mit der Ausnahme von Mirror-Pods (welche vom API Server nicht gel\u00f6scht werden k\u00f6nnen)\n\t\tWenn DaemonSet-verwaltete Pods existieren, wird 'drain' nicht fortgesetzt\n\t\tohne die --ignore-daemonsets Option, und es wird in keinem Fall\n\t\tDaemonSet-verwaltete Pods l\u00f6schen, weil diese Pods direkt ersetzt w\u00fcrden durch den\n\t\tDaemonSet-Controller, der unschedulable Markierungen ignoriert. Wenn es irgendwelche\n\t\tPods gibt, die weder Mirror-Pods sind, noch von einem ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet oder Job verwaltet werden, wird drain keine Pods l\u00f6schen, au\u00dfer die\n\t\t--force Option ist gesetzt. --force l\u00e4sst das L\u00f6schen selbst zu, wenn die verwaltende Resource von einem\n\t\toder mehreren Pods fehlt.\n\n\t\t'drain' wartet auf eine grazi\u00f6se L\u00f6schung. Man sollte auf der Maschine nichts tun, w\u00e4hrend\n\t\tder Befehl l\u00e4uft.\n\n\t\tWenn der Knoten wieder bereit ist die Arbeit aufzunehmen, benutze kubectl uncordon,\n\t\twas den Knoten als schedulable markiert.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tBearbeite eine Resource mit dem Standardeditor.\n\n\t\tDer edit-Befehl erlaubt es jede API Resource direkt zu bearbeiten, wenn sie mit den\n\t\tCommand-Line-Tools erreichbar ist. Er \u00f6ffnet den Editor, der in der KUBE_EDITOR oder EDITOR\n\t\tUmgebunsvariable festgelegt ist, oder 'vi' auf Linux und 'notepad' auf Windows.\n\t\tEs ist m\u00f6glich mehrere Objekte zu bearbeiten, aber die \u00c4nderungen werden nacheinander angewendet. Der Befehl\n\t\takzeptiert Dateinamen und Command-Line-Parameter, aber die verwendeten Dateien m\u00fcssen\n\t\tvorab gespeicherte Versionen von Resourcen sein.\n\n\t\tDie Bearbeitung verwendet die API Version, die genutzt wurde, um die Resource zu lesen.\n\t\tUm eine spezifische API Version zu verwenden, muss die vollst\u00e4ndige Resource, Version und Group angegeben werden.\n\n\t\tDas Standardformat ist YAML. Um mit JSON zu arbeiten, setze \"-o json\".\n\n\t\tDie Option --windows-line-endings kann benutzt werden, um Windows Zeilen-umbr\u00fcche zu verwenden,\n\t\tansonsten wird der Standard des Betriebssystems verwendet.\n\n\t\tFalls beim Update ein Fehler auftritt, wird eine tempor\u00e4re Datei auf der Festplatte angelegt,\n\t\tdie die nicht verarbeiteten \u00c4nderungen enth\u00e4lt. Der h\u00e4ufigste Fehler beim Bearbeiten einer Resource\n\t\tist ein anderer Editor, der die Resource auf dem Server \u00e4ndert. Wenn das auftritt, muss man\n\t\tseine \u00c4nderungen auf die neue Version anwenden oder seine tempor\u00e4re\n\t\tgespeicherte Kopie mit der neuesten Resourcenversion aktualisieren.\x00\n\t\tMarkiere Knoten als schedulable.\x00\n\t\tMarkiere Knoten als unschedulable.\x00\n\t\tGibt den Shell-Completion-Code f\u00fcr die angegebene Shell aus (bash oder zsh).\n\t\tDer Shell-Code muss f\u00fcr eine interaktive Vervollst\u00e4ndigung von kubectl \n\t\tausgewertet werden. Das ist m\u00f6glich, indem man\n\t\tdie .bash_profile Datei sourcet.\n\n\t\tHinweis: Dies setzt das Bash-Completion-Framework voraus, das auf dem Mac nicht standardm\u00e4\u00dfig installiert ist. \n\t\tEs kann mit homebrew installiert werden:\n\n\t\t $ brew install bash-completion\n\n\t\tSobald es installiert ist, muss bash_completion ausgewertet werden. Dies wird erreicht, indem man\n\t\tdie folgende Zeile zur .bash_profile-Datei hinzuf\u00fcgt\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tHinweis f\u00fcr zsh Nutzer: [1] zsh completions werden nur in Versionen von zsh >= 5.2 unterst\u00fctzt\x00\n\t\tF\u00fchre ein Rolling-Update des gegebenen ReplicationControllers aus.\n\n\t\tErsetzt den gegebenen ReplicationController mit einem neuen Replication-Controller, indem die neue PodTampleta Pod f\u00fcr Pod\n\t\tangewendet wird. Die new-controller.json muss den gleichen Namespace wie\n\t\tder aktuelle ReplicationController besitzen und mindestens ein gemeinsames Label im ReplicaSelector \u00fcberschreiben.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tErsetze eine Resource mit Dateinamen oder stdin.\n\n\t\tJSON- and YAML-Formate werden akzeptiert. Wenn eine existierende Resource ersetzt wird,\n\t\tmuss die vollst\u00e4ndige spSpecec mitgegeben werden. Diese kann hiermit ausgelesen werden\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tBitte konsultiere https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html um zu erfahren, ob ein Feld ver\u00e4ndert werden darf.\x00\n\t\tSetze eine neue Gr\u00f6\u00dfe f\u00fcr ein Deployment, ReplicaSet, Replication-Contoller oder Job.\n\n\t\tScale erlaubt es Nutzern eine oder mehr Voraussetzungen f\u00fcr die Aktion festzulegen.\n\n\t\tWenn --current-replicas oder --resource-version gegeben ist, wird es validiert, bevor\n\t\tscale versucht wird, und es wird garantiert, dass die Voraussetzungen erf\u00fcllt sind, wenn\n\t\tscale zum Server geschickt wird.\x00\n\t\tSetze die aktuelle Annotation Last-Applied-Configuration auf den Inhalt der Datei.\n\t\tDas bedeutet, dass Last-Applied-Configuration aktualisiert wird, als ob 'kubectl apply -f ' ausgef\u00fchrt wurde,\n\t\tohne andere Teile des Objekts zu aktualisieren.\x00\n\t\tProxy alle Teile der Kubernetes-API und sonst nichts:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tProxy nur bestimmte Teile der Kubernetes-API und einige statische Dateien:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tDer Befehl oben l\u00e4sst dich 'curl localhost:8001/api/v1/pods' aufrufen.\n\n\t\tProxy alle Teile der Kubernetes-API auf einem anderen root:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tDer Befehl oben l\u00e4sst dich 'curl localhost:8001/custom/api/v1/pods' aufrufen\x00\n\t\tAktualisiere Felder einer Resource mit einem Strategic-Merge-Patch\n\n\t\tJSON- und YAML-Formate werden akzeptiert.\n\n\t\tBitte konsultiere https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html um zu erfahren, ob ein Feld mutable ist.\x00\n\t # Erstelle ein neues TLS Secret tl-secret mit dem gegebenen Schl\u00fcsselpaar:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Erstelle einen neuen Namespace my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Erstelle ein neues Secret my-secret mit einem Key f\u00fcr jede Datei im Ordner bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Erstelle ein neues Secret my-secret mit den gegebenen Keys statt der Namen auf der Festplatte\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Erstelle ein neues Scret my-secret mit key1=supersecret und key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Erstelle einen neuen ServiceAccount my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Erstelle einen neuen ExternalName-Service my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tErstelle einen ExternalName-Service mit den gegebenen Namen.\n\n\tExternalName service referenziert eine externe DNS Adresse statt\n\teines pods, was Anwendungsautoren erlaubt, einen Service zu referenzieren,\n\tder abseits der Platform, auf anderen Clustern oder lokal exisiert.\x00\n\tHelp hilft bei jedem Befehl in der Anwendung.\n\tGib einfach kubectl help [path to command] f\u00fcr alle Details ein.\x00\n # Erstelle einen neuen LoadBalancer-Service my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Erstelle einen neuen ClusterIP-Service my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Erstelle einen neuen ClusterIP-Service my-cs (im headless-Modus)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Erstelle ein neues Deployment my-dep, dass das busybox-Image nutzt.\n kubectl create deployment my-dep --image=busybox\x00\n # Erstelle einen neuen NodePort-Service my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Schreibe den aktuellen Cluster-Zustand auf stdout\n kubectl cluster-info dump\n\n # Schreibe aktuellen Cluster-Zustand in /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Schreibe alle Namespaces auf stdout\n kubectl cluster-info dump --all-namespaces\n\n # Schreibe eine Menge an Namespaces in /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n Erstelle einen LoadBalancer-Service mit dem gegebenen Namen.\x00\n Erstelle einen ClusterIP-Service mit dem gegebenen Namen.\x00\n Erstelle ein Deployment mit dem gegebenen Namen.\x00\n Erstelle einen NodePort-Service mit dem gegebenen Namen.\x00\n Zeigt Adressen des Master und von Services mit Label kubernetes.io/cluster-service=true\n F\u00fcr das weitere Debugging und die Diagnose von Clusterproblemen nutze 'kubectl cluster-info dump'.\x00Eine komma-separierte Menge von Quota-Scopes, die zu jedem Object passen muss, dass von der Quota betroffen ist.\x00Eine komma-separierte Menge von resource=quantity Paaren, die ein hartes Limit definieren.\x00Ein Label-Selektor, der f\u00fcr das Budget benutzt werden kann. Nur gleichheits-basierte Auswahlkriterien werden unterst\u00fctzt.\x00Ein Label-Selektor, der f\u00fcr den Service benutzt werden kann. Nur gleichheits-basierte Auswahlkriterien werden unterst\u00fctzt. Wenn er leer ist (standard), wird der Selektor vom ReplicationController oder ReplicaSet abgeleitet\x00Ein Schedule im Cron Format, dass der Job nutzen soll.\x00Zus\u00e4tzliche, externe IP Adressen (die nicht von Kubernetes verwaltet werden), die der Service akzeptieren soll. Wenn diese IP zu einem Knoten gerouted wird, kann der Service \u00fcber die IP angesprochen werden, zus\u00e4tzlich zu seiner generierten Service-IP.\x00Wende eine Konfiguration auf eine Resource \u00fcber den Dateinamen oder stdin an\x00Genehmige eine Certificate-Signing-Request\x00Weise Deine eigene ClusterIP zu oder setze sie auf 'None' f\u00fcr einen 'headless'-Service (kein LoadBalancing).\x00Weise einem laufenden Container zu\x00Auto-skaliere ein Deployment, ReplicaSet oder ReplicationController\x00ClusterIP, die dem Service zugewiesen werden soll. Freilassen, f\u00fcr automatische Zuweisung oder auf 'None' setzen f\u00fcr einen headless-Service.\x00ClusterRole, die das ClusterRoleBinding referenzieren soll\x00ClusterRole, die das RoleBinding referenzieren soll\x00Name des Containers dessen Image aktualisiert wird. Nur relevant, wenn --image angegeben ist, sonst ignoriert. Verpflichtend, wenn --image auf einem Multi-Container-Pod verwendet wird\x00Konvertiere Config-Dateien zwischen verschiedenen API Versionen\x00Kopiere Dateien und Ordner aus/in Container(n).\x00Erstelle ein ClusterRoleBinding f\u00fcr eine bestimmte ClusterRole\x00Erstelle einen LoadBalancer-Service.\x00Erstelle einen NodePort-Service.\x00Erstelle ein RoleBinding f\u00fcr eine bestimmte Role oder ClusterRole\x00Erstelle ein TLS-Secret\x00Erstelle einen ClusterIP-Service\x00Erstelle eine ConfigMap von einer Datei, einem Ordner oder einem festen Wert\x00Erstelle ein Deployment mit dem gegebenen Namen.\x00Erstelle einen Namespace mit dem gegebenen Namen\x00Erstelle ein Pod-Disruption-Budget mit dem gegebenen Namen.\x00Erstelle eine Quota mit dem gegebenen Namen.\x00Erstelle eine Resource von einer Datei oder stdin\x00Erstelle ein Secret f\u00fcr die Benutzung mit einer Docker-Registry\x00Erstelle ein Secret von einer lokalen Datei, einem Ordner oder einem festen Wert\x00Erstelle ein Secret mit dem angegebenen Sub-Befehl\x00Erstelle einen ServiceAccount mit dem gegebenen Namen\x00Erstelle einen Servuce mit dem angegebenen Sub-Befehl\x00Erstelle einen ExternalName-Service.\x00L\u00f6sche Resourcen von einer Datei, stdin, resources- und names- oder mit resources- und label-Selektor\x00L\u00f6sche das angegebene Cluster aus der kubeconfig\x00L\u00f6sche den angegebenen Kontext aus der kubeconfig\x00Lehne eine Certificate-Signing-Request ab\x00Veraltet: Grazi\u00f6ses herunterfahren einer Resource \u00fcber den Namen oder Dateinamen\x00Beschreibe einen oder mehrere Kontexte\x00Zeige Resourcennutzung (CPU/Memory) von Knoten\x00Zeige Resourcennutzung (CPU/Memory) von Pods\x00Zeige Resourcennutzung (CPU/Memory).\x00Zeige Cluster-Info\x00Zeige Cluster, die in der kubeconfig definiert sind\x00Zeige vereinte kubeconfig-Einstellungen oder die angegebene kubeconfig-Datei\x00Zeige eine oder mehrere Resourcen\x00Zeige den aktuellen Kontext\x00Dokumentation einer Resource\x00Leere Knoten, um eine Wartung vorzubereiten\x00Zeige viele relevante Informationen f\u00fcr Debugging und Diagnose\x00Bearbeite eine Resource auf dem Server\x00E-Mail f\u00fcr Docker-Registry\x00F\u00fchre einen Befehl im Container aus\x00Explizite Vorgabe, wann Container-Images gepullt werden. Verpflichtend, wenn --image ist gleich dem aktuellen Image ist - sonst ignoriert.\x00Leite einen oder mehrere lokale Ports an einen Pod weiter\x00Hilfe f\u00fcr jeden Befehl\x00IP, die dem Load-Balancer zugewiesen wird. Falls leer, wird eine tempor\u00e4re IP erstellt und verwendet (Cloud-Provider spezifisch)\x00Verwalte ein Deployment-Rollout\x00Markiere Knoten als schedulable\x00Markiere Knoten als unschedulable\x00Markiere die gegebene Resource als pausiert\x00Ver\u00e4ndere Certificate-Resources\x00Ver\u00e4ndere kubeconfig Dateien\x00Name oder Nummer des Ports in dem Container, zu dem der Service Daten leiten soll. Optional.\x00Zeige nur Logs nach einem bestimmten Datum (RFC3339) an. Zeigt standardm\u00e4\u00dfig alle logs. Es kann entweder since-time oder since benutzt werden.\x00Zeige Shell-Completion-Code f\u00fcr die angegebene Shell (bash oder zsh)\x00Passwort f\u00fcr die Authentifizierung bei der Docker-Registry\x00Pfad des Public-Key-Zertifikats im PEM-Format.\x00Pfad zum Private-Key, der zum gegebenen Zertifikat passt.\x00F\u00fchre ein Rolling-Update des gegebenen ReplicationControllers aus\x00Vorbedingung f\u00fcr Resource-Version. Verlangt, dass die aktuelle Resource-Version diesen Wert erf\u00fcllt, um zu skalieren.\x00Schreibt die Client- und Server-Versionsinformation\x00Schreibt die Liste von Optionen, die alle Befehle erben\x00Schreibt die Logs f\u00fcr einen Container in einem Pod\x00Ersetze eine Resource von einem Dateinamen oder stdin\x00Setze eine pausierte Resource fort\x00Role, die dieses RoleBinding referenzieren soll\x00Starte ein bestimmtes Image auf dem Cluster\x00Starte einen Proxy zum Kubernetes-API-Server\x00Setze eine neue Gr\u00f6\u00dfe f\u00fcr ein Deployment, ReplicaSet, ReplicationController oder Job\x00Setze bestimmte Features auf Objekten\x00Setze die Annotation Last-Applied-Configuration auf einem Live-Objekt auf den Inhalt einer Datei.\x00Setze den Selektor auf einer Resource\x00Setze einen Cluster-Eintrag in der kubeconfig\x00Setze einen Kontext-Eintrag in der kubeconfig\x00Setze einen User-Eintrag in der kubeconfig\x00Setze einen einzelnen Value in einer kubeconfig-Datei\x00Setze den aktuellen Kontext in einer kubeconfig-Datei\x00Zeige Details zu einer bestimmten Resource oder Gruppe von Resourcen\x00Zeige den Status des Rollout\x00Synonym f\u00fcr --target-port\x00Nehme einen Replication Controller, Service, Deployment oder Pod und biete ihn als neuen Kubernetes-Service an\x00Das Image, dass auf dem Container gestartet werden soll.\x00Die Image-Pull-Policy f\u00fcr den Container. Wenn leer, wird der Wert nicht vom Client gesetzt, sondern standardm\u00e4\u00dfig vom Server.\x00Die minimale Anzahl oder Prozentzahl von verf\u00fcgbaren Pods, die das Budget voraussetzt.\x00Der Name des neu erstellten Objekts.\x00Der Name des neu erstellten Objekts. Falls nicht angegeben, wird der Name der Input-Resource verwendet.\x00Der Name des zu verwendenden API-Generators. Siehe http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators f\u00fcr eine \u00dcbersicht.\x00Der Name des zu verwendenden API-Generators. Zur Zeit gibt es nur einen Generator.\x00Der Name des zu verwendenden API-Generators. Es gibt zwei Generatoren: 'service/v1' und 'service/v2'. Der einzige Unterschied ist, dass der Serviceport in v1 'default' hei\u00dft, w\u00e4hrend er in v2 unbenannt bleibt. Standard ist 'service/v2'.\x00Der Name des zu verwendenden Generators, um einen Service zu erstellen. Wird nur benutzt, wenn --expose true ist\x00Das Netzwerkprotokoll, f\u00fcr den zu erstellenden Service. Standard ist 'TCP'.\x00Der Port auf den der Service h\u00f6ren soll. Wird von der angebotenen Resource kopiert, falls nicht angegeben\x00Der Port, den der Container anbietet. Wenn --expose true ist, ist es auch der Port, den der zu erstellende Service verwendet\x00Der Typ des zu erstellenden Secrets\x00Typ f\u00fcr diesen Service: ClusterIP, NodePort oder LoadBalancer. Standard ist 'ClusterIP'.\x00Widerrufe ein vorheriges Rollout\x00Aktualisiere Felder einer Resource mit einem Strategic-Merge-Patch\x00Aktualisiere das Image einer Pod-Template\x00Aktualisiere Resourcen requests/limits auf Objekten mit Pod-Templates\x00Aktualisiere die Annotationen auf einer Resource\x00Aktualisiere die Labels auf einer Resource\x00Aktualisiere die Taints auf einem oder mehreren Knoten\x00Username f\u00fcr Authentifizierung bei der Docker-Registry\x00Zeige die aktuelle Annotation Last-Applied-Configuration einer Resource / eines Object\x00Zeige rollout-Verlauf\x00kubectl kontrolliert den Kubernetes-Cluster-Manager\x00") + +func translationsKubectlDe_deLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlDe_deLc_messagesK8sMo, nil +} + +func translationsKubectlDe_deLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlDe_deLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/de_DE/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlDe_deLc_messagesK8sPo = []byte(`# German translation. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR steffenschmitz@hotmail.de, 2017. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: kubernetes\n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-09-02 01:36+0200\n" +"PO-Revision-Date: 2017-09-02 01:36+0200\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Last-Translator: Steffen Schmitz \n" +"Language-Team: Steffen Schmitz \n" +"X-Generator: Poedit 1.8.7.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Erstellt ein ClusterRoleBinding für user1, user2 und group1 mit der " +"ClusterRole cluster-admin\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Erstellt ein RoleBinding für user1, user2 und group1 mit der " +"ClusterRole admin\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" +"\n" +"\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config basierend auf " +"dem Ordner bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config mit den " +"angegebenen Keys statt des Dateinamens auf der Festplatte.\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Erstellt eine neue ConfigMap mit dem Namen my-config mit key1=config1" +" und key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # Wenn keine .dockercfg Datei existiert, kann direkt ein " +"dockercfg Secret erstellen mit:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # Zeige Metriken für alle Nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Zeige Metriken für den gegebenen Node\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" +"\n" +"\t\t# Wende die Konfiguration in pod.json auf einen Pod an.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Wende die JSON-Daten von stdin auf einen Pod an.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Hinweis: --prune ist noch in Alpha\n" +"\t\t# Wende die Konfiguration, mit dem Label app=nginx, im manifest.yaml " +"an und lösche alle Resourcen, die nicht in der Datei sind oder nicht das " +"Label app=nginx besitzen.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Wende die Konfiguration im manifest.yaml an und lösche alle ConfigMaps, " +"die nicht in der Datei sind.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# Auto-skaliere ein Deployment \"foo\", mit einer Anzahl an Pods zwischen " +"2 und 10, eine Ziel-CPU-Auslastung ist angegeben, sodass eine Standard-" +"autoskalierungsregel verwendet wird:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto-skaliere einen Replication-Controller \"foo\", mit einer Anzahl an " +"Pods zwischen 1 und 5, mit einer Ziel-CPU-Auslastung von 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# Konvertiere 'pod.yaml' zur neuesten Version und schreibe auf stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Konvertiere den aktuellen Zustand der Resource, die in 'pod.yaml' " +"angegeben ist, zur neuesten Version\n" +"\t\t# und schreibe auf stdout im JSON-Format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Konvertiere alle Dateien im aktuellen Ordner zur neuesten Version und " +"erstelle sie.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Erstellt eine ClusterRole \"pod-reader\", die es Nutzern erlaubt " +"\"get\", \"watch\" und \"list\" auf den Pods auszuführen\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Erstellt eine ClusterRole \"pod-reader\" mit dem angegebenen " +"ResourceName\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Erstellt eine Role \"pod-reader\", die es dem Nutzer erlaubt " +"\"get\", \"watch\" und \"list\" auf den Pods auszuführen\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Erstellt eine Role \"pod-reader\" mit dem angegebenen ResourceName\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# Erstellt eine neue ResourceQuota my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Erstellt eine neue ResourceQuota best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# Erstellt ein Pod-Disruption-Budget my-pdb, dass alle Pods mit " +"dem Label app=rails auswählt\n" +"\t\t# und sicherstellt, dass mindestens einer von ihnen zu jedem Zeitpunkt " +"verfügbar ist.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Erstellt ein Pod-Disruption-Budget my-pdb, dass alle Pods mit " +"dem Label app=nginx auswählt\n" +"\t\t# und sicherstellt, dass mindestens die Hälfte der gewählten Pods zu " +"jedem Zeitpunkt verfügbar ist.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# Erstellt einen Pod mit den Daten in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Erstellt einen Pod basierend auf den JSON-Daten von stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Verändert die Daten in docker-registry.yaml in JSON mit dem v1 API " +"Format und erstellt eine Resource mit den veränderten Daten.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# Erstellt einen Service für einen replizierten nginx, der auf Port 80 " +"hört und verbindet sich mit den Containern auf Port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Erstellt einen Service für einen Replication-Controller, der über type " +"und name in \"nginx-controller.yaml\" identifiziert wird, auf Port 80 " +"hört und verbindet sich mit den Containern auf Port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Erstellt einen Service, mit dem Namen \"frontend\", für einen Pod " +"valid-pod, der auf port 444 hört\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Erstellt einen zweiten Service basierend auf dem vorherigen Service, " +"der den Container Port 8443 auf Port 443 mit dem Namen \"nginx-https\" " +"anbietet\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Erstellt einen Service für eine Replicated-Streaming-Application auf " +"Port 4100, die UDP-Traffic verarbeitet und 'video-stream' heißt.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Erstellt einen Service für einen replizierten nginx mit einem Replica-" +"Set, dass auf Port 80 hört und verbindet sich mit den Containern auf Port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Erstellt einen Service für ein nginx Deployment, dass auf Port 80 hört " +"und verbindet sich mit den Containern auf Port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# Löscht einen Pod mit type und name aus pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Löscht einen Pod mit dem type und name aus den JSON-Daten von stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Löscht Pods und Services mit den Namen \"baz\" und \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Löscht Pods und Services mit dem Label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Löscht einen Pod mit minimaler Verzögerung\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Erzwingt das Löschen eines Pods auf einem toten Node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Löscht alle Pods\n" +"\t\tkubectl delete pods --all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# Beschreibt einen Knoten\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Beschreibt einen Pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Beschreibt einen Pod mit type und name aus \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Beschreibt alle Pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Beschreibt Pods mit dem Label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Beschreibt alle Pods, die vom ReplicationController 'frontend' " +"verwaltet werden (rc-erstellte Pods\n" +"\t\t# bekommen den Namen des rc als Prefix im Podnamen).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# Leere den Knoten \"foo\", selbst wenn er Pods enthält, die nicht von " +"einem ReplicationController, ReplicaSet, Job, DaemonSet oder StatefulSet " +"verwaltet werden.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# Wie zuvor, aber es wird abgebrochen, wenn er Pods enthält, die nicht von " +"einem ReplicationController, ReplicaSet, Job, DaemonSet oder StatefulSet " +"verwaltet werden und mit einer Schonfrist von 15 Minuten.\n" +"\t\t$ kubectl drain foo --grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# Bearbeite den Service 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Benutze einen anderen Editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Bearbeite den Job 'myjob' in JSON mit dem v1 API Format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Bearbeite das Deployment 'mydeployment' in YAML und speichere die " +"veränderte Konfiguration in ihrer Annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# Erhalte die Ausgabe vom Aufruf von 'date' auf dem Pod 123456-7890, mit " +"dem ersten Container als Standard\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Erhalte die Ausgabe vom Aufruf von 'date' im Ruby-Container aus dem Pod " +"123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Wechsle in den Terminal-Modus und sende stdin zu 'bash' im Ruby-Container " +"aus dem Pod 123456-7890\n" +"\t\t# und sende stdout/stderr von 'bash' zurück zum Client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Erhalte die Ausgabe vom laufenden Pod 123456-7890, mit dem ersten " +"Container als Standard\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Erhalte die Ausgabe vom Ruby-Container aus dem Pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Wechsle in den Terminal-Modus und sende stdin zu 'bash' im Ruby-Container " +"aus dem Pod 123456-7890\n" +"\t\t# und sende stdout/stderr von 'bash' zurück zum Client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Erhalte die Ausgabe vom ersten Pod eines ReplicaSets nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# Erhalte die Dokumentation einer Resource und ihrer Felder\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Erhalte die Dokumentation eines speziellen Felds einer Resource\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# Installiere bash completion auf einem Mac mit homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Lade den kubectl-Completion-Code für bash in der aktuellen Shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Schreibe den Bash-Completion-Code in eine Datei und source sie im " +".bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Lade den kubectl-Completion-Code für zsh[1] in die aktuelle Shell\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# Liste alle Pods im ps-Format auf.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# Liste alle Pods im ps-Format mit zusätzlichen Informationen (wie dem " +"Knotennamen) auf.\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# Liste alle einzelnen ReplicationController mit dem angegebenen Namen im " +"ps-Format auf.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# Liste einen einzelnen Pod im JSON-Format auf.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# Liste einen Pod mit Typ und Namen aus \"pod.yaml\" im JSON-Format auf.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Gib nur den phase-Wert des angegebenen Pods zurück.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# Liste alle ReplicationController und Services im ps-Format auf.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# Liste eine oder mehrere Resourcen über ihren Typ und Namen auf.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# Liste alle Resourcen mit verschiedenen Typen auf.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" +"\n" +"\t\t# Hört lokal auf Port 5000 und 6000 und leitet Daten zum/vom Port 5000 und " +"6000 weiter an den Pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Hört lokal auf Port 8888 und leitet an Port 5000 des Pods weiter\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Hört auf einen zufälligen lokalen Port und leitet an Port 5000 des Pods " +"weiter\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Hört auf einen zufälligen lokalen Port und leitet an Port 5000 des Pods " +"weiter\n" +"\t\tkubectl port-forward mypod 0:5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# Markiere Knoten \"foo\" als schedulable.\n" +"\t\t$ kubectl uncordon foo" + +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# Markiere Knoten \"foo\" als unschedulable.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# Aktualisiere einen Knoten teilweise mit einem Strategic-Merge-Patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Aktualisiere einen Knoten, mit type und name aus \"node.json\", mit einem " +"Strategic-Merge-Patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Aktualisiere das Image eines Containers; spec.containers[*].name ist " +"erforderlich, da es der Merge-Key ist\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Aktualisiere das Image eines Containers mit einem JSON-Patch mit " +"Positional-Arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" + +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# Gebe Optionen aus, die an alle Kommandos vererbt werden\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# Gebe die Adresse des Masters und des Cluster-Services aus\n" +"\t\tkubectl cluster-info" + +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# Gebe die Client- und Server-Versionen des aktuellen Kontexts aus\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# Gebe die unterstützten API Versionen aus\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# Ersetze einen Pod mit den Daten aus pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Ersetze einen Pod mit den JSON-Daten von stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Setze die Pod-Image-Version (tag) eines einzelnen Containers zu v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Erzwinge das Ersetzen, Löschen und Neu-Erstellen der Resource\n" +"\t\tkubectl replace --force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# Gib die Snapshot-Logs des Pods nginx mit nur einem Container zurück\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Gib die Snapshot-Logs für die Pods mit dem Label app=nginx zurück\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Gib die Snapshot-Logs des zuvor gelöschten Ruby-Containers des Pods " +"web-1 zurück\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Starte das Streaming der Logs vom Ruby-Container im Pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Zeige die letzten 20 Zeilen der Ausgabe des Pods nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Zeige alle Logs der letzten Stunde des Pods nginx an\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Gib die Snapshot-Logs des ersten Containers des Jobs hello zurück\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Gib die Snapshot-Logs des Containers nginx-1 eines Deployments nginx " +"zurück\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# Starte einen Proxy zum Kubernetes-Apiserver auf Port 8011 und sende " +"statische Inhalte von ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Starte einen Proxy zum Kubernetes-Apiserver auf einem zufälligen lokalen " +"Port.\n" +"\t\t# Der gewählte Port für den Server wird im stdout zurückgegeben.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Starte einen Proxy zum Kubernetes-Apiserver und ändere das API-Prefix " +"zu k8s-api\n" +"\t\t# Damit ist die Pods-API bspw. unter localhost:8001/k8s-api/v1/pods/ " +"erreichbar\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Skaliere ein ReplicaSet 'foo' auf 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Skaliere eine Resource mit type und name aus \"foo.yaml\" auf 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# Wenn die aktuelle Größe des Deployments mysql 2 ist, skaliere mysql auf 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Skaliere mehrere MultiplicationController.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Skaliere den Job cron auf 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Setze die Last-Applied-Configuration einer Resource auf den Inhalt einer " +"Datei.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Führe Set-Last-Applied auf jeder Konfigurationsdatei in einem Ordner aus.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Setze die Last-Applied-Configuration einer Resource auf den Inhalt einer " +"Datei; erstellt die Annotation, wenn sie noch nicht existiert.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# Zeige Metriken für alle Pods im Namespace default\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Zeige Metriken für alle Pods im gegebenen namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Zeige Metriken für den gebenen Pod und seine Container\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Zeige Metriken für Pods mit dem Label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Stoppe foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stoppe Pods und Services mit dem Label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Stoppe den in service.json definierten Service\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Stoppe alle Resourcen im Ordner path/to/resources\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Starte eine einzelne Instanz von nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Starte eine einzelne Instanz von hazelcast und öffne Port 5701 auf dem " +"Container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Starte eine einzelne Instanz von hazelcast und setze die Umgebungs-" +"variablen \"DNS_DOMAIN=cluster\" und \"POD_NAMESPACE=default\" im Container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Starte eine replizierte Instanz von nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Testlauf. Zeige die zugehörigen API Objekte ohne sie zu erstellen.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Starte eine einzelne Instanz von nginx, aber überlade die Spec des " +"Deployments mit einer Teilmenge von JSON-Werten.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Starte einen busybox Pod und lass ihn im Vordergrund laufen; starte ihn " +"nicht neu, wenn er existiert.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Starte einen nginx-Container mit dem Standardkommando, aber übergebe " +"die Parameter (arg1 .. argN) an das Kommando.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Starte den nginx-Container mit einem anderen Kommando und Parametern.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Starte den perl-Container, um π auf 2000 Stellen zu berechnen und gib es " +"aus.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Starte den cron-Job, um π auf 2000 Stellen zu berechnen und gib sie alle " +"5 Minuten aus.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Aktualisiere Knoten 'foo' mit einem Taint mit dem Key 'dedicated', dem " +"Value 'special-user' und dem Effect 'NoSchedule'.\n" +"\t\t# Wenn ein Taint mit dem Key und Effect schon existiert, wird sein Value " +"mit den gegebenen Werten ersetzt.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Entferne vom Knoten 'foo' den Taint mit dem Key 'dedicated' und dem Effect " +"'NoSchedule', wenn er existiert.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Entferne vom Knoten 'foo' alle Tains mit dem Key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Aktualisiere den Pod 'foo' mit dem Label 'unhealthy' und dem Value " +"'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Aktualisiere den Pod 'foo' mit dem Label 'status' und dem Value " +"'unhealthy' und überschreibe alle bisherigen Values.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Aktualisiere alle Pods im Namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Aktualisiere den Pod mit type und name aus \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Aktualisiere den Pod 'foo', wenn die Resource sich nicht von version 1 " +"unterscheidet.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Aktualisiere den Pod 'foo', indem das Label 'bar' gelöscht wird, wenn es " +"existiert.\n" +"\t\t# Benötigt kein --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Aktualisiere die Pods in frontend-v1 mit den neuen Replication-" +"Controller Daten in frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Aktualisiere die Pods in frontend-v1 mit den JSON-Daten von stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Aktualisiere die Pods von frontend-v1 auf frontend-v2, indem das Image " +"geändert wird und\n" +"\t\t# der Name des ReplicationControllers.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Aktualisiere die Pods in frontend, indem das Image geändert, aber der " +"alte Name beibehalten wird.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Breche ein laufendes Rollout (von frontend-v1 zu frontend-v2) ab und " +"mache es rückgängig.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# Zeige die Annotation Last-Applied-Configuration mit type/name in YAML an.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# Zeige die Annotation Last-applied-configuration mit der Datei in JSON an\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." +msgstr "" +"\n" +"\t\tWende eine Konfiguration auf eine Resource mit Dateinamen oder stdin an.\n" +"\t\tDie Resource wird erstellt, wenn sie noch nicht existiert.\n" +"\t\tUm 'apply' zu benutzen, muss die Resource initital mit 'apply' oder " +"'create --save-config' erstellt werden.\n" +"\n" +"\t\tJSON- und YAML-Formate werden akzeptiert.\n" +"\n" +"\t\tAlpha Disclaimer: Die --prune Funktion ist noch nicht fertig. Benutze sie " +"nicht, wenn der aktuelle Zustand nicht bekannt ist. Siehe https://issues.k8s." +"io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\tKonvertiere Konfigurationsdateien zwischen API Versionen. Sowohl YAML-\n" +"\t\talsauch JSON-Formate werden akzeptiert.\n" +"\n" +"\t\tDer Befehlt akzeptiert Dateinamen, Ordner oder URL als Parameter und " +"konvertiert es ins Format\n" +"\t\tder mit --output-version gegebenen Version. Wenn die Zielversion nicht \n" +"\t\tangegeben wird oder ungültig ist, wird die neueste Version verwendet.\n" +"\n" +"\t\tDie Standardausgabe wird auf stdout im YAML-Format ausgegeben. Man kann " +"die Option -o verwenden,\n" +"\t\tum das Ausgabeziel festzulegen." + +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\tErstelle eine ClusterRole." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\tErstelle ein ClusterRoleBinding für eine bestimmte ClusterRole." + +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\tErstelle ein RoleBinding für eine bestimmte ClusterRole." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\tErstelle ein TLS-Secret vom gegebenen Public/Private-Schlüsselpaar.\n" +"\n" +"\t\tDas Public/Private-Schlüsselpaar muss vorab bestehen. Das Public-Key-" +"Zertifikat muss im PEM-Format sein und zum gegebenen Private-Key passen." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tErstelle eine ConfigMap basierend auf einer Datei, einem Order oder einem " +"gegebenen Wert.\n" +"\n" +"\t\tEine einzelne ConfigMap kann eins oder mehr Key/Value-Paare beinhalten.\n" +"\n" +"\t\tWenn man eine ConfigMap von einer Datei erstellt, wird der Key standard" +"mäßig der Name der Datei, und der Wert wird\n" +"\t\tstandardmäßig der Dateiinhalt. Wenn der Dateiname ein ungültiger Key ist, " +"kann ein anderer Key angegeben werden.\n" +"\n" +"\t\tWenn man eine ConfigMap von einem Ordner erstellt, wird jede Datei, deren " +"Name ein gültiger Key ist\n" +"\t\tin die ConfigMap aufgenommen. Jegliche Einträge im Ordner, die keine " +"regulären Dateien sind, werden ignoriert (z.B. SubDirectories, \n" +"\t\tSymLinks, Devices, Pipes, usw)." + +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\tErstelle einen Namespace mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tErstelle ein Secret für die Benutzung mit Docker-Registries.\n" +"\n" +"\t\tDockercfg Secrets werden für die Authentifizierung bei Docker-Registries " +"benutzt.\n" +"\n" +"\t\tWenn die Docker-command -line zum pushen von Images benutzt wird, kann man " +"sich bei einer gegebenen Registry authentifizieren mit\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" Dies produziert eine ~/.dockercfg Datei, die für folgende 'docker push' " +"und 'docker pull' Befehle genutzt wird,\n" +"\t\tum sich an der Registry zu authentifizieren. Die E-Mail-Adresse ist " +"optional.\n" +"\n" +"\t\tBei der Erstellung von Applikationen, kann eine Docker-Registry eine " +"Authentifizierung verlangen. Damit\n" +"\t\tdeine Knoten in deinem Namen Images herunterladen können, benötigen sie " +"die Credentials. " +"Man kann diese Information bereitstellen\n" +"\t\tindem man ein dockercfg secret erstellt und zu seinem ServiceAccount " +"hinzufügt." + +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" +"\n" +"\t\tErstelle ein Pod-Disruption-Budget mit dem gegebenen name, selector und " +"der gewünschten Mindestanzahl verfügbarer Pods" + +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\tErstelle eine Resource mit Dateinamen oder stdin.\n" +"\n" +"\t\tJSON- und YAML-Formate werden akzeptiert." + +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" +"\n" +"\t\tErstelle eine ResourceQuota mit dem gegebenen name, hard limits und optional " +"scopes" + +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\tErstelle eine Role mit einer einzelnen Rule." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tErstelle ein Secret basierend auf einer Datei, einem Ordner oder einem " +"gegebenen Wert.\n" +"\n" +"\t\tEin einzelnes Secret kann eins oder mehr Key/Value-Paare beinhalten.\n" +"\n" +"\t\tWenn man ein Secret von einer Datei erstellt, wird der Key standard" +"mäßig der Name der Datei, und der Wert wird\n" +"\t\tstandardmäßig der Dateiinhalt. Wenn der Dateiname ein ungültiger Key ist, " +"kann ein anderer Key angegeben werden.\n" +"\n" +"\t\tWenn man ein Secret von einem Ordner erstellt, wird jede Datei, deren " +"Name ein gültiger Key ist\n" +"\t\tin das Secret aufgenommen. Jegliche Einträge im Ordner, die keine " +"regulären Dateien sind, werden ignoriert (z.B. SubDirectories, \n" +"\t\tSymLinks, Devices, Pipes, usw)." + +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\tErstelle einen ServiceAccount mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tErstelle und starte ein bestimmtes Image, möglicherweise repliziert.\n" +"\n" +"\t\tErstellt ein Deployment oder Job, um den/die erstellten Container zu " +"verwalten." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" +"\n" +"\t\tErstellt einen AutoScaler der die Anzahl der Pods, die im Kubernetes-" +"Cluster laufen, automatisch wählt und anpasst.\n" +"\n" +"\t\tSucht ein Deployment, ReplicaSet oder ReplicationController mit Namen name " +"und erstellt einen AutoScaler, der die Resource als Referenz nimmt.\n" +"\t\tEin AutoScaler kann die Anzahl der im System deployten Pods nach Bedarf " +"erhöhen oder verringern." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tLöscht die Resourcen mit Dateinamen, stdin, resources- und names- oder mit " +"resources- und label-Selektor.\n" +"\n" +"\t\tJSON- und YAML-Formate werden akzeptiert. Nur einer der Parameter darf " +"verwendet werden: Dateiname,\n" +"\t\tresources- und names-, oder resources- und label-Selektor.\n" +"\n" +"\t\tManche Resourcen, zum Beispiel Pods, unterstützen graziöses Löschen. Sie " +"definieren einen Standardzeitraum\n" +"\t\tbevor das Löschen erzwungen wird (grace-period), aber dieser Wert kann " +"überschrieben werden mit\n" +"\t\tder --grace-period Option, oder mit --now, das die grace-period auf 1 " +"setzt. " +"Da diese Resourcen\n" +"\t\thäufig Einheiten im Cluster sind, kann das Löschen nicht immer direkt " +"bestätigt werden. Wenn der Knoten\n" +"\t\tauf dem der Pod läuft nicht verfügbar ist, oder den API Server nicht " +"erreichen kann, kann das Löschen bedeutend länger dauern\n" +"\t\tals die grace-period. Um das Löschen zu erzwingen, muss eine grace-period " +"von 0 übergeben werden\n" +"\t\tund die --force Option gesetzt sein.\n" +"\n" +"\t\tWICHTIG: Ein erzwungenes Löschen wartet nicht auf die Bestätigung, dass " +"der Prozess\n" +"\t\tbeendet wurde, was den Prozess am Leben erhalten kann, bis der Knoten " +"die Löschung erkennt\n" +"\t\tund das graziöse Löschen beendet. Wenn Prozesse Shared-Storage oder eine " +"Remote-API verwenden und\n" +"\t\tden Namen des Pods brauchen, um sich selbst zu identifizieren, kann das " +"erzwungene Löschen dazu führen, dass\n" +"\t\tmehrere Prozesse auf der gleichen Maschine die gleiche Identität verwenden, " +"was zu\n" +"\t\tDatenkorruption oder Inkonsistenz führen kann. Erzwinge nur ein " +"Löschen, wenn sichergestellt ist, dass der Pod\n" +"\t\tgelöscht ist, oder wenn die Anwendung mehrere gleichzeitig laufende " +"Kopien verarbeiten kann.\n" +"\t\tAußerdem kann es passieren, dass der Scheduler neue Pods auf dem Knoten " +"plaziert, bevor der Knoten\n" +"\t\tdie Resourcen freigegeben hat, sodass diese Pods direkt entfernt werden.\n" +"\n" +"\t\tBerücksichtige außerdem, dass der Delete-Befehl KEINE versionen prüft, " +"sodass, wenn jemand\n" +"\t\tein Update einer Resource gleichzeitig mit Deinem delete anstößt, dessen " +"Update\n" +"\t\tmit dem Rest der Resource entfernt wird." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tVeraltet: Fahre eine Resource mit Namen oder Dateinamen graziös heruter.\n" +"\n" +"\t\tDer Stop-Befehl ist veraltet und alle Funktioneren werden mit dem Delete-" +"Befehl abgedeckt.\n" +"\t\tSiehe 'kubectl delete --help' für mehr Details.\n" +"\n" +"\t\tVersucht eine Resource, die graziöses Löschen unterstützt, herunterzufahren " +"und zu löschen.\n" +"\t\tWenn die Resource skaliert werden kann, wird sie vor dem Löschen auf 0 " +"skaliert." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\tZeigt die Resourcennutzung (CPU/Memory/Storage) von Knoten.\n" +"\n" +"\t\tDer top-node-Befehl erlaubt es, die Resourcennutzung von Knoten zu " +"betrachten." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\tZeigt die Resourcennutzung (CPU/Memory/Storage) von Pods.\n" +"\n" +"\t\tDer 'top pod'-Befehl erlaubt es, die Resourcennutzung von Pods zu " +"betrachten.\n" +"\n" +"\t\tAufgrund der Metrik-Pipeline-Verzögerung, können sie für ein paar Minuten " +"nicht verfügbar sein,\n" +"\t\tnach der Pod-Erstellung." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" +"\n" +"\t\tZeige Resourcennutzung (CPU/Memory/Storage).\n" +"\n" +"\t\tDer top-Befehl erlaubt es, die Resourcennutzung von Knoten oder Pods zu " +"betrachten.\n" +"\n" +"\t\tDieser Befehl benötigt eine korrekt konfigurierte und funktionierende " +"Heapster-Installation auf dem Server. " + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\tLeere Knoten, um eine Wartung vorzubereiten.\n" +"\n" +"\t\tDer gegebene Knoten wird als unschedulable markiert, um die Zuordnung von " +"neuen Pods zu verhindern.\n" +"\t\t'drain' entfernt den Pod, falls der API-Server die Entfernung unterstützt\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Wenn nicht, wird ein " +"normales DELETE verwendet,\n" +"\t\tum die Pods zu löschen.\n" +"\t\t'drain' entfernt oder löscht alle Pods mit der Ausnahme von Mirror-Pods (" +"welche vom API Server nicht gelöscht werden können)\n" +"\t\tWenn DaemonSet-verwaltete Pods existieren, wird 'drain' " +"nicht fortgesetzt\n" +"\t\tohne die --ignore-daemonsets Option, und es wird in keinem Fall\n" +"\t\tDaemonSet-verwaltete Pods löschen, weil diese Pods direkt ersetzt würden " +"durch den\n" +"\t\tDaemonSet-Controller, der unschedulable Markierungen ignoriert. Wenn es " +"irgendwelche\n" +"\t\tPods gibt, die weder Mirror-Pods sind, noch von einem ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet oder Job verwaltet werden, wird drain " +"keine Pods löschen, außer die\n" +"\t\t--force Option ist gesetzt. --force lässt das Löschen selbst zu, wenn die " +"verwaltende Resource von einem\n" +"\t\toder mehreren Pods fehlt.\n" +"\n" +"\t\t'drain' wartet auf eine graziöse Löschung. Man sollte auf der Maschine " +"nichts tun, während\n" +"\t\tder Befehl läuft.\n" +"\n" +"\t\tWenn der Knoten wieder bereit ist die Arbeit aufzunehmen, benutze kubectl " +"uncordon,\n" +"\t\twas den Knoten als schedulable markiert.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\tBearbeite eine Resource mit dem Standardeditor.\n" +"\n" +"\t\tDer edit-Befehl erlaubt es jede API Resource direkt zu bearbeiten, wenn " +"sie mit den\n" +"\t\tCommand-Line-Tools erreichbar ist. Er öffnet den Editor, der in der " +"KUBE_EDITOR oder EDITOR\n" +"\t\tUmgebunsvariable festgelegt ist, oder 'vi' auf Linux und " +"'notepad' auf Windows.\n" +"\t\tEs ist möglich mehrere Objekte zu bearbeiten, aber die Änderungen werden " +"nacheinander angewendet. Der Befehl\n" +"\t\takzeptiert Dateinamen und Command-Line-Parameter, aber die verwendeten " +"Dateien müssen\n" +"\t\tvorab gespeicherte Versionen von Resourcen sein.\n" +"\n" +"\t\tDie Bearbeitung verwendet die API Version, die genutzt wurde, um die " +"Resource zu lesen.\n" +"\t\tUm eine spezifische API Version zu verwenden, muss die vollständige " +"Resource, Version und Group angegeben werden.\n" +"\n" +"\t\tDas Standardformat ist YAML. Um mit JSON zu arbeiten, setze \"-o json\".\n" +"\n" +"\t\tDie Option --windows-line-endings kann benutzt werden, um Windows Zeilen-" +"umbrüche zu verwenden,\n" +"\t\tansonsten wird der Standard des Betriebssystems verwendet.\n" +"\n" +"\t\tFalls beim Update ein Fehler auftritt, wird eine temporäre Datei auf der " +"Festplatte angelegt,\n" +"\t\tdie die nicht verarbeiteten Änderungen enthält. Der häufigste Fehler beim " +"Bearbeiten einer Resource\n" +"\t\tist ein anderer Editor, der die Resource auf dem Server ändert. Wenn das " +"auftritt, muss man\n" +"\t\tseine Änderungen auf die neue Version anwenden oder seine temporäre\n" +"\t\tgespeicherte Kopie mit der neuesten Resourcenversion aktualisieren." + +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\tMarkiere Knoten als schedulable." + +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\tMarkiere Knoten als unschedulable." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" +msgstr "" +"\n" +"\t\tGibt den Shell-Completion-Code für die angegebene Shell aus (bash oder zsh).\n" +"\t\tDer Shell-Code muss für eine interaktive Vervollständigung von kubectl \n" +"\t\tausgewertet werden. Das ist möglich, indem man\n" +"\t\tdie .bash_profile Datei sourcet.\n" +"\n" +"\t\tHinweis: Dies setzt das Bash-Completion-Framework voraus, das auf dem Mac " +"nicht standardmäßig installiert ist. \n" +"\t\tEs kann mit homebrew installiert werden:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tSobald es installiert ist, muss bash_completion ausgewertet werden. Dies " +"wird erreicht, indem man\n" +"\t\tdie folgende Zeile zur .bash_profile-Datei hinzufügt\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tHinweis für zsh Nutzer: [1] zsh completions werden nur in Versionen " +"von zsh >= 5.2 unterstützt" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\tFühre ein Rolling-Update des gegebenen ReplicationControllers aus.\n" +"\n" +"\t\tErsetzt den gegebenen ReplicationController mit einem neuen Replication-" +"Controller, indem die neue PodTampleta Pod für Pod\n" +"\t\tangewendet wird. Die new-controller.json muss den gleichen Namespace wie\n" +"\t\tder aktuelle ReplicationController besitzen und mindestens ein " +"gemeinsames Label im ReplicaSelector überschreiben.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tErsetze eine Resource mit Dateinamen oder stdin.\n" +"\n" +"\t\tJSON- and YAML-Formate werden akzeptiert. Wenn eine existierende Resource " +"ersetzt wird,\n" +"\t\tmuss die vollständige spSpecec mitgegeben werden. Diese kann hiermit " +"ausgelesen werden\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tBitte konsultiere https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html um zu erfahren, ob ein Feld verändert werden darf." + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tSetze eine neue Größe für ein Deployment, ReplicaSet, Replication-" +"Contoller oder Job.\n" +"\n" +"\t\tScale erlaubt es Nutzern eine oder mehr Voraussetzungen für die Aktion " +"festzulegen.\n" +"\n" +"\t\tWenn --current-replicas oder --resource-version gegeben ist, wird " +"es validiert, bevor\n" +"\t\tscale versucht wird, und es wird garantiert, dass die Voraussetzungen " +"erfüllt sind, wenn\n" +"\t\tscale zum Server geschickt wird." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tSetze die aktuelle Annotation Last-Applied-Configuration auf den Inhalt " +"der Datei.\n" +"\t\tDas bedeutet, dass Last-Applied-Configuration aktualisiert wird, als ob " +"'kubectl apply -f ' ausgeführt wurde,\n" +"\t\tohne andere Teile des Objekts zu aktualisieren." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tProxy alle Teile der Kubernetes-API und sonst nichts:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tProxy nur bestimmte Teile der Kubernetes-API und einige statische Dateien:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tDer Befehl oben lässt dich 'curl localhost:8001/api/v1/pods' aufrufen.\n" +"\n" +"\t\tProxy alle Teile der Kubernetes-API auf einem anderen root:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tDer Befehl oben lässt dich 'curl localhost:8001/custom/api/v1/pods' " +"aufrufen" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tAktualisiere Felder einer Resource mit einem Strategic-Merge-Patch\n" +"\n" +"\t\tJSON- und YAML-Formate werden akzeptiert.\n" +"\n" +"\t\tBitte konsultiere https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html um zu erfahren, ob ein Feld mutable ist." + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." +msgstr "" + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." +msgstr "" + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" +"\n" +"\t # Erstelle ein neues TLS Secret tl-secret mit dem gegebenen Schlüsselpaar:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # Erstelle einen neuen Namespace my-namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Erstelle ein neues Secret my-secret mit einem Key für jede Datei " +"im Ordner bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Erstelle ein neues Secret my-secret mit den gegebenen Keys statt " +"der Namen auf der Festplatte\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Erstelle ein neues Scret my-secret mit key1=supersecret und " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Erstelle einen neuen ServiceAccount my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Erstelle einen neuen ExternalName-Service my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tErstelle einen ExternalName-Service mit den gegebenen Namen.\n" +"\n" +"\tExternalName service referenziert eine externe DNS Adresse statt\n" +"\teines pods, was Anwendungsautoren erlaubt, einen Service zu referenzieren,\n" +"\tder abseits der Platform, auf anderen Clustern oder lokal exisiert." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp hilft bei jedem Befehl in der Anwendung.\n" +"\tGib einfach kubectl help [path to command] für alle Details ein." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # Erstelle einen neuen LoadBalancer-Service my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # Erstelle einen neuen ClusterIP-Service my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Erstelle einen neuen ClusterIP-Service my-cs (im headless-Modus)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # Erstelle ein neues Deployment my-dep, dass das busybox-Image " +"nutzt.\n" +" kubectl create deployment my-dep --image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # Erstelle einen neuen NodePort-Service my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" +"\n" +" # Schreibe den aktuellen Cluster-Zustand auf stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Schreibe aktuellen Cluster-Zustand in /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Schreibe alle Namespaces auf stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Schreibe eine Menge an Namespaces in /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" Erstelle einen LoadBalancer-Service mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" Erstelle einen ClusterIP-Service mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" Erstelle ein Deployment mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" Erstelle einen NodePort-Service mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" +"\n" +" Zeigt Adressen des Master und von Services mit Label kubernetes.io/" +"cluster-service=true\n" +" Für das weitere Debugging und die Diagnose von Clusterproblemen nutze " +"'kubectl cluster-info dump'." + +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." +msgstr "" +"Eine komma-separierte Menge von Quota-Scopes, die zu jedem Object passen " +"muss, dass von der Quota betroffen ist." + +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" +"Eine komma-separierte Menge von resource=quantity Paaren, die ein hartes " +"Limit definieren." + +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" +"Ein Label-Selektor, der für das Budget benutzt werden kann. Nur gleichheits-" +"basierte Auswahlkriterien werden unterstützt." + +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" +"Ein Label-Selektor, der für den Service benutzt werden kann. Nur gleichheits-" +"basierte Auswahlkriterien werden unterstützt. Wenn er leer ist (standard), wird " +"der Selektor vom ReplicationController oder ReplicaSet abgeleitet" + +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "Ein Schedule im Cron Format, dass der Job nutzen soll." + +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" +"Zusätzliche, externe IP Adressen (die nicht von Kubernetes verwaltet werden), " +"die der Service akzeptieren soll. Wenn diese IP zu einem Knoten gerouted wird, " +"kann der Service über die IP angesprochen werden, zusätzlich zu seiner " +"generierten Service-IP." + +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" + +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "Wende eine Konfiguration auf eine Resource über den Dateinamen oder " +"stdin an" + +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "Genehmige eine Certificate-Signing-Request" + +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" +"Weise Deine eigene ClusterIP zu oder setze sie auf 'None' für einen 'headless'-" +"Service (kein LoadBalancing)." + +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Weise einem laufenden Container zu" + +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "Auto-skaliere ein Deployment, ReplicaSet oder ReplicationController" + +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." +msgstr "" +"ClusterIP, die dem Service zugewiesen werden soll. Freilassen, für " +"automatische Zuweisung oder auf 'None' setzen für einen headless-Service." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRole, die das ClusterRoleBinding referenzieren soll" + +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "ClusterRole, die das RoleBinding referenzieren soll" + +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" +msgstr "" +"Name des Containers dessen Image aktualisiert wird. Nur relevant, wenn " +"--image angegeben ist, sonst ignoriert. Verpflichtend, wenn --image auf einem " +"Multi-Container-Pod verwendet wird" + +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "Konvertiere Config-Dateien zwischen verschiedenen API Versionen" + +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "Kopiere Dateien und Ordner aus/in Container(n)." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "Erstelle ein ClusterRoleBinding für eine bestimmte ClusterRole" + +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "Erstelle einen LoadBalancer-Service." + +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "Erstelle einen NodePort-Service." + +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "Erstelle ein RoleBinding für eine bestimmte Role oder ClusterRole" + +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "Erstelle ein TLS-Secret" + +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "Erstelle einen ClusterIP-Service" + +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "Erstelle eine ConfigMap von einer Datei, einem Ordner oder einem " +"festen Wert" + +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "Erstelle ein Deployment mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "Erstelle einen Namespace mit dem gegebenen Namen" + +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "Erstelle ein Pod-Disruption-Budget mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "Erstelle eine Quota mit dem gegebenen Namen." + +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "Erstelle eine Resource von einer Datei oder stdin" + +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "Erstelle ein Secret für die Benutzung mit einer Docker-Registry" + +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "Erstelle ein Secret von einer lokalen Datei, einem Ordner oder einem " +"festen Wert" + +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "Erstelle ein Secret mit dem angegebenen Sub-Befehl" + +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "Erstelle einen ServiceAccount mit dem gegebenen Namen" + +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "Erstelle einen Servuce mit dem angegebenen Sub-Befehl" + +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Erstelle einen ExternalName-Service." + +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "Lösche Resourcen von einer Datei, stdin, resources- und names- oder mit " +"resources- und label-Selektor" + +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "Lösche das angegebene Cluster aus der kubeconfig" + +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "Lösche den angegebenen Kontext aus der kubeconfig" + +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "Lehne eine Certificate-Signing-Request ab" + +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Veraltet: Graziöses herunterfahren einer Resource über den Namen " +"oder Dateinamen" + +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "Beschreibe einen oder mehrere Kontexte" + +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Zeige Resourcennutzung (CPU/Memory) von Knoten" + +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Zeige Resourcennutzung (CPU/Memory) von Pods" + +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "Zeige Resourcennutzung (CPU/Memory)." + +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "Zeige Cluster-Info" + +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "Zeige Cluster, die in der kubeconfig definiert sind" + +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "Zeige vereinte kubeconfig-Einstellungen oder die angegebene kubeconfig-" +"Datei" + +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "Zeige eine oder mehrere Resourcen" + +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "Zeige den aktuellen Kontext" + +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "Dokumentation einer Resource" + +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Leere Knoten, um eine Wartung vorzubereiten" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Zeige viele relevante Informationen für Debugging und Diagnose" + +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "Bearbeite eine Resource auf dem Server" + +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "E-Mail für Docker-Registry" + +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "Führe einen Befehl im Container aus" + +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" +"Explizite Vorgabe, wann Container-Images gepullt werden. Verpflichtend, wenn " +"--image ist gleich dem aktuellen Image ist - sonst ignoriert." + +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Leite einen oder mehrere lokale Ports an einen Pod weiter" + +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Hilfe für jeden Befehl" + +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" +"IP, die dem Load-Balancer zugewiesen wird. Falls leer, wird eine temporäre IP " +"erstellt und verwendet (Cloud-Provider spezifisch)" + +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" +msgstr "" + +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "Verwalte ein Deployment-Rollout" + +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "Markiere Knoten als schedulable" + +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "Markiere Knoten als unschedulable" + +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "Markiere die gegebene Resource als pausiert" + +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "Verändere Certificate-Resources" + +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "Verändere kubeconfig Dateien" + +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" +"Name oder Nummer des Ports in dem Container, zu dem der Service Daten leiten " +"soll. Optional." + +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" +"Zeige nur Logs nach einem bestimmten Datum (RFC3339) an. Zeigt standardmäßig " +"alle logs. Es kann entweder since-time oder since benutzt werden." + +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "Zeige Shell-Completion-Code für die angegebene Shell (bash oder zsh)" + +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Passwort für die Authentifizierung bei der Docker-Registry" + +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Pfad des Public-Key-Zertifikats im PEM-Format." + +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Pfad zum Private-Key, der zum gegebenen Zertifikat passt." + +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "Führe ein Rolling-Update des gegebenen ReplicationControllers aus" + +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." +msgstr "" +"Vorbedingung für Resource-Version. Verlangt, dass die aktuelle Resource-" +"Version diesen Wert erfüllt, um zu skalieren." + +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "Schreibt die Client- und Server-Versionsinformation" + +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "Schreibt die Liste von Optionen, die alle Befehle erben" + +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "Schreibt die Logs für einen Container in einem Pod" + +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "Ersetze eine Resource von einem Dateinamen oder stdin" + +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "Setze eine pausierte Resource fort" + +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "Role, die dieses RoleBinding referenzieren soll" + +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "Starte ein bestimmtes Image auf dem Cluster" + +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "Starte einen Proxy zum Kubernetes-API-Server" + +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "" + +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" +"Setze eine neue Größe für ein Deployment, ReplicaSet, ReplicationController " +"oder Job" + +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "Setze bestimmte Features auf Objekten" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" +"Setze die Annotation Last-Applied-Configuration auf einem Live-Objekt auf den " +"Inhalt einer Datei." + +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "Setze den Selektor auf einer Resource" + +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "Setze einen Cluster-Eintrag in der kubeconfig" + +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "Setze einen Kontext-Eintrag in der kubeconfig" + +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "Setze einen User-Eintrag in der kubeconfig" + +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "Setze einen einzelnen Value in einer kubeconfig-Datei" + +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "Setze den aktuellen Kontext in einer kubeconfig-Datei" + +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "Zeige Details zu einer bestimmten Resource oder Gruppe von " +"Resourcen" + +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "Zeige den Status des Rollout" + +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Synonym für --target-port" + +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" +"Nehme einen Replication Controller, Service, Deployment oder Pod und biete " +"ihn als neuen Kubernetes-Service an" + +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "Das Image, dass auf dem Container gestartet werden soll." + +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" +"Die Image-Pull-Policy für den Container. Wenn leer, wird der Wert nicht vom " +"Client gesetzt, sondern standardmäßig vom Server." + +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "" +"The minimum number or percentage of available pods this budget requires." +msgstr "" +"Die minimale Anzahl oder Prozentzahl von verfügbaren Pods, die das Budget " +"voraussetzt." + +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "Der Name des neu erstellten Objekts." + +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" +"Der Name des neu erstellten Objekts. Falls nicht angegeben, wird der Name " +"der Input-Resource verwendet." + +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" +"Der Name des zu verwendenden API-Generators. Siehe http://kubernetes.io/docs/" +"user-guide/kubectl-conventions/#generators für eine Übersicht." + +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" +"Der Name des zu verwendenden API-Generators. Zur Zeit gibt es nur einen " +"Generator." + +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." +msgstr "" +"Der Name des zu verwendenden API-Generators. Es gibt zwei Generatoren: " +"'service/v1' und 'service/v2'. Der einzige Unterschied ist, dass der " +"Serviceport in v1 'default' heißt, während er in v2 unbenannt bleibt. " +"Standard ist 'service/v2'." + +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" +"Der Name des zu verwendenden Generators, um einen Service zu erstellen. Wird " +"nur benutzt, wenn --expose true ist" + +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "Das Netzwerkprotokoll, für den zu erstellenden Service. Standard ist " +"'TCP'." + +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" +"Der Port auf den der Service hören soll. Wird von der angebotenen Resource " +"kopiert, falls nicht angegeben" + +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" +"Der Port, den der Container anbietet. Wenn --expose true ist, ist es auch " +"der Port, den der zu erstellende Service verwendet" + +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" + +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "Der Typ des zu erstellenden Secrets" + +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" +"Typ für diesen Service: ClusterIP, NodePort oder LoadBalancer. Standard ist " +"'ClusterIP'." + +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "Widerrufe ein vorheriges Rollout" + +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "" + +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "Aktualisiere Felder einer Resource mit einem Strategic-Merge-Patch" + +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "Aktualisiere das Image einer Pod-Template" + +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "Aktualisiere Resourcen requests/limits auf Objekten mit Pod-Templates" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "Aktualisiere die Annotationen auf einer Resource" + +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "Aktualisiere die Labels auf einer Resource" + +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "Aktualisiere die Taints auf einem oder mehreren Knoten" + +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Username für Authentifizierung bei der Docker-Registry" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "Zeige die aktuelle Annotation Last-Applied-Configuration einer Resource " +"/ eines Object" + +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "Zeige rollout-Verlauf" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "" + +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "kubectl kontrolliert den Kubernetes-Cluster-Manager" +`) + +func translationsKubectlDe_deLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlDe_deLc_messagesK8sPo, nil +} + +func translationsKubectlDe_deLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlDe_deLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/de_DE/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlDefaultLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xeb\x00\x00\x00\x1c\x00\x00\x00t\a\x00\x009\x01\x00\x00\xcc\x0e\x00\x00\x00\x00\x00\x00\xb0\x13\x00\x00\xdc\x00\x00\x00\xb1\x13\x00\x00\xb6\x00\x00\x00\x8e\x14\x00\x00\v\x02\x00\x00E\x15\x00\x00\x1f\x01\x00\x00Q\x17\x00\x00z\x00\x00\x00q\x18\x00\x00_\x02\x00\x00\xec\x18\x00\x00\u007f\x01\x00\x00L\x1b\x00\x00\x8f\x01\x00\x00\xcc\x1c\x00\x00k\x01\x00\x00\\\x1e\x00\x00k\x01\x00\x00\xc8\x1f\x00\x00>\x01\x00\x004!\x00\x00\x03\x02\x00\x00s\"\x00\x00o\x01\x00\x00w$\x00\x00H\x05\x00\x00\xe7%\x00\x00g\x02\x00\x000+\x00\x00\x1b\x02\x00\x00\x98-\x00\x00q\x01\x00\x00\xb4/\x00\x00\xa8\x01\x00\x00&1\x00\x00\xd4\x01\x00\x00\xcf2\x00\x00\x02\x02\x00\x00\xa44\x00\x00\xb4\x00\x00\x00\xa76\x00\x00\xb7\x02\x00\x00\\7\x00\x00\x92\x03\x00\x00\x14:\x00\x00\xbf\x01\x00\x00\xa7=\x00\x00=\x00\x00\x00g?\x00\x00;\x00\x00\x00\xa5?\x00\x00\xcd\x02\x00\x00\xe1?\x00\x00<\x00\x00\x00\xafB\x00\x00P\x00\x00\x00\xecB\x00\x00S\x00\x00\x00=C\x00\x00<\x00\x00\x00\x91C\x00\x00\xac\x01\x00\x00\xceC\x00\x00\x13\x03\x00\x00{E\x00\x00\xea\x01\x00\x00\x8fH\x00\x00\xfa\x01\x00\x00zJ\x00\x00\xda\x01\x00\x00uL\x00\x00c\x01\x00\x00PN\x00\x00T\x01\x00\x00\xb4O\x00\x00\xba\x06\x00\x00\tQ\x00\x00\xf9\x01\x00\x00\xc4W\x00\x00\xe0\x02\x00\x00\xbeY\x00\x00\x02\x03\x00\x00\x9f\\\x00\x00\xfb\x00\x00\x00\xa2_\x00\x00\xa5\x01\x00\x00\x9e`\x00\x00\xb4\x01\x00\x00Db\x00\x00\x18\x00\x00\x00\xf9c\x00\x00<\x00\x00\x00\x12d\x00\x00=\x00\x00\x00Od\x00\x00\xc6\x00\x00\x00\x8dd\x00\x00g\x02\x00\x00Te\x00\x00.\x00\x00\x00\xbcg\x00\x001\x03\x00\x00\xebg\x00\x00g\x00\x00\x00\x1dk\x00\x00Q\x00\x00\x00\x85k\x00\x00R\x00\x00\x00\xd7k\x00\x00\"\x00\x00\x00*l\x00\x00X\x02\x00\x00Ml\x00\x004\x00\x00\x00\xa6n\x00\x00}\x00\x00\x00\xdbn\x00\x00k\x01\x00\x00Yo\x00\x00\x81\a\x00\x00\xc5p\x00\x00f\x01\x00\x00Gx\x00\x00\x85\x00\x00\x00\xaey\x00\x00\xea\x00\x00\x004z\x00\x00\xd9\x00\x00\x00\x1f{\x00\x00\n\x05\x00\x00\xf9{\x00\x00\x10\x05\x00\x00\x04\x81\x00\x00\x1c\x00\x00\x00\x15\x86\x00\x00\x1e\x00\x00\x002\x86\x00\x00\x98\x02\x00\x00Q\x86\x00\x00\xbc\x01\x00\x00\xea\x88\x00\x00\x9c\x01\x00\x00\xa7\x8a\x00\x00q\x01\x00\x00D\x8c\x00\x00\x05\x01\x00\x00\xb6\x8d\x00\x00\xdf\x01\x00\x00\xbc\x8e\x00\x00\x1c\x01\x00\x00\x9c\x90\x00\x00\xc1\x01\x00\x00\xb9\x91\x00\x00\x1b\x02\x00\x00{\x93\x00\x00\xc0\x00\x00\x00\x97\x95\x00\x00\xd5\x02\x00\x00X\x96\x00\x00\x9d\x00\x00\x00.\x99\x00\x00X\x00\x00\x00\u0319\x00\x00%\x02\x00\x00%\x9a\x00\x00o\x00\x00\x00K\x9c\x00\x00u\x00\x00\x00\xbb\x9c\x00\x00\x01\x01\x00\x001\x9d\x00\x00v\x00\x00\x003\x9e\x00\x00t\x00\x00\x00\xaa\x9e\x00\x00\xef\x00\x00\x00\x1f\x9f\x00\x00}\x00\x00\x00\x0f\xa0\x00\x00j\x00\x00\x00\x8d\xa0\x00\x00\xc4\x01\x00\x00\xf8\xa0\x00\x00\xf7\x03\x00\x00\xbd\xa2\x00\x00;\x00\x00\x00\xb5\xa6\x00\x008\x00\x00\x00\xf1\xa6\x00\x001\x00\x00\x00*\xa7\x00\x007\x00\x00\x00\\\xa7\x00\x00u\x02\x00\x00\x94\xa7\x00\x00\xb0\x00\x00\x00\n\xaa\x00\x00[\x00\x00\x00\xbb\xaa\x00\x00J\x00\x00\x00\x17\xab\x00\x00a\x00\x00\x00b\xab\x00\x00\xbd\x00\x00\x00\u012b\x00\x009\x00\x00\x00\x82\xac\x00\x00\xc5\x00\x00\x00\xbc\xac\x00\x00\xae\x00\x00\x00\x82\xad\x00\x00\xd6\x00\x00\x001\xae\x00\x008\x00\x00\x00\b\xaf\x00\x00%\x00\x00\x00A\xaf\x00\x00W\x00\x00\x00g\xaf\x00\x00\x1d\x00\x00\x00\xbf\xaf\x00\x00=\x00\x00\x00\u076f\x00\x00u\x00\x00\x00\x1b\xb0\x00\x004\x00\x00\x00\x91\xb0\x00\x00-\x00\x00\x00\u01b0\x00\x00\xa3\x00\x00\x00\xf4\xb0\x00\x003\x00\x00\x00\x98\xb1\x00\x002\x00\x00\x00\u0331\x00\x008\x00\x00\x00\xff\xb1\x00\x00\x1e\x00\x00\x008\xb2\x00\x00\x1a\x00\x00\x00W\xb2\x00\x009\x00\x00\x00r\xb2\x00\x00\x13\x00\x00\x00\xac\xb2\x00\x00\x1b\x00\x00\x00\xc0\xb2\x00\x00@\x00\x00\x00\u0732\x00\x00,\x00\x00\x00\x1d\xb3\x00\x00*\x00\x00\x00J\xb3\x00\x007\x00\x00\x00u\xb3\x00\x00'\x00\x00\x00\xad\xb3\x00\x00&\x00\x00\x00\u0573\x00\x00.\x00\x00\x00\xfc\xb3\x00\x00=\x00\x00\x00+\xb4\x00\x00*\x00\x00\x00i\xb4\x00\x000\x00\x00\x00\x94\xb4\x00\x00,\x00\x00\x00\u0174\x00\x00\x1f\x00\x00\x00\xf2\xb4\x00\x00]\x00\x00\x00\x12\xb5\x00\x000\x00\x00\x00p\xb5\x00\x000\x00\x00\x00\xa1\xb5\x00\x00\"\x00\x00\x00\u04b5\x00\x00?\x00\x00\x00\xf5\xb5\x00\x00\x1d\x00\x00\x005\xb6\x00\x00,\x00\x00\x00S\xb6\x00\x00+\x00\x00\x00\x80\xb6\x00\x00$\x00\x00\x00\xac\xb6\x00\x00\x14\x00\x00\x00\u0476\x00\x00*\x00\x00\x00\xe6\xb6\x00\x00A\x00\x00\x00\x11\xb7\x00\x00\x1d\x00\x00\x00S\xb7\x00\x00\x1c\x00\x00\x00q\xb7\x00\x00\x1a\x00\x00\x00\x8e\xb7\x00\x00)\x00\x00\x00\xa9\xb7\x00\x006\x00\x00\x00\u04f7\x00\x00\x1d\x00\x00\x00\n\xb8\x00\x00\x19\x00\x00\x00(\xb8\x00\x00 \x00\x00\x00B\xb8\x00\x00v\x00\x00\x00c\xb8\x00\x00(\x00\x00\x00\u06b8\x00\x00\x16\x00\x00\x00\x03\xb9\x00\x00p\x00\x00\x00\x1a\xb9\x00\x00`\x00\x00\x00\x8b\xb9\x00\x00\x9b\x00\x00\x00\xec\xb9\x00\x00\x97\x00\x00\x00\x88\xba\x00\x00\xa8\x00\x00\x00 \xbb\x00\x00\x1b\x00\x00\x00\u027b\x00\x00\x18\x00\x00\x00\xe5\xbb\x00\x00\x1a\x00\x00\x00\xfe\xbb\x00\x00$\x00\x00\x00\x19\xbc\x00\x00\x1d\x00\x00\x00>\xbc\x00\x00\x17\x00\x00\x00\\\xbc\x00\x00a\x00\x00\x00t\xbc\x00\x00s\x00\x00\x00\u05bc\x00\x00B\x00\x00\x00J\xbd\x00\x00Y\x00\x00\x00\x8d\xbd\x00\x00+\x00\x00\x00\xe7\xbd\x00\x00+\x00\x00\x00\x13\xbe\x00\x006\x00\x00\x00?\xbe\x00\x00;\x00\x00\x00v\xbe\x00\x00q\x00\x00\x00\xb2\xbe\x00\x00/\x00\x00\x00$\xbf\x00\x001\x00\x00\x00T\xbf\x00\x00'\x00\x00\x00\x86\xbf\x00\x00'\x00\x00\x00\xae\xbf\x00\x00\x18\x00\x00\x00\u05bf\x00\x00&\x00\x00\x00\xef\xbf\x00\x00%\x00\x00\x00\x16\xc0\x00\x00(\x00\x00\x00<\xc0\x00\x00#\x00\x00\x00e\xc0\x00\x00K\x00\x00\x00\x89\xc0\x00\x00 \x00\x00\x00\xd5\xc0\x00\x00_\x00\x00\x00\xf6\xc0\x00\x00\x1e\x00\x00\x00V\xc1\x00\x00\"\x00\x00\x00u\xc1\x00\x00\"\x00\x00\x00\x98\xc1\x00\x00\x1f\x00\x00\x00\xbb\xc1\x00\x00-\x00\x00\x00\xdb\xc1\x00\x00-\x00\x00\x00\t\xc2\x00\x009\x00\x00\x007\xc2\x00\x00\x1e\x00\x00\x00q\xc2\x00\x00\x19\x00\x00\x00\x90\xc2\x00\x00c\x00\x00\x00\xaa\xc2\x00\x00#\x00\x00\x00\x0e\xc3\x00\x00\x82\x00\x00\x002\xc3\x00\x00\x94\x00\x00\x00\xb5\xc3\x00\x00H\x00\x00\x00J\xc4\x00\x00&\x00\x00\x00\x93\xc4\x00\x00e\x00\x00\x00\xba\xc4\x00\x00z\x00\x00\x00 \xc5\x00\x00J\x00\x00\x00\x9b\xc5\x00\x00\xe5\x00\x00\x00\xe6\xc5\x00\x00W\x00\x00\x00\xcc\xc6\x00\x00E\x00\x00\x00$\xc7\x00\x00a\x00\x00\x00j\xc7\x00\x00v\x00\x00\x00\xcc\xc7\x00\x00\xcb\x00\x00\x00C\xc8\x00\x00\xcf\x00\x00\x00\x0f\xc9\x00\x00\x1e\x01\x00\x00\xdf\xc9\x00\x00\x1c\x00\x00\x00\xfe\xca\x00\x00T\x00\x00\x00\x1b\xcb\x00\x00\x17\x00\x00\x00p\xcb\x00\x00/\x00\x00\x00\x88\xcb\x00\x009\x00\x00\x00\xb8\xcb\x00\x00\x1e\x00\x00\x00\xf2\xcb\x00\x00=\x00\x00\x00\x11\xcc\x00\x00$\x00\x00\x00O\xcc\x00\x00\x1f\x00\x00\x00t\xcc\x00\x00&\x00\x00\x00\x94\xcc\x00\x00+\x00\x00\x00\xbb\xcc\x00\x00G\x00\x00\x00\xe7\xcc\x00\x00\x14\x00\x00\x00/\xcd\x00\x00r\x00\x00\x00D\xcd\x00\x00\x13\x00\x00\x00\xb7\xcd\x00\x00\x18\x00\x00\x00\xcb\xcd\x00\x00/\x00\x00\x00\xe4\xcd\x00\x00\xb1\x01\x00\x00\x14\xce\x00\x00\xdc\x00\x00\x00\xc6\xcf\x00\x00\xb6\x00\x00\x00\xa3\xd0\x00\x00\v\x02\x00\x00Z\xd1\x00\x00\x1f\x01\x00\x00f\xd3\x00\x00z\x00\x00\x00\x86\xd4\x00\x00_\x02\x00\x00\x01\xd5\x00\x00\u007f\x01\x00\x00a\xd7\x00\x00\x8f\x01\x00\x00\xe1\xd8\x00\x00k\x01\x00\x00q\xda\x00\x00k\x01\x00\x00\xdd\xdb\x00\x00>\x01\x00\x00I\xdd\x00\x00\x03\x02\x00\x00\x88\xde\x00\x00o\x01\x00\x00\x8c\xe0\x00\x00H\x05\x00\x00\xfc\xe1\x00\x00g\x02\x00\x00E\xe7\x00\x00\x1b\x02\x00\x00\xad\xe9\x00\x00q\x01\x00\x00\xc9\xeb\x00\x00\xa8\x01\x00\x00;\xed\x00\x00\xd4\x01\x00\x00\xe4\xee\x00\x00\x02\x02\x00\x00\xb9\xf0\x00\x00\xb4\x00\x00\x00\xbc\xf2\x00\x00\xb7\x02\x00\x00q\xf3\x00\x00\x92\x03\x00\x00)\xf6\x00\x00\xbf\x01\x00\x00\xbc\xf9\x00\x00=\x00\x00\x00|\xfb\x00\x00;\x00\x00\x00\xba\xfb\x00\x00\xcd\x02\x00\x00\xf6\xfb\x00\x00<\x00\x00\x00\xc4\xfe\x00\x00P\x00\x00\x00\x01\xff\x00\x00S\x00\x00\x00R\xff\x00\x00<\x00\x00\x00\xa6\xff\x00\x00\xac\x01\x00\x00\xe3\xff\x00\x00\x13\x03\x00\x00\x90\x01\x01\x00\xea\x01\x00\x00\xa4\x04\x01\x00\xfa\x01\x00\x00\x8f\x06\x01\x00\xda\x01\x00\x00\x8a\b\x01\x00c\x01\x00\x00e\n\x01\x00T\x01\x00\x00\xc9\v\x01\x00\xba\x06\x00\x00\x1e\r\x01\x00\xf9\x01\x00\x00\xd9\x13\x01\x00\xe0\x02\x00\x00\xd3\x15\x01\x00\x02\x03\x00\x00\xb4\x18\x01\x00\xfb\x00\x00\x00\xb7\x1b\x01\x00\xa5\x01\x00\x00\xb3\x1c\x01\x00\xb4\x01\x00\x00Y\x1e\x01\x00\x18\x00\x00\x00\x0e \x01\x00<\x00\x00\x00' \x01\x00=\x00\x00\x00d \x01\x00\xc6\x00\x00\x00\xa2 \x01\x00g\x02\x00\x00i!\x01\x00.\x00\x00\x00\xd1#\x01\x001\x03\x00\x00\x00$\x01\x00g\x00\x00\x002'\x01\x00Q\x00\x00\x00\x9a'\x01\x00R\x00\x00\x00\xec'\x01\x00\"\x00\x00\x00?(\x01\x00X\x02\x00\x00b(\x01\x004\x00\x00\x00\xbb*\x01\x00}\x00\x00\x00\xf0*\x01\x00k\x01\x00\x00n+\x01\x00\x81\a\x00\x00\xda,\x01\x00f\x01\x00\x00\\4\x01\x00\x85\x00\x00\x00\xc35\x01\x00\xea\x00\x00\x00I6\x01\x00\xd9\x00\x00\x0047\x01\x00\n\x05\x00\x00\x0e8\x01\x00\x10\x05\x00\x00\x19=\x01\x00\x1c\x00\x00\x00*B\x01\x00\x1e\x00\x00\x00GB\x01\x00\x98\x02\x00\x00fB\x01\x00\xbc\x01\x00\x00\xffD\x01\x00\x9c\x01\x00\x00\xbcF\x01\x00q\x01\x00\x00YH\x01\x00\x05\x01\x00\x00\xcbI\x01\x00\xdf\x01\x00\x00\xd1J\x01\x00\x1c\x01\x00\x00\xb1L\x01\x00\xc1\x01\x00\x00\xceM\x01\x00\x1b\x02\x00\x00\x90O\x01\x00\xc0\x00\x00\x00\xacQ\x01\x00\xd5\x02\x00\x00mR\x01\x00\x9d\x00\x00\x00CU\x01\x00X\x00\x00\x00\xe1U\x01\x00%\x02\x00\x00:V\x01\x00o\x00\x00\x00`X\x01\x00u\x00\x00\x00\xd0X\x01\x00\x01\x01\x00\x00FY\x01\x00v\x00\x00\x00HZ\x01\x00t\x00\x00\x00\xbfZ\x01\x00\xef\x00\x00\x004[\x01\x00}\x00\x00\x00$\\\x01\x00j\x00\x00\x00\xa2\\\x01\x00\xc4\x01\x00\x00\r]\x01\x00\xf7\x03\x00\x00\xd2^\x01\x00;\x00\x00\x00\xcab\x01\x008\x00\x00\x00\x06c\x01\x001\x00\x00\x00?c\x01\x007\x00\x00\x00qc\x01\x00u\x02\x00\x00\xa9c\x01\x00\xb0\x00\x00\x00\x1ff\x01\x00[\x00\x00\x00\xd0f\x01\x00J\x00\x00\x00,g\x01\x00a\x00\x00\x00wg\x01\x00\xbd\x00\x00\x00\xd9g\x01\x009\x00\x00\x00\x97h\x01\x00\xc5\x00\x00\x00\xd1h\x01\x00\xae\x00\x00\x00\x97i\x01\x00\xd6\x00\x00\x00Fj\x01\x008\x00\x00\x00\x1dk\x01\x00%\x00\x00\x00Vk\x01\x00W\x00\x00\x00|k\x01\x00\x1d\x00\x00\x00\xd4k\x01\x00=\x00\x00\x00\xf2k\x01\x00u\x00\x00\x000l\x01\x004\x00\x00\x00\xa6l\x01\x00-\x00\x00\x00\xdbl\x01\x00\xa3\x00\x00\x00\tm\x01\x003\x00\x00\x00\xadm\x01\x002\x00\x00\x00\xe1m\x01\x008\x00\x00\x00\x14n\x01\x00\x1e\x00\x00\x00Mn\x01\x00\x1a\x00\x00\x00ln\x01\x009\x00\x00\x00\x87n\x01\x00\x13\x00\x00\x00\xc1n\x01\x00\x1b\x00\x00\x00\xd5n\x01\x00@\x00\x00\x00\xf1n\x01\x00,\x00\x00\x002o\x01\x00*\x00\x00\x00_o\x01\x007\x00\x00\x00\x8ao\x01\x00'\x00\x00\x00\xc2o\x01\x00&\x00\x00\x00\xeao\x01\x00.\x00\x00\x00\x11p\x01\x00=\x00\x00\x00@p\x01\x00*\x00\x00\x00~p\x01\x000\x00\x00\x00\xa9p\x01\x00,\x00\x00\x00\xdap\x01\x00\x1f\x00\x00\x00\aq\x01\x00]\x00\x00\x00'q\x01\x000\x00\x00\x00\x85q\x01\x000\x00\x00\x00\xb6q\x01\x00\"\x00\x00\x00\xe7q\x01\x00?\x00\x00\x00\nr\x01\x00\x1d\x00\x00\x00Jr\x01\x00,\x00\x00\x00hr\x01\x00+\x00\x00\x00\x95r\x01\x00$\x00\x00\x00\xc1r\x01\x00\x14\x00\x00\x00\xe6r\x01\x00*\x00\x00\x00\xfbr\x01\x00A\x00\x00\x00&s\x01\x00\x1d\x00\x00\x00hs\x01\x00\x1c\x00\x00\x00\x86s\x01\x00\x1a\x00\x00\x00\xa3s\x01\x00)\x00\x00\x00\xbes\x01\x006\x00\x00\x00\xe8s\x01\x00\x1d\x00\x00\x00\x1ft\x01\x00\x19\x00\x00\x00=t\x01\x00 \x00\x00\x00Wt\x01\x00v\x00\x00\x00xt\x01\x00(\x00\x00\x00\xeft\x01\x00\x16\x00\x00\x00\x18u\x01\x00p\x00\x00\x00/u\x01\x00`\x00\x00\x00\xa0u\x01\x00\x9b\x00\x00\x00\x01v\x01\x00\x97\x00\x00\x00\x9dv\x01\x00\xa8\x00\x00\x005w\x01\x00\x1b\x00\x00\x00\xdew\x01\x00\x18\x00\x00\x00\xfaw\x01\x00\x1a\x00\x00\x00\x13x\x01\x00$\x00\x00\x00.x\x01\x00\x1d\x00\x00\x00Sx\x01\x00\x17\x00\x00\x00qx\x01\x00a\x00\x00\x00\x89x\x01\x00s\x00\x00\x00\xebx\x01\x00B\x00\x00\x00_y\x01\x00Y\x00\x00\x00\xa2y\x01\x00+\x00\x00\x00\xfcy\x01\x00+\x00\x00\x00(z\x01\x006\x00\x00\x00Tz\x01\x00;\x00\x00\x00\x8bz\x01\x00q\x00\x00\x00\xc7z\x01\x00/\x00\x00\x009{\x01\x001\x00\x00\x00i{\x01\x00'\x00\x00\x00\x9b{\x01\x00'\x00\x00\x00\xc3{\x01\x00\x18\x00\x00\x00\xeb{\x01\x00&\x00\x00\x00\x04|\x01\x00%\x00\x00\x00+|\x01\x00(\x00\x00\x00Q|\x01\x00#\x00\x00\x00z|\x01\x00K\x00\x00\x00\x9e|\x01\x00 \x00\x00\x00\xea|\x01\x00_\x00\x00\x00\v}\x01\x00\x1e\x00\x00\x00k}\x01\x00\"\x00\x00\x00\x8a}\x01\x00\"\x00\x00\x00\xad}\x01\x00\x1f\x00\x00\x00\xd0}\x01\x00-\x00\x00\x00\xf0}\x01\x00-\x00\x00\x00\x1e~\x01\x009\x00\x00\x00L~\x01\x00\x1e\x00\x00\x00\x86~\x01\x00\x19\x00\x00\x00\xa5~\x01\x00c\x00\x00\x00\xbf~\x01\x00#\x00\x00\x00#\u007f\x01\x00\x82\x00\x00\x00G\u007f\x01\x00\x94\x00\x00\x00\xca\u007f\x01\x00H\x00\x00\x00_\x80\x01\x00&\x00\x00\x00\xa8\x80\x01\x00e\x00\x00\x00\u03c0\x01\x00z\x00\x00\x005\x81\x01\x00J\x00\x00\x00\xb0\x81\x01\x00\xe5\x00\x00\x00\xfb\x81\x01\x00W\x00\x00\x00\xe1\x82\x01\x00E\x00\x00\x009\x83\x01\x00a\x00\x00\x00\u007f\x83\x01\x00v\x00\x00\x00\xe1\x83\x01\x00\xcb\x00\x00\x00X\x84\x01\x00\xcf\x00\x00\x00$\x85\x01\x00\x1e\x01\x00\x00\xf4\x85\x01\x00\x1c\x00\x00\x00\x13\x87\x01\x00T\x00\x00\x000\x87\x01\x00\x17\x00\x00\x00\x85\x87\x01\x00/\x00\x00\x00\x9d\x87\x01\x009\x00\x00\x00\u0347\x01\x00\x1e\x00\x00\x00\a\x88\x01\x00=\x00\x00\x00&\x88\x01\x00$\x00\x00\x00d\x88\x01\x00\x1f\x00\x00\x00\x89\x88\x01\x00&\x00\x00\x00\xa9\x88\x01\x00+\x00\x00\x00\u0408\x01\x00G\x00\x00\x00\xfc\x88\x01\x00\x14\x00\x00\x00D\x89\x01\x00r\x00\x00\x00Y\x89\x01\x00\x13\x00\x00\x00\u0309\x01\x00\x18\x00\x00\x00\xe0\x89\x01\x00/\x00\x00\x00\xf9\x89\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\xc4\x00\x00\x00\x0f\x00\x00\x00\xc3\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\xeb\x00\x00\x00c\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00o\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x98\x00\x00\x00U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb\x00\x00\x00\x17\x00\x00\x00u\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\xb7\x00\x00\x00\xd7\x00\x00\x00*\x00\x00\x00\x99\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x84\x00\x00\x00\x9c\x00\x00\x00\xe6\x00\x00\x00\x9d\x00\x00\x00\xc5\x00\x00\x00\xd9\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\xcd\x00\x00\x00\xcb\x00\x00\x00y\x00\x00\x00\x97\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x93\x00\x00\x00\xad\x00\x00\x00\xe1\x00\x00\x00\xa6\x00\x00\x00\xd0\x00\x00\x00r\x00\x00\x00+\x00\x00\x006\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00h\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xd1\x00\x00\x00\xde\x00\x00\x00;\x00\x00\x00\x00\x00\x00\x00\xe9\x00\x00\x00\xe7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00/\x00\x00\x00V\x00\x00\x00\x8d\x00\x00\x00\xe3\x00\x00\x00!\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x00\x00\x00\x88\x00\x00\x00l\x00\x00\x00s\x00\x00\x00g\x00\x00\x00\x05\x00\x00\x00\xc6\x00\x00\x00#\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00\x00\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x00\x00S\x00\x00\x00G\x00\x00\x00$\x00\x00\x00\xc1\x00\x00\x00\xb5\x00\x00\x00X\x00\x00\x00m\x00\x00\x00\t\x00\x00\x00x\x00\x00\x00\xb8\x00\x00\x00\xbd\x00\x00\x00k\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00E\x00\x00\x00\xbf\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x82\x00\x00\x00\x81\x00\x00\x00&\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00I\x00\x00\x00e\x00\x00\x00\x04\x00\x00\x00>\x00\x00\x00\b\x00\x00\x00\x94\x00\x00\x00\x8f\x00\x00\x00\xce\x00\x00\x00?\x00\x00\x00Y\x00\x00\x00\xda\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x004\x00\x00\x00\xcc\x00\x00\x00\f\x00\x00\x005\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00 \x00\x00\x00)\x00\x00\x00\xcf\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00Z\x00\x00\x00\"\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00]\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00j\x00\x00\x008\x00\x00\x00\xa3\x00\x00\x00q\x00\x00\x00t\x00\x00\x00_\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00@\x00\x00\x00\xd2\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x95\x00\x00\x00\x06\x00\x00\x00\xa8\x00\x00\x00\xae\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x0e\x00\x00\x00{\x00\x00\x00\xa7\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00w\x00\x00\x00\x12\x00\x00\x00=\x00\x00\x00\xaf\x00\x00\x00\a\x00\x00\x00\xdf\x00\x00\x00\xc0\x00\x00\x00N\x00\x00\x00%\x00\x00\x009\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\xbe\x00\x00\x00\xe2\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\xb3\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00D\x00\x00\x00B\x00\x00\x00n\x00\x00\x00\x00\x00\x00\x00\xd6\x00\x00\x00\x83\x00\x00\x00\n\x00\x00\x00W\x00\x00\x00\x14\x00\x00\x00Q\x00\x00\x00\xd4\x00\x00\x00d\x00\x00\x00\xac\x00\x00\x00\x16\x00\x00\x00\x96\x00\x00\x00K\x00\x00\x002\x00\x00\x00\x1a\x00\x00\x00\xb4\x00\x00\x00f\x00\x00\x00\xa2\x00\x00\x00\xe8\x00\x00\x00\x02\x00\x00\x00A\x00\x00\x00\xe4\x00\x00\x00\x8c\x00\x00\x00\x9a\x00\x00\x00`\x00\x00\x00\xab\x00\x00\x00M\x00\x00\x007\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9b\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\xdd\x00\x00\x00\x8e\x00\x00\x00\xca\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x003\x00\x00\x00T\x00\x00\x00\x87\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\xaa\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x00\xc7\x00\x00\x00\x8b\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: EMAIL\nPOT-Creation-Date: 2017-03-14 21:32-0700\nPO-Revision-Date: 2017-05-24 18:01+0800\nLast-Translator: Brendan Burns \nLanguage-Team: \nLanguage: en\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 1.8.12\nX-Poedit-SourceCharset: UTF-8\nPlural-Forms: nplurals=2; plural=(n != 1);\n\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00") + +func translationsKubectlDefaultLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlDefaultLc_messagesK8sMo, nil +} + +func translationsKubectlDefaultLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlDefaultLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/default/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlDefaultLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2016 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR brendan.d.burns@gmail.com, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-03-14 21:32-0700\n" +"PO-Revision-Date: 2017-05-24 18:01+0800\n" +"Last-Translator: Brendan Burns \n" +"Language-Team: \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.12\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod" +"\t\tkubectl port-forward pod/mypod 5000 6000" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the deployment" +"\t\tkubectl port-forward deployment/mydeployment 5000 6000" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the service" +"\t\tkubectl port-forward service/myservice 5000 6000" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod" +"\t\tkubectl port-forward pod/mypod 8888:5000" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod" +"\t\tkubectl port-forward pod/mypod :5000" +msgstr "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod" +"\t\tkubectl port-forward pod/mypod 5000 6000" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the deployment" +"\t\tkubectl port-forward deployment/mydeployment 5000 6000" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in a pod selected by the service" +"\t\tkubectl port-forward service/myservice 5000 6000" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod" +"\t\tkubectl port-forward pod/mypod 8888:5000" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod" +"\t\tkubectl port-forward pod/mypod :5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." +msgstr "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRole." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\tCreate a namespace with the specified name." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\tCreate a role with single rule." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\tCreate a service account with the specified name." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\tMark node as schedulable." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\tMark node as unschedulable." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" +msgstr "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." +msgstr "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." +msgstr "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" Create a LoadBalancer service with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" Create a clusterIP service with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" Create a deployment with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" Create a nodeport service with the specified name." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L61 +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." +msgstr "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L60 +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L63 +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L106 +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L136 +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "A schedule in the Cron format the job should be run with." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L111 +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L119 +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L134 +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/apply.go#L98 +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "Apply a configuration to a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L71 +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "Approve a certificate signing request" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L81 +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/attach.go#L64 +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Attach to a running container" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L55 +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "Auto-scale a Deployment, ReplicaSet, or ReplicationController" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L115 +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." +msgstr "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L55 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRole this ClusterRoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L55 +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "ClusterRole this RoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L101 +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" +msgstr "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert.go#L67 +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "Convert config files between different API versions" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cp.go#L64 +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "Copy files and directories to and from containers." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "Create a ClusterRoleBinding for a particular ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L181 +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "Create a LoadBalancer service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L124 +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "Create a NodePort service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "Create a RoleBinding for a particular Role or ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L214 +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "Create a TLS secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "Create a clusterIP service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_configmap.go#L59 +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "Create a configmap from a local file, directory or literal value" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "Create a deployment with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "Create a namespace with the specified name" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "Create a pod disruption budget with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "Create a quota with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "Create a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L143 +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "Create a secret for use with a Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L73 +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "Create a secret from a local file, directory or literal value" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L34 +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "Create a secret using specified subcommand" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "Create a service account with the specified name" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L36 +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "Create a service using specified subcommand." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L240 +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Create an ExternalName service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/delete.go#L130 +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "Delete the specified cluster from the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "Delete the specified context from the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L121 +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "Deny a certificate signing request" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/stop.go#L58 +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Deprecated: Gracefully shut down a resource by name or filename" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "Describe one or many contexts" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "Display cluster info" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "Display clusters defined in the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "Display merged kubeconfig settings or a specified kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/get.go#L107 +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "Display one or many resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "Displays the current-context" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/explain.go#L50 +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "Documentation of resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L176 +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Drain node in preparation for maintenance" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L37 +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Dump lots of relevant info for debugging and diagnosis" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L100 +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "Edit a resource on the server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L159 +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "Email for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/exec.go#L68 +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "Execute a command in a container" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L102 +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/portforward.go#L75 +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Forward one or more local ports to a pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/help.go#L36 +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Help about any command" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L105 +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L114 +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" +msgstr "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/annotate.go#L135 +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L132 +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L98 +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" +msgstr "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout.go#L46 +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "Manage a deployment rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "Mark node as schedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "Mark node as unschedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_pause.go#L73 +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "Mark the provided resource as paused" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L35 +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "Modify certificate resources." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "Modify kubeconfig files" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L110 +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L108 +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/completion.go#L97 +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "Output shell completion code for the specified shell (bash or zsh)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L115 +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" +msgstr "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L157 +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Password for Docker registry authentication" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L226 +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Path to PEM encoded public key certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L227 +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Path to private key associated with given certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L84 +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "Perform a rolling update of the given ReplicationController" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L82 +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." +msgstr "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "Print the client and server version information" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "Print the list of flags inherited by all commands" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L86 +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "Print the logs for a container in a pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/replace.go#L70 +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "Replace a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_resume.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "Resume a paused resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L56 +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "Role this RoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L94 +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "Run a particular image on the cluster" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/proxy.go#L68 +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "Run a proxy to the Kubernetes API server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L161 +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "Server location for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L71 +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set.go#L37 +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "Set specific features on objects" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_selector.go#L81 +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "Set the selector on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "Sets a cluster entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "Sets a context entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "Sets a user entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "Sets an individual value in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "Sets the current-context in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/describe.go#L80 +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "Show details of a specific resource or group of resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_status.go#L57 +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "Show the status of the rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L108 +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Synonym for --target-port" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L87 +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L114 +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "The image for the container to run." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L116 +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L100 +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L62 +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "" +"The minimum number or percentage of available pods this budget requires." +msgstr "" +"The minimum number or percentage of available pods this budget requires." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L113 +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "The name for the newly created object." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L71 +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L113 +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L66 +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" +"The name of the API generator to use. Currently there is only 1 generator." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L98 +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." +msgstr "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L133 +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L99 +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "The network protocol for the service to be created. Default is 'TCP'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L100 +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L121 +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L131 +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L130 +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L128 +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L87 +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "The type of secret to create" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L101 +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_undo.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "Undo a previous rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "Unsets an individual value in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/patch.go#L91 +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "Update field(s) of a resource using strategic merge patch" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_image.go#L94 +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "Update image of a pod template" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_resources.go#L101 +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "Update resource requests/limits on objects with pod templates" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "Update the annotations on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L109 +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "Update the labels on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/taint.go#L88 +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "Update the taints on one or more nodes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L155 +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Username for Docker registry authentication" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "" +"View latest last-applied-configuration annotations of a resource/object" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_history.go#L51 +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "View rollout history" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L45 +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "dummy restart flag)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L253 +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "external name of service" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cmd.go#L217 +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "kubectl controls the Kubernetes cluster manager" + +#~ msgid "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgid_plural "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgstr[0] "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resource was found" +#~ msgstr[1] "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +`) + +func translationsKubectlDefaultLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlDefaultLc_messagesK8sPo, nil +} + +func translationsKubectlDefaultLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlDefaultLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/default/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlEn_usLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xeb\x00\x00\x00\x1c\x00\x00\x00t\a\x00\x009\x01\x00\x00\xcc\x0e\x00\x00\x00\x00\x00\x00\xb0\x13\x00\x00\xdc\x00\x00\x00\xb1\x13\x00\x00\xb6\x00\x00\x00\x8e\x14\x00\x00\v\x02\x00\x00E\x15\x00\x00\x1f\x01\x00\x00Q\x17\x00\x00z\x00\x00\x00q\x18\x00\x00_\x02\x00\x00\xec\x18\x00\x00\u007f\x01\x00\x00L\x1b\x00\x00\x8f\x01\x00\x00\xcc\x1c\x00\x00k\x01\x00\x00\\\x1e\x00\x00k\x01\x00\x00\xc8\x1f\x00\x00>\x01\x00\x004!\x00\x00\x03\x02\x00\x00s\"\x00\x00o\x01\x00\x00w$\x00\x00H\x05\x00\x00\xe7%\x00\x00g\x02\x00\x000+\x00\x00\x1b\x02\x00\x00\x98-\x00\x00q\x01\x00\x00\xb4/\x00\x00\xa8\x01\x00\x00&1\x00\x00\xd4\x01\x00\x00\xcf2\x00\x00\x02\x02\x00\x00\xa44\x00\x00\xb4\x00\x00\x00\xa76\x00\x00\xb7\x02\x00\x00\\7\x00\x00\x92\x03\x00\x00\x14:\x00\x00\xbf\x01\x00\x00\xa7=\x00\x00=\x00\x00\x00g?\x00\x00;\x00\x00\x00\xa5?\x00\x00\xcd\x02\x00\x00\xe1?\x00\x00<\x00\x00\x00\xafB\x00\x00P\x00\x00\x00\xecB\x00\x00S\x00\x00\x00=C\x00\x00<\x00\x00\x00\x91C\x00\x00\xac\x01\x00\x00\xceC\x00\x00\x13\x03\x00\x00{E\x00\x00\xea\x01\x00\x00\x8fH\x00\x00\xfa\x01\x00\x00zJ\x00\x00\xda\x01\x00\x00uL\x00\x00c\x01\x00\x00PN\x00\x00T\x01\x00\x00\xb4O\x00\x00\xba\x06\x00\x00\tQ\x00\x00\xf9\x01\x00\x00\xc4W\x00\x00\xe0\x02\x00\x00\xbeY\x00\x00\x02\x03\x00\x00\x9f\\\x00\x00\xfb\x00\x00\x00\xa2_\x00\x00\xa5\x01\x00\x00\x9e`\x00\x00\xb4\x01\x00\x00Db\x00\x00\x18\x00\x00\x00\xf9c\x00\x00<\x00\x00\x00\x12d\x00\x00=\x00\x00\x00Od\x00\x00\xc6\x00\x00\x00\x8dd\x00\x00g\x02\x00\x00Te\x00\x00.\x00\x00\x00\xbcg\x00\x001\x03\x00\x00\xebg\x00\x00g\x00\x00\x00\x1dk\x00\x00Q\x00\x00\x00\x85k\x00\x00R\x00\x00\x00\xd7k\x00\x00\"\x00\x00\x00*l\x00\x00X\x02\x00\x00Ml\x00\x004\x00\x00\x00\xa6n\x00\x00}\x00\x00\x00\xdbn\x00\x00k\x01\x00\x00Yo\x00\x00\x81\a\x00\x00\xc5p\x00\x00f\x01\x00\x00Gx\x00\x00\x85\x00\x00\x00\xaey\x00\x00\xea\x00\x00\x004z\x00\x00\xd9\x00\x00\x00\x1f{\x00\x00\n\x05\x00\x00\xf9{\x00\x00\x10\x05\x00\x00\x04\x81\x00\x00\x1c\x00\x00\x00\x15\x86\x00\x00\x1e\x00\x00\x002\x86\x00\x00\x98\x02\x00\x00Q\x86\x00\x00\xbc\x01\x00\x00\xea\x88\x00\x00\x9c\x01\x00\x00\xa7\x8a\x00\x00q\x01\x00\x00D\x8c\x00\x00\x05\x01\x00\x00\xb6\x8d\x00\x00\xdf\x01\x00\x00\xbc\x8e\x00\x00\x1c\x01\x00\x00\x9c\x90\x00\x00\xc1\x01\x00\x00\xb9\x91\x00\x00\x1b\x02\x00\x00{\x93\x00\x00\xc0\x00\x00\x00\x97\x95\x00\x00\xd5\x02\x00\x00X\x96\x00\x00\x9d\x00\x00\x00.\x99\x00\x00X\x00\x00\x00\u0319\x00\x00%\x02\x00\x00%\x9a\x00\x00o\x00\x00\x00K\x9c\x00\x00u\x00\x00\x00\xbb\x9c\x00\x00\x01\x01\x00\x001\x9d\x00\x00v\x00\x00\x003\x9e\x00\x00t\x00\x00\x00\xaa\x9e\x00\x00\xef\x00\x00\x00\x1f\x9f\x00\x00}\x00\x00\x00\x0f\xa0\x00\x00j\x00\x00\x00\x8d\xa0\x00\x00\xc4\x01\x00\x00\xf8\xa0\x00\x00\xf7\x03\x00\x00\xbd\xa2\x00\x00;\x00\x00\x00\xb5\xa6\x00\x008\x00\x00\x00\xf1\xa6\x00\x001\x00\x00\x00*\xa7\x00\x007\x00\x00\x00\\\xa7\x00\x00u\x02\x00\x00\x94\xa7\x00\x00\xb0\x00\x00\x00\n\xaa\x00\x00[\x00\x00\x00\xbb\xaa\x00\x00J\x00\x00\x00\x17\xab\x00\x00a\x00\x00\x00b\xab\x00\x00\xbd\x00\x00\x00\u012b\x00\x009\x00\x00\x00\x82\xac\x00\x00\xc5\x00\x00\x00\xbc\xac\x00\x00\xae\x00\x00\x00\x82\xad\x00\x00\xd6\x00\x00\x001\xae\x00\x008\x00\x00\x00\b\xaf\x00\x00%\x00\x00\x00A\xaf\x00\x00W\x00\x00\x00g\xaf\x00\x00\x1d\x00\x00\x00\xbf\xaf\x00\x00=\x00\x00\x00\u076f\x00\x00u\x00\x00\x00\x1b\xb0\x00\x004\x00\x00\x00\x91\xb0\x00\x00-\x00\x00\x00\u01b0\x00\x00\xa3\x00\x00\x00\xf4\xb0\x00\x003\x00\x00\x00\x98\xb1\x00\x002\x00\x00\x00\u0331\x00\x008\x00\x00\x00\xff\xb1\x00\x00\x1e\x00\x00\x008\xb2\x00\x00\x1a\x00\x00\x00W\xb2\x00\x009\x00\x00\x00r\xb2\x00\x00\x13\x00\x00\x00\xac\xb2\x00\x00\x1b\x00\x00\x00\xc0\xb2\x00\x00@\x00\x00\x00\u0732\x00\x00,\x00\x00\x00\x1d\xb3\x00\x00*\x00\x00\x00J\xb3\x00\x007\x00\x00\x00u\xb3\x00\x00'\x00\x00\x00\xad\xb3\x00\x00&\x00\x00\x00\u0573\x00\x00.\x00\x00\x00\xfc\xb3\x00\x00=\x00\x00\x00+\xb4\x00\x00*\x00\x00\x00i\xb4\x00\x000\x00\x00\x00\x94\xb4\x00\x00,\x00\x00\x00\u0174\x00\x00\x1f\x00\x00\x00\xf2\xb4\x00\x00]\x00\x00\x00\x12\xb5\x00\x000\x00\x00\x00p\xb5\x00\x000\x00\x00\x00\xa1\xb5\x00\x00\"\x00\x00\x00\u04b5\x00\x00?\x00\x00\x00\xf5\xb5\x00\x00\x1d\x00\x00\x005\xb6\x00\x00,\x00\x00\x00S\xb6\x00\x00+\x00\x00\x00\x80\xb6\x00\x00$\x00\x00\x00\xac\xb6\x00\x00\x14\x00\x00\x00\u0476\x00\x00*\x00\x00\x00\xe6\xb6\x00\x00A\x00\x00\x00\x11\xb7\x00\x00\x1d\x00\x00\x00S\xb7\x00\x00\x1c\x00\x00\x00q\xb7\x00\x00\x1a\x00\x00\x00\x8e\xb7\x00\x00)\x00\x00\x00\xa9\xb7\x00\x006\x00\x00\x00\u04f7\x00\x00\x1d\x00\x00\x00\n\xb8\x00\x00\x19\x00\x00\x00(\xb8\x00\x00 \x00\x00\x00B\xb8\x00\x00v\x00\x00\x00c\xb8\x00\x00(\x00\x00\x00\u06b8\x00\x00\x16\x00\x00\x00\x03\xb9\x00\x00p\x00\x00\x00\x1a\xb9\x00\x00`\x00\x00\x00\x8b\xb9\x00\x00\x9b\x00\x00\x00\xec\xb9\x00\x00\x97\x00\x00\x00\x88\xba\x00\x00\xa8\x00\x00\x00 \xbb\x00\x00\x1b\x00\x00\x00\u027b\x00\x00\x18\x00\x00\x00\xe5\xbb\x00\x00\x1a\x00\x00\x00\xfe\xbb\x00\x00$\x00\x00\x00\x19\xbc\x00\x00\x1d\x00\x00\x00>\xbc\x00\x00\x17\x00\x00\x00\\\xbc\x00\x00a\x00\x00\x00t\xbc\x00\x00s\x00\x00\x00\u05bc\x00\x00B\x00\x00\x00J\xbd\x00\x00Y\x00\x00\x00\x8d\xbd\x00\x00+\x00\x00\x00\xe7\xbd\x00\x00+\x00\x00\x00\x13\xbe\x00\x006\x00\x00\x00?\xbe\x00\x00;\x00\x00\x00v\xbe\x00\x00q\x00\x00\x00\xb2\xbe\x00\x00/\x00\x00\x00$\xbf\x00\x001\x00\x00\x00T\xbf\x00\x00'\x00\x00\x00\x86\xbf\x00\x00'\x00\x00\x00\xae\xbf\x00\x00\x18\x00\x00\x00\u05bf\x00\x00&\x00\x00\x00\xef\xbf\x00\x00%\x00\x00\x00\x16\xc0\x00\x00(\x00\x00\x00<\xc0\x00\x00#\x00\x00\x00e\xc0\x00\x00K\x00\x00\x00\x89\xc0\x00\x00 \x00\x00\x00\xd5\xc0\x00\x00_\x00\x00\x00\xf6\xc0\x00\x00\x1e\x00\x00\x00V\xc1\x00\x00\"\x00\x00\x00u\xc1\x00\x00\"\x00\x00\x00\x98\xc1\x00\x00\x1f\x00\x00\x00\xbb\xc1\x00\x00-\x00\x00\x00\xdb\xc1\x00\x00-\x00\x00\x00\t\xc2\x00\x009\x00\x00\x007\xc2\x00\x00\x1e\x00\x00\x00q\xc2\x00\x00\x19\x00\x00\x00\x90\xc2\x00\x00c\x00\x00\x00\xaa\xc2\x00\x00#\x00\x00\x00\x0e\xc3\x00\x00\x82\x00\x00\x002\xc3\x00\x00\x94\x00\x00\x00\xb5\xc3\x00\x00H\x00\x00\x00J\xc4\x00\x00&\x00\x00\x00\x93\xc4\x00\x00e\x00\x00\x00\xba\xc4\x00\x00z\x00\x00\x00 \xc5\x00\x00J\x00\x00\x00\x9b\xc5\x00\x00\xe5\x00\x00\x00\xe6\xc5\x00\x00W\x00\x00\x00\xcc\xc6\x00\x00E\x00\x00\x00$\xc7\x00\x00a\x00\x00\x00j\xc7\x00\x00v\x00\x00\x00\xcc\xc7\x00\x00\xcb\x00\x00\x00C\xc8\x00\x00\xcf\x00\x00\x00\x0f\xc9\x00\x00\x1e\x01\x00\x00\xdf\xc9\x00\x00\x1c\x00\x00\x00\xfe\xca\x00\x00T\x00\x00\x00\x1b\xcb\x00\x00\x17\x00\x00\x00p\xcb\x00\x00/\x00\x00\x00\x88\xcb\x00\x009\x00\x00\x00\xb8\xcb\x00\x00\x1e\x00\x00\x00\xf2\xcb\x00\x00=\x00\x00\x00\x11\xcc\x00\x00$\x00\x00\x00O\xcc\x00\x00\x1f\x00\x00\x00t\xcc\x00\x00&\x00\x00\x00\x94\xcc\x00\x00+\x00\x00\x00\xbb\xcc\x00\x00G\x00\x00\x00\xe7\xcc\x00\x00\x14\x00\x00\x00/\xcd\x00\x00r\x00\x00\x00D\xcd\x00\x00\x13\x00\x00\x00\xb7\xcd\x00\x00\x18\x00\x00\x00\xcb\xcd\x00\x00/\x00\x00\x00\xe4\xcd\x00\x00\xb1\x01\x00\x00\x14\xce\x00\x00\xdc\x00\x00\x00\xc6\xcf\x00\x00\xb6\x00\x00\x00\xa3\xd0\x00\x00\v\x02\x00\x00Z\xd1\x00\x00\x1f\x01\x00\x00f\xd3\x00\x00z\x00\x00\x00\x86\xd4\x00\x00_\x02\x00\x00\x01\xd5\x00\x00\u007f\x01\x00\x00a\xd7\x00\x00\x8f\x01\x00\x00\xe1\xd8\x00\x00k\x01\x00\x00q\xda\x00\x00k\x01\x00\x00\xdd\xdb\x00\x00>\x01\x00\x00I\xdd\x00\x00\x03\x02\x00\x00\x88\xde\x00\x00o\x01\x00\x00\x8c\xe0\x00\x00H\x05\x00\x00\xfc\xe1\x00\x00g\x02\x00\x00E\xe7\x00\x00\x1b\x02\x00\x00\xad\xe9\x00\x00q\x01\x00\x00\xc9\xeb\x00\x00\xa8\x01\x00\x00;\xed\x00\x00\xd4\x01\x00\x00\xe4\xee\x00\x00\x02\x02\x00\x00\xb9\xf0\x00\x00\xb4\x00\x00\x00\xbc\xf2\x00\x00\xb7\x02\x00\x00q\xf3\x00\x00\x92\x03\x00\x00)\xf6\x00\x00\xbf\x01\x00\x00\xbc\xf9\x00\x00=\x00\x00\x00|\xfb\x00\x00;\x00\x00\x00\xba\xfb\x00\x00\xcd\x02\x00\x00\xf6\xfb\x00\x00<\x00\x00\x00\xc4\xfe\x00\x00P\x00\x00\x00\x01\xff\x00\x00S\x00\x00\x00R\xff\x00\x00<\x00\x00\x00\xa6\xff\x00\x00\xac\x01\x00\x00\xe3\xff\x00\x00\x13\x03\x00\x00\x90\x01\x01\x00\xea\x01\x00\x00\xa4\x04\x01\x00\xfa\x01\x00\x00\x8f\x06\x01\x00\xda\x01\x00\x00\x8a\b\x01\x00c\x01\x00\x00e\n\x01\x00T\x01\x00\x00\xc9\v\x01\x00\xba\x06\x00\x00\x1e\r\x01\x00\xf9\x01\x00\x00\xd9\x13\x01\x00\xe0\x02\x00\x00\xd3\x15\x01\x00\x02\x03\x00\x00\xb4\x18\x01\x00\xfb\x00\x00\x00\xb7\x1b\x01\x00\xa5\x01\x00\x00\xb3\x1c\x01\x00\xb4\x01\x00\x00Y\x1e\x01\x00\x18\x00\x00\x00\x0e \x01\x00<\x00\x00\x00' \x01\x00=\x00\x00\x00d \x01\x00\xc6\x00\x00\x00\xa2 \x01\x00g\x02\x00\x00i!\x01\x00.\x00\x00\x00\xd1#\x01\x001\x03\x00\x00\x00$\x01\x00g\x00\x00\x002'\x01\x00Q\x00\x00\x00\x9a'\x01\x00R\x00\x00\x00\xec'\x01\x00\"\x00\x00\x00?(\x01\x00X\x02\x00\x00b(\x01\x004\x00\x00\x00\xbb*\x01\x00}\x00\x00\x00\xf0*\x01\x00k\x01\x00\x00n+\x01\x00\x81\a\x00\x00\xda,\x01\x00f\x01\x00\x00\\4\x01\x00\x85\x00\x00\x00\xc35\x01\x00\xea\x00\x00\x00I6\x01\x00\xd9\x00\x00\x0047\x01\x00\n\x05\x00\x00\x0e8\x01\x00\x10\x05\x00\x00\x19=\x01\x00\x1c\x00\x00\x00*B\x01\x00\x1e\x00\x00\x00GB\x01\x00\x98\x02\x00\x00fB\x01\x00\xbc\x01\x00\x00\xffD\x01\x00\x9c\x01\x00\x00\xbcF\x01\x00q\x01\x00\x00YH\x01\x00\x05\x01\x00\x00\xcbI\x01\x00\xdf\x01\x00\x00\xd1J\x01\x00\x1c\x01\x00\x00\xb1L\x01\x00\xc1\x01\x00\x00\xceM\x01\x00\x1b\x02\x00\x00\x90O\x01\x00\xc0\x00\x00\x00\xacQ\x01\x00\xd5\x02\x00\x00mR\x01\x00\x9d\x00\x00\x00CU\x01\x00X\x00\x00\x00\xe1U\x01\x00%\x02\x00\x00:V\x01\x00o\x00\x00\x00`X\x01\x00u\x00\x00\x00\xd0X\x01\x00\x01\x01\x00\x00FY\x01\x00v\x00\x00\x00HZ\x01\x00t\x00\x00\x00\xbfZ\x01\x00\xef\x00\x00\x004[\x01\x00}\x00\x00\x00$\\\x01\x00j\x00\x00\x00\xa2\\\x01\x00\xc4\x01\x00\x00\r]\x01\x00\xf7\x03\x00\x00\xd2^\x01\x00;\x00\x00\x00\xcab\x01\x008\x00\x00\x00\x06c\x01\x001\x00\x00\x00?c\x01\x007\x00\x00\x00qc\x01\x00u\x02\x00\x00\xa9c\x01\x00\xb0\x00\x00\x00\x1ff\x01\x00[\x00\x00\x00\xd0f\x01\x00J\x00\x00\x00,g\x01\x00a\x00\x00\x00wg\x01\x00\xbd\x00\x00\x00\xd9g\x01\x009\x00\x00\x00\x97h\x01\x00\xc5\x00\x00\x00\xd1h\x01\x00\xae\x00\x00\x00\x97i\x01\x00\xd6\x00\x00\x00Fj\x01\x008\x00\x00\x00\x1dk\x01\x00%\x00\x00\x00Vk\x01\x00W\x00\x00\x00|k\x01\x00\x1d\x00\x00\x00\xd4k\x01\x00=\x00\x00\x00\xf2k\x01\x00u\x00\x00\x000l\x01\x004\x00\x00\x00\xa6l\x01\x00-\x00\x00\x00\xdbl\x01\x00\xa3\x00\x00\x00\tm\x01\x003\x00\x00\x00\xadm\x01\x002\x00\x00\x00\xe1m\x01\x008\x00\x00\x00\x14n\x01\x00\x1e\x00\x00\x00Mn\x01\x00\x1a\x00\x00\x00ln\x01\x009\x00\x00\x00\x87n\x01\x00\x13\x00\x00\x00\xc1n\x01\x00\x1b\x00\x00\x00\xd5n\x01\x00@\x00\x00\x00\xf1n\x01\x00,\x00\x00\x002o\x01\x00*\x00\x00\x00_o\x01\x007\x00\x00\x00\x8ao\x01\x00'\x00\x00\x00\xc2o\x01\x00&\x00\x00\x00\xeao\x01\x00.\x00\x00\x00\x11p\x01\x00=\x00\x00\x00@p\x01\x00*\x00\x00\x00~p\x01\x000\x00\x00\x00\xa9p\x01\x00,\x00\x00\x00\xdap\x01\x00\x1f\x00\x00\x00\aq\x01\x00]\x00\x00\x00'q\x01\x000\x00\x00\x00\x85q\x01\x000\x00\x00\x00\xb6q\x01\x00\"\x00\x00\x00\xe7q\x01\x00?\x00\x00\x00\nr\x01\x00\x1d\x00\x00\x00Jr\x01\x00,\x00\x00\x00hr\x01\x00+\x00\x00\x00\x95r\x01\x00$\x00\x00\x00\xc1r\x01\x00\x14\x00\x00\x00\xe6r\x01\x00*\x00\x00\x00\xfbr\x01\x00A\x00\x00\x00&s\x01\x00\x1d\x00\x00\x00hs\x01\x00\x1c\x00\x00\x00\x86s\x01\x00\x1a\x00\x00\x00\xa3s\x01\x00)\x00\x00\x00\xbes\x01\x006\x00\x00\x00\xe8s\x01\x00\x1d\x00\x00\x00\x1ft\x01\x00\x19\x00\x00\x00=t\x01\x00 \x00\x00\x00Wt\x01\x00v\x00\x00\x00xt\x01\x00(\x00\x00\x00\xeft\x01\x00\x16\x00\x00\x00\x18u\x01\x00p\x00\x00\x00/u\x01\x00`\x00\x00\x00\xa0u\x01\x00\x9b\x00\x00\x00\x01v\x01\x00\x97\x00\x00\x00\x9dv\x01\x00\xa8\x00\x00\x005w\x01\x00\x1b\x00\x00\x00\xdew\x01\x00\x18\x00\x00\x00\xfaw\x01\x00\x1a\x00\x00\x00\x13x\x01\x00$\x00\x00\x00.x\x01\x00\x1d\x00\x00\x00Sx\x01\x00\x17\x00\x00\x00qx\x01\x00a\x00\x00\x00\x89x\x01\x00s\x00\x00\x00\xebx\x01\x00B\x00\x00\x00_y\x01\x00Y\x00\x00\x00\xa2y\x01\x00+\x00\x00\x00\xfcy\x01\x00+\x00\x00\x00(z\x01\x006\x00\x00\x00Tz\x01\x00;\x00\x00\x00\x8bz\x01\x00q\x00\x00\x00\xc7z\x01\x00/\x00\x00\x009{\x01\x001\x00\x00\x00i{\x01\x00'\x00\x00\x00\x9b{\x01\x00'\x00\x00\x00\xc3{\x01\x00\x18\x00\x00\x00\xeb{\x01\x00&\x00\x00\x00\x04|\x01\x00%\x00\x00\x00+|\x01\x00(\x00\x00\x00Q|\x01\x00#\x00\x00\x00z|\x01\x00K\x00\x00\x00\x9e|\x01\x00 \x00\x00\x00\xea|\x01\x00_\x00\x00\x00\v}\x01\x00\x1e\x00\x00\x00k}\x01\x00\"\x00\x00\x00\x8a}\x01\x00\"\x00\x00\x00\xad}\x01\x00\x1f\x00\x00\x00\xd0}\x01\x00-\x00\x00\x00\xf0}\x01\x00-\x00\x00\x00\x1e~\x01\x009\x00\x00\x00L~\x01\x00\x1e\x00\x00\x00\x86~\x01\x00\x19\x00\x00\x00\xa5~\x01\x00c\x00\x00\x00\xbf~\x01\x00#\x00\x00\x00#\u007f\x01\x00\x82\x00\x00\x00G\u007f\x01\x00\x94\x00\x00\x00\xca\u007f\x01\x00H\x00\x00\x00_\x80\x01\x00&\x00\x00\x00\xa8\x80\x01\x00e\x00\x00\x00\u03c0\x01\x00z\x00\x00\x005\x81\x01\x00J\x00\x00\x00\xb0\x81\x01\x00\xe5\x00\x00\x00\xfb\x81\x01\x00W\x00\x00\x00\xe1\x82\x01\x00E\x00\x00\x009\x83\x01\x00a\x00\x00\x00\u007f\x83\x01\x00v\x00\x00\x00\xe1\x83\x01\x00\xcb\x00\x00\x00X\x84\x01\x00\xcf\x00\x00\x00$\x85\x01\x00\x1e\x01\x00\x00\xf4\x85\x01\x00\x1c\x00\x00\x00\x13\x87\x01\x00T\x00\x00\x000\x87\x01\x00\x17\x00\x00\x00\x85\x87\x01\x00/\x00\x00\x00\x9d\x87\x01\x009\x00\x00\x00\u0347\x01\x00\x1e\x00\x00\x00\a\x88\x01\x00=\x00\x00\x00&\x88\x01\x00$\x00\x00\x00d\x88\x01\x00\x1f\x00\x00\x00\x89\x88\x01\x00&\x00\x00\x00\xa9\x88\x01\x00+\x00\x00\x00\u0408\x01\x00G\x00\x00\x00\xfc\x88\x01\x00\x14\x00\x00\x00D\x89\x01\x00r\x00\x00\x00Y\x89\x01\x00\x13\x00\x00\x00\u0309\x01\x00\x18\x00\x00\x00\xe0\x89\x01\x00/\x00\x00\x00\xf9\x89\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\xc4\x00\x00\x00\x0f\x00\x00\x00\xc3\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\xeb\x00\x00\x00c\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00o\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x98\x00\x00\x00U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb\x00\x00\x00\x17\x00\x00\x00u\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\xb7\x00\x00\x00\xd7\x00\x00\x00*\x00\x00\x00\x99\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x84\x00\x00\x00\x9c\x00\x00\x00\xe6\x00\x00\x00\x9d\x00\x00\x00\xc5\x00\x00\x00\xd9\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\xcd\x00\x00\x00\xcb\x00\x00\x00y\x00\x00\x00\x97\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x93\x00\x00\x00\xad\x00\x00\x00\xe1\x00\x00\x00\xa6\x00\x00\x00\xd0\x00\x00\x00r\x00\x00\x00+\x00\x00\x006\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00h\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xd1\x00\x00\x00\xde\x00\x00\x00;\x00\x00\x00\x00\x00\x00\x00\xe9\x00\x00\x00\xe7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00/\x00\x00\x00V\x00\x00\x00\x8d\x00\x00\x00\xe3\x00\x00\x00!\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x00\x00\x00\x88\x00\x00\x00l\x00\x00\x00s\x00\x00\x00g\x00\x00\x00\x05\x00\x00\x00\xc6\x00\x00\x00#\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00\x00\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x00\x00S\x00\x00\x00G\x00\x00\x00$\x00\x00\x00\xc1\x00\x00\x00\xb5\x00\x00\x00X\x00\x00\x00m\x00\x00\x00\t\x00\x00\x00x\x00\x00\x00\xb8\x00\x00\x00\xbd\x00\x00\x00k\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00E\x00\x00\x00\xbf\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x82\x00\x00\x00\x81\x00\x00\x00&\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00I\x00\x00\x00e\x00\x00\x00\x04\x00\x00\x00>\x00\x00\x00\b\x00\x00\x00\x94\x00\x00\x00\x8f\x00\x00\x00\xce\x00\x00\x00?\x00\x00\x00Y\x00\x00\x00\xda\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x004\x00\x00\x00\xcc\x00\x00\x00\f\x00\x00\x005\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00 \x00\x00\x00)\x00\x00\x00\xcf\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00Z\x00\x00\x00\"\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00]\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00j\x00\x00\x008\x00\x00\x00\xa3\x00\x00\x00q\x00\x00\x00t\x00\x00\x00_\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00@\x00\x00\x00\xd2\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x95\x00\x00\x00\x06\x00\x00\x00\xa8\x00\x00\x00\xae\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x0e\x00\x00\x00{\x00\x00\x00\xa7\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00w\x00\x00\x00\x12\x00\x00\x00=\x00\x00\x00\xaf\x00\x00\x00\a\x00\x00\x00\xdf\x00\x00\x00\xc0\x00\x00\x00N\x00\x00\x00%\x00\x00\x009\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\xbe\x00\x00\x00\xe2\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\xb3\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00D\x00\x00\x00B\x00\x00\x00n\x00\x00\x00\x00\x00\x00\x00\xd6\x00\x00\x00\x83\x00\x00\x00\n\x00\x00\x00W\x00\x00\x00\x14\x00\x00\x00Q\x00\x00\x00\xd4\x00\x00\x00d\x00\x00\x00\xac\x00\x00\x00\x16\x00\x00\x00\x96\x00\x00\x00K\x00\x00\x002\x00\x00\x00\x1a\x00\x00\x00\xb4\x00\x00\x00f\x00\x00\x00\xa2\x00\x00\x00\xe8\x00\x00\x00\x02\x00\x00\x00A\x00\x00\x00\xe4\x00\x00\x00\x8c\x00\x00\x00\x9a\x00\x00\x00`\x00\x00\x00\xab\x00\x00\x00M\x00\x00\x007\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9b\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\xdd\x00\x00\x00\x8e\x00\x00\x00\xca\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x003\x00\x00\x00T\x00\x00\x00\x87\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\xaa\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x00\xc7\x00\x00\x00\x8b\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: EMAIL\nPOT-Creation-Date: 2017-03-14 21:32-0700\nPO-Revision-Date: 2017-03-14 21:33-0800\nLast-Translator: Brendan Burns \nLanguage-Team: \nLanguage: en\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 1.6.10\nX-Poedit-SourceCharset: UTF-8\nPlural-Forms: nplurals=2; plural=(n != 1);\n\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00") + +func translationsKubectlEn_usLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlEn_usLc_messagesK8sMo, nil +} + +func translationsKubectlEn_usLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlEn_usLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/en_US/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlEn_usLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2016 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR brendan.d.burns@gmail.com, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-03-14 21:32-0700\n" +"PO-Revision-Date: 2017-03-14 21:33-0800\n" +"Last-Translator: Brendan Burns \n" +"Language-Team: \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." +msgstr "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRole." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\tCreate a namespace with the specified name." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\tCreate a role with single rule." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\tCreate a service account with the specified name." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\tMark node as schedulable." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\tMark node as unschedulable." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" +msgstr "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." +msgstr "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." +msgstr "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" Create a LoadBalancer service with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" Create a clusterIP service with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" Create a deployment with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" Create a nodeport service with the specified name." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L61 +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." +msgstr "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L60 +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L63 +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L106 +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L136 +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "A schedule in the Cron format the job should be run with." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L111 +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L119 +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L134 +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "Apply a configuration to a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L71 +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "Approve a certificate signing request" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L81 +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/attach.go#L64 +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Attach to a running container" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L55 +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "Auto-scale a Deployment, ReplicaSet, or ReplicationController" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L115 +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." +msgstr "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L55 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRole this ClusterRoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L55 +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "ClusterRole this RoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L101 +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" +msgstr "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert.go#L67 +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "Convert config files between different API versions" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cp.go#L64 +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "Copy files and directories to and from containers." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "Create a ClusterRoleBinding for a particular ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L181 +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "Create a LoadBalancer service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L124 +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "Create a NodePort service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "Create a RoleBinding for a particular Role or ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L214 +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "Create a TLS secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "Create a clusterIP service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_configmap.go#L59 +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "Create a configmap from a local file, directory or literal value" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "Create a deployment with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "Create a namespace with the specified name" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "Create a pod disruption budget with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "Create a quota with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "Create a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L143 +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "Create a secret for use with a Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L73 +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "Create a secret from a local file, directory or literal value" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L34 +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "Create a secret using specified subcommand" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "Create a service account with the specified name" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L36 +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "Create a service using specified subcommand." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L240 +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Create an ExternalName service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/delete.go#L130 +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "Delete the specified cluster from the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "Delete the specified context from the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L121 +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "Deny a certificate signing request" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/stop.go#L58 +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Deprecated: Gracefully shut down a resource by name or filename" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "Describe one or many contexts" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "Display cluster info" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "Display clusters defined in the kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "Display merged kubeconfig settings or a specified kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/get.go#L107 +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "Display one or many resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "Displays the current-context" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/explain.go#L50 +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "Documentation of resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L176 +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Drain node in preparation for maintenance" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L37 +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Dump lots of relevant info for debugging and diagnosis" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L100 +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "Edit a resource on the server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L159 +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "Email for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/exec.go#L68 +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "Execute a command in a container" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L102 +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/portforward.go#L75 +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Forward one or more local ports to a pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/help.go#L36 +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Help about any command" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L105 +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L114 +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" +msgstr "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/annotate.go#L135 +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L132 +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L98 +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" +msgstr "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout.go#L46 +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "Manage a deployment rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "Mark node as schedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "Mark node as unschedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_pause.go#L73 +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "Mark the provided resource as paused" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L35 +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "Modify certificate resources." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "Modify kubeconfig files" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L110 +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L108 +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/completion.go#L97 +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "Output shell completion code for the specified shell (bash or zsh)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L115 +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" +msgstr "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L157 +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Password for Docker registry authentication" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L226 +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Path to PEM encoded public key certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L227 +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Path to private key associated with given certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L84 +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "Perform a rolling update of the given ReplicationController" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L82 +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." +msgstr "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "Print the client and server version information" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "Print the list of flags inherited by all commands" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L86 +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "Print the logs for a container in a pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/replace.go#L70 +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "Replace a resource by filename or stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_resume.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "Resume a paused resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L56 +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "Role this RoleBinding should reference" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L94 +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "Run a particular image on the cluster" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/proxy.go#L68 +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "Run a proxy to the Kubernetes API server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L161 +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "Server location for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L71 +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set.go#L37 +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "Set specific features on objects" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_selector.go#L81 +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "Set the selector on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "Sets a cluster entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "Sets a context entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "Sets a user entry in kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "Sets an individual value in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "Sets the current-context in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/describe.go#L80 +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "Show details of a specific resource or group of resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_status.go#L57 +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "Show the status of the rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L108 +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Synonym for --target-port" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L87 +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L114 +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "The image for the container to run." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L116 +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L100 +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L62 +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "" +"The minimum number or percentage of available pods this budget requires." +msgstr "" +"The minimum number or percentage of available pods this budget requires." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L113 +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "The name for the newly created object." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L71 +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L113 +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L66 +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" +"The name of the API generator to use. Currently there is only 1 generator." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L98 +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." +msgstr "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L133 +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L99 +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "The network protocol for the service to be created. Default is 'TCP'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L100 +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L121 +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L131 +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L130 +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" +"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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L128 +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L87 +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "The type of secret to create" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L101 +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_undo.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "Undo a previous rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "Unsets an individual value in a kubeconfig file" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/patch.go#L91 +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "Update field(s) of a resource using strategic merge patch" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_image.go#L94 +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "Update image of a pod template" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_resources.go#L101 +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "Update resource requests/limits on objects with pod templates" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "Update the annotations on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L109 +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "Update the labels on a resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/taint.go#L88 +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "Update the taints on one or more nodes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L155 +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Username for Docker registry authentication" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "" +"View latest last-applied-configuration annotations of a resource/object" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_history.go#L51 +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "View rollout history" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L45 +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "dummy restart flag)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L253 +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "external name of service" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cmd.go#L217 +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "kubectl controls the Kubernetes cluster manager" + +#~ msgid "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgid_plural "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgstr[0] "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resource was found" +#~ msgstr[1] "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +`) + +func translationsKubectlEn_usLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlEn_usLc_messagesK8sPo, nil +} + +func translationsKubectlEn_usLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlEn_usLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/en_US/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlFr_frLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x11\x00\x00\x00\x1c\x00\x00\x00\xa4\x00\x00\x00\x17\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00\x88\x01\x00\x008\x00\x00\x00\x89\x01\x00\x000\x00\x00\x00\xc2\x01\x00\x000\x00\x00\x00\xf3\x01\x00\x00\x1d\x00\x00\x00$\x02\x00\x00*\x00\x00\x00B\x02\x00\x00A\x00\x00\x00m\x02\x00\x00\x1c\x00\x00\x00\xaf\x02\x00\x00\x17\x00\x00\x00\xcc\x02\x00\x00\"\x00\x00\x00\xe4\x02\x00\x00\"\x00\x00\x00\a\x03\x00\x00\x1f\x00\x00\x00*\x03\x00\x00-\x00\x00\x00J\x03\x00\x00-\x00\x00\x00x\x03\x00\x00/\x00\x00\x00\xa6\x03\x00\x00$\x00\x00\x00\xd6\x03\x00\x00\xc5\x00\x00\x00\xfb\x03\x00\x00\xab\x01\x00\x00\xc1\x04\x00\x00O\x00\x00\x00m\x06\x00\x00-\x00\x00\x00\xbd\x06\x00\x00.\x00\x00\x00\xeb\x06\x00\x00\"\x00\x00\x00\x1a\a\x00\x00-\x00\x00\x00=\a\x00\x00W\x00\x00\x00k\a\x00\x00\x1a\x00\x00\x00\xc3\a\x00\x00 \x00\x00\x00\xde\a\x00\x00#\x00\x00\x00\xff\a\x00\x00$\x00\x00\x00#\b\x00\x00'\x00\x00\x00H\b\x00\x00;\x00\x00\x00p\b\x00\x007\x00\x00\x00\xac\b\x00\x00;\x00\x00\x00\xe4\b\x00\x00.\x00\x00\x00 \t\x00\x00\x05\x01\x00\x00O\t\x00\x00\x01\x00\x00\x00\n\x00\x00\x00\v\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\f\x00\x00\x00\x05\x00\x00\x00\r\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00Apply a configuration to a resource by filename or stdin\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Describe one or many contexts\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Displays the current-context\x00Modify kubeconfig files\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Unsets an individual value in a kubeconfig file\x00Update the annotations on a resource\x00watch is only supported on individual resources and resource collections - %d resources were found\x00watch is only supported on individual resources and resource collections - %d resources were found\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2017-01-29 22:54-0800\nLast-Translator: Brendan Burns \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 1.6.10\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=2; plural=(n > 1);\nLanguage: fr\n\x00Appliquer une configuration \u00e0 une ressource par nom de fichier ou depuis stdin\x00Supprimer le cluster sp\u00e9cifi\u00e9 du kubeconfig\x00Supprimer le contexte sp\u00e9cifi\u00e9 du kubeconfig\x00D\u00e9crire un ou plusieurs contextes\x00Afficher les cluster d\u00e9finis dans kubeconfig\x00Afficher les param\u00e8tres fusionn\u00e9s de kubeconfig ou d'un fichier kubeconfig sp\u00e9cifi\u00e9\x00Affiche le contexte actuel\x00Modifier des fichiers kubeconfig\x00D\u00e9finit un cluster dans kubeconfig\x00D\u00e9finit un contexte dans kubeconfig\x00D\u00e9finit un utilisateur dans kubeconfig\x00D\u00e9finit une valeur individuelle dans un fichier kubeconfig\x00D\u00e9finit le contexte courant dans un fichier kubeconfig\x00Supprime une valeur individuelle dans un fichier kubeconfig\x00Mettre \u00e0 jour les annotations d'une ressource\x00watch n'est compatible qu'avec les ressources individuelles et les collections de ressources. - %d ressource a \u00e9t\u00e9 trouv\u00e9e. \x00watch n'est compatible qu'avec les ressources individuelles et les collections de ressources. - %d ressources ont \u00e9t\u00e9 trouv\u00e9es. \x00") + +func translationsKubectlFr_frLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlFr_frLc_messagesK8sMo, nil +} + +func translationsKubectlFr_frLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlFr_frLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/fr_FR/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlFr_frLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2016 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR brendan.d.burns@gmail.com, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2017-01-29 22:54-0800\n" +"Last-Translator: Brendan Burns \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language: fr\n" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/apply.go#L98 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "" +"Appliquer une configuration à une ressource par nom de fichier ou depuis " +"stdin" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "Supprimer le cluster spécifié du kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +msgid "Delete the specified context from the kubeconfig" +msgstr "Supprimer le contexte spécifié du kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +msgid "Describe one or many contexts" +msgstr "Décrire un ou plusieurs contextes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +msgid "Display clusters defined in the kubeconfig" +msgstr "Afficher les cluster définis dans kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "" +"Afficher les paramètres fusionnés de kubeconfig ou d'un fichier kubeconfig " +"spécifié" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +msgid "Displays the current-context" +msgstr "Affiche le contexte actuel" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +msgid "Modify kubeconfig files" +msgstr "Modifier des fichiers kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +msgid "Sets a cluster entry in kubeconfig" +msgstr "Définit un cluster dans kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +msgid "Sets a context entry in kubeconfig" +msgstr "Définit un contexte dans kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +msgid "Sets a user entry in kubeconfig" +msgstr "Définit un utilisateur dans kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +msgid "Sets an individual value in a kubeconfig file" +msgstr "Définit une valeur individuelle dans un fichier kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +msgid "Sets the current-context in a kubeconfig file" +msgstr "Définit le contexte courant dans un fichier kubeconfig" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "Supprime une valeur individuelle dans un fichier kubeconfig" + +msgid "Update the annotations on a resource" +msgstr "Mettre à jour les annotations d'une ressource" + +msgid "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgid_plural "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgstr[0] "" +"watch n'est compatible qu'avec les ressources individuelles et les " +"collections de ressources. - %d ressource a été trouvée. " +msgstr[1] "" +"watch n'est compatible qu'avec les ressources individuelles et les " +"collections de ressources. - %d ressources ont été trouvées. " +`) + +func translationsKubectlFr_frLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlFr_frLc_messagesK8sPo, nil +} + +func translationsKubectlFr_frLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlFr_frLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/fr_FR/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlIt_itLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xeb\x00\x00\x00\x1c\x00\x00\x00t\a\x00\x009\x01\x00\x00\xcc\x0e\x00\x00\x00\x00\x00\x00\xb0\x13\x00\x00\xdc\x00\x00\x00\xb1\x13\x00\x00\xb6\x00\x00\x00\x8e\x14\x00\x00\v\x02\x00\x00E\x15\x00\x00\x1f\x01\x00\x00Q\x17\x00\x00z\x00\x00\x00q\x18\x00\x00_\x02\x00\x00\xec\x18\x00\x00\u007f\x01\x00\x00L\x1b\x00\x00\x8f\x01\x00\x00\xcc\x1c\x00\x00k\x01\x00\x00\\\x1e\x00\x00k\x01\x00\x00\xc8\x1f\x00\x00>\x01\x00\x004!\x00\x00\x03\x02\x00\x00s\"\x00\x00o\x01\x00\x00w$\x00\x00H\x05\x00\x00\xe7%\x00\x00g\x02\x00\x000+\x00\x00\x1b\x02\x00\x00\x98-\x00\x00q\x01\x00\x00\xb4/\x00\x00\xa8\x01\x00\x00&1\x00\x00\xd4\x01\x00\x00\xcf2\x00\x00\x02\x02\x00\x00\xa44\x00\x00\xb4\x00\x00\x00\xa76\x00\x00\xb7\x02\x00\x00\\7\x00\x00\x92\x03\x00\x00\x14:\x00\x00\xbf\x01\x00\x00\xa7=\x00\x00=\x00\x00\x00g?\x00\x00;\x00\x00\x00\xa5?\x00\x00\xcd\x02\x00\x00\xe1?\x00\x00<\x00\x00\x00\xafB\x00\x00P\x00\x00\x00\xecB\x00\x00S\x00\x00\x00=C\x00\x00<\x00\x00\x00\x91C\x00\x00\xac\x01\x00\x00\xceC\x00\x00\x13\x03\x00\x00{E\x00\x00\xea\x01\x00\x00\x8fH\x00\x00\xfa\x01\x00\x00zJ\x00\x00\xda\x01\x00\x00uL\x00\x00c\x01\x00\x00PN\x00\x00T\x01\x00\x00\xb4O\x00\x00\xba\x06\x00\x00\tQ\x00\x00\xf9\x01\x00\x00\xc4W\x00\x00\xe0\x02\x00\x00\xbeY\x00\x00\x02\x03\x00\x00\x9f\\\x00\x00\xfb\x00\x00\x00\xa2_\x00\x00\xa5\x01\x00\x00\x9e`\x00\x00\xb4\x01\x00\x00Db\x00\x00\x18\x00\x00\x00\xf9c\x00\x00<\x00\x00\x00\x12d\x00\x00=\x00\x00\x00Od\x00\x00\xc6\x00\x00\x00\x8dd\x00\x00g\x02\x00\x00Te\x00\x00.\x00\x00\x00\xbcg\x00\x001\x03\x00\x00\xebg\x00\x00g\x00\x00\x00\x1dk\x00\x00Q\x00\x00\x00\x85k\x00\x00R\x00\x00\x00\xd7k\x00\x00\"\x00\x00\x00*l\x00\x00X\x02\x00\x00Ml\x00\x004\x00\x00\x00\xa6n\x00\x00}\x00\x00\x00\xdbn\x00\x00k\x01\x00\x00Yo\x00\x00\x81\a\x00\x00\xc5p\x00\x00f\x01\x00\x00Gx\x00\x00\x85\x00\x00\x00\xaey\x00\x00\xea\x00\x00\x004z\x00\x00\xd9\x00\x00\x00\x1f{\x00\x00\n\x05\x00\x00\xf9{\x00\x00\x10\x05\x00\x00\x04\x81\x00\x00\x1c\x00\x00\x00\x15\x86\x00\x00\x1e\x00\x00\x002\x86\x00\x00\x98\x02\x00\x00Q\x86\x00\x00\xbc\x01\x00\x00\xea\x88\x00\x00\x9c\x01\x00\x00\xa7\x8a\x00\x00q\x01\x00\x00D\x8c\x00\x00\x05\x01\x00\x00\xb6\x8d\x00\x00\xdf\x01\x00\x00\xbc\x8e\x00\x00\x1c\x01\x00\x00\x9c\x90\x00\x00\xc1\x01\x00\x00\xb9\x91\x00\x00\x1b\x02\x00\x00{\x93\x00\x00\xc0\x00\x00\x00\x97\x95\x00\x00\xd5\x02\x00\x00X\x96\x00\x00\x9d\x00\x00\x00.\x99\x00\x00X\x00\x00\x00\u0319\x00\x00%\x02\x00\x00%\x9a\x00\x00o\x00\x00\x00K\x9c\x00\x00u\x00\x00\x00\xbb\x9c\x00\x00\x01\x01\x00\x001\x9d\x00\x00v\x00\x00\x003\x9e\x00\x00t\x00\x00\x00\xaa\x9e\x00\x00\xef\x00\x00\x00\x1f\x9f\x00\x00}\x00\x00\x00\x0f\xa0\x00\x00j\x00\x00\x00\x8d\xa0\x00\x00\xc4\x01\x00\x00\xf8\xa0\x00\x00\xf7\x03\x00\x00\xbd\xa2\x00\x00;\x00\x00\x00\xb5\xa6\x00\x008\x00\x00\x00\xf1\xa6\x00\x001\x00\x00\x00*\xa7\x00\x007\x00\x00\x00\\\xa7\x00\x00u\x02\x00\x00\x94\xa7\x00\x00\xb0\x00\x00\x00\n\xaa\x00\x00[\x00\x00\x00\xbb\xaa\x00\x00J\x00\x00\x00\x17\xab\x00\x00a\x00\x00\x00b\xab\x00\x00\xbd\x00\x00\x00\u012b\x00\x009\x00\x00\x00\x82\xac\x00\x00\xc5\x00\x00\x00\xbc\xac\x00\x00\xae\x00\x00\x00\x82\xad\x00\x00\xd6\x00\x00\x001\xae\x00\x008\x00\x00\x00\b\xaf\x00\x00%\x00\x00\x00A\xaf\x00\x00W\x00\x00\x00g\xaf\x00\x00\x1d\x00\x00\x00\xbf\xaf\x00\x00=\x00\x00\x00\u076f\x00\x00u\x00\x00\x00\x1b\xb0\x00\x004\x00\x00\x00\x91\xb0\x00\x00-\x00\x00\x00\u01b0\x00\x00\xa3\x00\x00\x00\xf4\xb0\x00\x003\x00\x00\x00\x98\xb1\x00\x002\x00\x00\x00\u0331\x00\x008\x00\x00\x00\xff\xb1\x00\x00\x1e\x00\x00\x008\xb2\x00\x00\x1a\x00\x00\x00W\xb2\x00\x009\x00\x00\x00r\xb2\x00\x00\x13\x00\x00\x00\xac\xb2\x00\x00\x1b\x00\x00\x00\xc0\xb2\x00\x00@\x00\x00\x00\u0732\x00\x00,\x00\x00\x00\x1d\xb3\x00\x00*\x00\x00\x00J\xb3\x00\x007\x00\x00\x00u\xb3\x00\x00'\x00\x00\x00\xad\xb3\x00\x00&\x00\x00\x00\u0573\x00\x00.\x00\x00\x00\xfc\xb3\x00\x00=\x00\x00\x00+\xb4\x00\x00*\x00\x00\x00i\xb4\x00\x000\x00\x00\x00\x94\xb4\x00\x00,\x00\x00\x00\u0174\x00\x00\x1f\x00\x00\x00\xf2\xb4\x00\x00]\x00\x00\x00\x12\xb5\x00\x000\x00\x00\x00p\xb5\x00\x000\x00\x00\x00\xa1\xb5\x00\x00\"\x00\x00\x00\u04b5\x00\x00?\x00\x00\x00\xf5\xb5\x00\x00\x1d\x00\x00\x005\xb6\x00\x00,\x00\x00\x00S\xb6\x00\x00+\x00\x00\x00\x80\xb6\x00\x00$\x00\x00\x00\xac\xb6\x00\x00\x14\x00\x00\x00\u0476\x00\x00*\x00\x00\x00\xe6\xb6\x00\x00A\x00\x00\x00\x11\xb7\x00\x00\x1d\x00\x00\x00S\xb7\x00\x00\x1c\x00\x00\x00q\xb7\x00\x00\x1a\x00\x00\x00\x8e\xb7\x00\x00)\x00\x00\x00\xa9\xb7\x00\x006\x00\x00\x00\u04f7\x00\x00\x1d\x00\x00\x00\n\xb8\x00\x00\x19\x00\x00\x00(\xb8\x00\x00 \x00\x00\x00B\xb8\x00\x00v\x00\x00\x00c\xb8\x00\x00(\x00\x00\x00\u06b8\x00\x00\x16\x00\x00\x00\x03\xb9\x00\x00p\x00\x00\x00\x1a\xb9\x00\x00`\x00\x00\x00\x8b\xb9\x00\x00\x9b\x00\x00\x00\xec\xb9\x00\x00\x97\x00\x00\x00\x88\xba\x00\x00\xa8\x00\x00\x00 \xbb\x00\x00\x1b\x00\x00\x00\u027b\x00\x00\x18\x00\x00\x00\xe5\xbb\x00\x00\x1a\x00\x00\x00\xfe\xbb\x00\x00$\x00\x00\x00\x19\xbc\x00\x00\x1d\x00\x00\x00>\xbc\x00\x00\x17\x00\x00\x00\\\xbc\x00\x00a\x00\x00\x00t\xbc\x00\x00s\x00\x00\x00\u05bc\x00\x00B\x00\x00\x00J\xbd\x00\x00Y\x00\x00\x00\x8d\xbd\x00\x00+\x00\x00\x00\xe7\xbd\x00\x00+\x00\x00\x00\x13\xbe\x00\x006\x00\x00\x00?\xbe\x00\x00;\x00\x00\x00v\xbe\x00\x00q\x00\x00\x00\xb2\xbe\x00\x00/\x00\x00\x00$\xbf\x00\x001\x00\x00\x00T\xbf\x00\x00'\x00\x00\x00\x86\xbf\x00\x00'\x00\x00\x00\xae\xbf\x00\x00\x18\x00\x00\x00\u05bf\x00\x00&\x00\x00\x00\xef\xbf\x00\x00%\x00\x00\x00\x16\xc0\x00\x00(\x00\x00\x00<\xc0\x00\x00#\x00\x00\x00e\xc0\x00\x00K\x00\x00\x00\x89\xc0\x00\x00 \x00\x00\x00\xd5\xc0\x00\x00_\x00\x00\x00\xf6\xc0\x00\x00\x1e\x00\x00\x00V\xc1\x00\x00\"\x00\x00\x00u\xc1\x00\x00\"\x00\x00\x00\x98\xc1\x00\x00\x1f\x00\x00\x00\xbb\xc1\x00\x00-\x00\x00\x00\xdb\xc1\x00\x00-\x00\x00\x00\t\xc2\x00\x009\x00\x00\x007\xc2\x00\x00\x1e\x00\x00\x00q\xc2\x00\x00\x19\x00\x00\x00\x90\xc2\x00\x00c\x00\x00\x00\xaa\xc2\x00\x00#\x00\x00\x00\x0e\xc3\x00\x00\x82\x00\x00\x002\xc3\x00\x00\x94\x00\x00\x00\xb5\xc3\x00\x00H\x00\x00\x00J\xc4\x00\x00&\x00\x00\x00\x93\xc4\x00\x00e\x00\x00\x00\xba\xc4\x00\x00z\x00\x00\x00 \xc5\x00\x00J\x00\x00\x00\x9b\xc5\x00\x00\xe5\x00\x00\x00\xe6\xc5\x00\x00W\x00\x00\x00\xcc\xc6\x00\x00E\x00\x00\x00$\xc7\x00\x00a\x00\x00\x00j\xc7\x00\x00v\x00\x00\x00\xcc\xc7\x00\x00\xcb\x00\x00\x00C\xc8\x00\x00\xcf\x00\x00\x00\x0f\xc9\x00\x00\x1e\x01\x00\x00\xdf\xc9\x00\x00\x1c\x00\x00\x00\xfe\xca\x00\x00T\x00\x00\x00\x1b\xcb\x00\x00\x17\x00\x00\x00p\xcb\x00\x00/\x00\x00\x00\x88\xcb\x00\x009\x00\x00\x00\xb8\xcb\x00\x00\x1e\x00\x00\x00\xf2\xcb\x00\x00=\x00\x00\x00\x11\xcc\x00\x00$\x00\x00\x00O\xcc\x00\x00\x1f\x00\x00\x00t\xcc\x00\x00&\x00\x00\x00\x94\xcc\x00\x00+\x00\x00\x00\xbb\xcc\x00\x00G\x00\x00\x00\xe7\xcc\x00\x00\x14\x00\x00\x00/\xcd\x00\x00r\x00\x00\x00D\xcd\x00\x00\x13\x00\x00\x00\xb7\xcd\x00\x00\x18\x00\x00\x00\xcb\xcd\x00\x00/\x00\x00\x00\xe4\xcd\x00\x00\xc9\x01\x00\x00\x14\xce\x00\x00\xde\x00\x00\x00\xde\xcf\x00\x00\xb9\x00\x00\x00\xbd\xd0\x00\x00*\x02\x00\x00w\xd1\x00\x00/\x01\x00\x00\xa2\xd3\x00\x00\x87\x00\x00\x00\xd2\xd4\x00\x00v\x02\x00\x00Z\xd5\x00\x00\x9d\x01\x00\x00\xd1\xd7\x00\x00\xaa\x01\x00\x00o\xd9\x00\x00z\x01\x00\x00\x1a\xdb\x00\x00|\x01\x00\x00\x95\xdc\x00\x00L\x01\x00\x00\x12\xde\x00\x00\x06\x02\x00\x00_\xdf\x00\x00~\x01\x00\x00f\xe1\x00\x00j\x05\x00\x00\xe5\xe2\x00\x00\x96\x02\x00\x00P\xe8\x00\x00#\x02\x00\x00\xe7\xea\x00\x00\x8c\x01\x00\x00\v\xed\x00\x00\xd1\x01\x00\x00\x98\xee\x00\x00\t\x02\x00\x00j\xf0\x00\x00+\x02\x00\x00t\xf2\x00\x00\xc1\x00\x00\x00\xa0\xf4\x00\x00\xe0\x02\x00\x00b\xf5\x00\x00\xd1\x03\x00\x00C\xf8\x00\x00\xbc\x01\x00\x00\x15\xfc\x00\x00E\x00\x00\x00\xd2\xfd\x00\x00F\x00\x00\x00\x18\xfe\x00\x00\x13\x03\x00\x00_\xfe\x00\x00A\x00\x00\x00s\x01\x01\x00K\x00\x00\x00\xb5\x01\x01\x00P\x00\x00\x00\x01\x02\x01\x00=\x00\x00\x00R\x02\x01\x00\xd3\x01\x00\x00\x90\x02\x01\x00)\x03\x00\x00d\x04\x01\x00\x1c\x02\x00\x00\x8e\a\x01\x00\x02\x02\x00\x00\xab\t\x01\x00\xf5\x01\x00\x00\xae\v\x01\x00\x8b\x01\x00\x00\xa4\r\x01\x00W\x01\x00\x000\x0f\x01\x00\xe2\x06\x00\x00\x88\x10\x01\x00#\x02\x00\x00k\x17\x01\x00\f\x03\x00\x00\x8f\x19\x01\x00\n\x03\x00\x00\x9c\x1c\x01\x00\x1e\x01\x00\x00\xa7\x1f\x01\x00\xc0\x01\x00\x00\xc6 \x01\x00\xf9\x01\x00\x00\x87\"\x01\x00\x17\x00\x00\x00\x81$\x01\x00=\x00\x00\x00\x99$\x01\x00>\x00\x00\x00\xd7$\x01\x00\xe0\x00\x00\x00\x16%\x01\x00\xbc\x02\x00\x00\xf7%\x01\x00/\x00\x00\x00\xb4(\x01\x00\x96\x03\x00\x00\xe4(\x01\x00h\x00\x00\x00{,\x01\x00S\x00\x00\x00\xe4,\x01\x00T\x00\x00\x008-\x01\x00(\x00\x00\x00\x8d-\x01\x00\xbe\x02\x00\x00\xb6-\x01\x005\x00\x00\x00u0\x01\x00\x82\x00\x00\x00\xab0\x01\x00\x98\x01\x00\x00.1\x01\x00^\b\x00\x00\xc72\x01\x00}\x01\x00\x00&;\x01\x00\x93\x00\x00\x00\xa4<\x01\x00\x1f\x01\x00\x008=\x01\x00\xec\x00\x00\x00X>\x01\x00F\x05\x00\x00E?\x01\x00\xf3\x05\x00\x00\x8cD\x01\x00+\x00\x00\x00\x80J\x01\x001\x00\x00\x00\xacJ\x01\x00\xf7\x02\x00\x00\xdeJ\x01\x00\xd3\x01\x00\x00\xd6M\x01\x00\xc2\x01\x00\x00\xaaO\x01\x00\x88\x01\x00\x00mQ\x01\x00'\x01\x00\x00\xf6R\x01\x00\xff\x01\x00\x00\x1eT\x01\x00=\x01\x00\x00\x1eV\x01\x00\xc2\x01\x00\x00\\W\x01\x00c\x02\x00\x00\x1fY\x01\x00\xdb\x00\x00\x00\x83[\x01\x00\x01\x03\x00\x00_\\\x01\x00\xa9\x00\x00\x00a_\x01\x00^\x00\x00\x00\v`\x01\x00N\x02\x00\x00j`\x01\x00u\x00\x00\x00\xb9b\x01\x00}\x00\x00\x00/c\x01\x00)\x01\x00\x00\xadc\x01\x00\x8b\x00\x00\x00\xd7d\x01\x00}\x00\x00\x00ce\x01\x00\x06\x01\x00\x00\xe1e\x01\x00\x84\x00\x00\x00\xe8f\x01\x00s\x00\x00\x00mg\x01\x00\xf0\x01\x00\x00\xe1g\x01\x00\x13\x04\x00\x00\xd2i\x01\x00;\x00\x00\x00\xe6m\x01\x008\x00\x00\x00\"n\x01\x002\x00\x00\x00[n\x01\x009\x00\x00\x00\x8en\x01\x00\xd5\x02\x00\x00\xc8n\x01\x00\xc8\x00\x00\x00\x9eq\x01\x00p\x00\x00\x00gr\x01\x00]\x00\x00\x00\xd8r\x01\x00l\x00\x00\x006s\x01\x00\xba\x00\x00\x00\xa3s\x01\x00B\x00\x00\x00^t\x01\x00\xca\x00\x00\x00\xa1t\x01\x00\xb5\x00\x00\x00lu\x01\x00\xe6\x00\x00\x00\"v\x01\x007\x00\x00\x00\tw\x01\x00.\x00\x00\x00Aw\x01\x00r\x00\x00\x00pw\x01\x00$\x00\x00\x00\xe3w\x01\x00<\x00\x00\x00\bx\x01\x00\x86\x00\x00\x00Ex\x01\x00:\x00\x00\x00\xccx\x01\x003\x00\x00\x00\ay\x01\x00\xc6\x00\x00\x00;y\x01\x00=\x00\x00\x00\x02z\x01\x000\x00\x00\x00@z\x01\x009\x00\x00\x00qz\x01\x00 \x00\x00\x00\xabz\x01\x00\x1a\x00\x00\x00\xccz\x01\x009\x00\x00\x00\xe7z\x01\x00\x12\x00\x00\x00!{\x01\x00\x1b\x00\x00\x004{\x01\x00H\x00\x00\x00P{\x01\x00-\x00\x00\x00\x99{\x01\x00)\x00\x00\x00\xc7{\x01\x006\x00\x00\x00\xf1{\x01\x00'\x00\x00\x00(|\x01\x00&\x00\x00\x00P|\x01\x003\x00\x00\x00w|\x01\x00E\x00\x00\x00\xab|\x01\x004\x00\x00\x00\xf1|\x01\x005\x00\x00\x00&}\x01\x007\x00\x00\x00\\}\x01\x00\x1e\x00\x00\x00\x94}\x01\x00g\x00\x00\x00\xb3}\x01\x00-\x00\x00\x00\x1b~\x01\x00-\x00\x00\x00I~\x01\x00+\x00\x00\x00w~\x01\x00A\x00\x00\x00\xa3~\x01\x00\x1b\x00\x00\x00\xe5~\x01\x007\x00\x00\x00\x01\u007f\x01\x007\x00\x00\x009\u007f\x01\x00/\x00\x00\x00q\u007f\x01\x00#\x00\x00\x00\xa1\u007f\x01\x00(\x00\x00\x00\xc5\u007f\x01\x00P\x00\x00\x00\xee\u007f\x01\x00\x1d\x00\x00\x00?\x80\x01\x00\x1d\x00\x00\x00]\x80\x01\x00\x1c\x00\x00\x00{\x80\x01\x00,\x00\x00\x00\x98\x80\x01\x00F\x00\x00\x00\u0140\x01\x00!\x00\x00\x00\f\x81\x01\x00\x1c\x00\x00\x00.\x81\x01\x00#\x00\x00\x00K\x81\x01\x00\x88\x00\x00\x00o\x81\x01\x00(\x00\x00\x00\xf8\x81\x01\x00\x1b\x00\x00\x00!\x82\x01\x00u\x00\x00\x00=\x82\x01\x00e\x00\x00\x00\xb3\x82\x01\x00\xb4\x00\x00\x00\x19\x83\x01\x00\xab\x00\x00\x00\u0383\x01\x00\xc0\x00\x00\x00z\x84\x01\x00\x1e\x00\x00\x00;\x85\x01\x00)\x00\x00\x00Z\x85\x01\x00-\x00\x00\x00\x84\x85\x01\x00$\x00\x00\x00\xb2\x85\x01\x00&\x00\x00\x00\u05c5\x01\x00\x1a\x00\x00\x00\xfe\x85\x01\x00e\x00\x00\x00\x19\x86\x01\x00\x93\x00\x00\x00\u007f\x86\x01\x00M\x00\x00\x00\x13\x87\x01\x00g\x00\x00\x00a\x87\x01\x003\x00\x00\x00\u0247\x01\x007\x00\x00\x00\xfd\x87\x01\x00D\x00\x00\x005\x88\x01\x00@\x00\x00\x00z\x88\x01\x00\x84\x00\x00\x00\xbb\x88\x01\x009\x00\x00\x00@\x89\x01\x001\x00\x00\x00z\x89\x01\x00$\x00\x00\x00\xac\x89\x01\x00+\x00\x00\x00\u0449\x01\x00\x1f\x00\x00\x00\xfd\x89\x01\x00$\x00\x00\x00\x1d\x8a\x01\x00+\x00\x00\x00B\x8a\x01\x00*\x00\x00\x00n\x8a\x01\x00+\x00\x00\x00\x99\x8a\x01\x00V\x00\x00\x00\u014a\x01\x000\x00\x00\x00\x1c\x8b\x01\x00s\x00\x00\x00M\x8b\x01\x00%\x00\x00\x00\xc1\x8b\x01\x00&\x00\x00\x00\xe7\x8b\x01\x00&\x00\x00\x00\x0e\x8c\x01\x00%\x00\x00\x005\x8c\x01\x00/\x00\x00\x00[\x8c\x01\x000\x00\x00\x00\x8b\x8c\x01\x00B\x00\x00\x00\xbc\x8c\x01\x00\x1b\x00\x00\x00\xff\x8c\x01\x00\x19\x00\x00\x00\x1b\x8d\x01\x00i\x00\x00\x005\x8d\x01\x00(\x00\x00\x00\x9f\x8d\x01\x00\x8f\x00\x00\x00\u020d\x01\x00\xa3\x00\x00\x00X\x8e\x01\x00P\x00\x00\x00\xfc\x8e\x01\x00#\x00\x00\x00M\x8f\x01\x00i\x00\x00\x00q\x8f\x01\x00\x85\x00\x00\x00\u06cf\x01\x00M\x00\x00\x00a\x90\x01\x00\x03\x01\x00\x00\xaf\x90\x01\x00i\x00\x00\x00\xb3\x91\x01\x00P\x00\x00\x00\x1d\x92\x01\x00X\x00\x00\x00n\x92\x01\x00u\x00\x00\x00\u01d2\x01\x00\xed\x00\x00\x00=\x93\x01\x00\xf8\x00\x00\x00+\x94\x01\x00H\x01\x00\x00$\x95\x01\x00\x19\x00\x00\x00m\x96\x01\x00^\x00\x00\x00\x87\x96\x01\x00\x1d\x00\x00\x00\xe6\x96\x01\x00,\x00\x00\x00\x04\x97\x01\x00=\x00\x00\x001\x97\x01\x00$\x00\x00\x00o\x97\x01\x00C\x00\x00\x00\x94\x97\x01\x00\x1f\x00\x00\x00\u0617\x01\x00\x1d\x00\x00\x00\xf8\x97\x01\x00$\x00\x00\x00\x16\x98\x01\x004\x00\x00\x00;\x98\x01\x00V\x00\x00\x00p\x98\x01\x00 \x00\x00\x00\u01d8\x01\x00\x82\x00\x00\x00\xe8\x98\x01\x00\x16\x00\x00\x00k\x99\x01\x00\x19\x00\x00\x00\x82\x99\x01\x002\x00\x00\x00\x9c\x99\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\xc4\x00\x00\x00\x0f\x00\x00\x00\xc3\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\xeb\x00\x00\x00c\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00o\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x98\x00\x00\x00U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb\x00\x00\x00\x17\x00\x00\x00u\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\xb7\x00\x00\x00\xd7\x00\x00\x00*\x00\x00\x00\x99\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x84\x00\x00\x00\x9c\x00\x00\x00\xe6\x00\x00\x00\x9d\x00\x00\x00\xc5\x00\x00\x00\xd9\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\xcd\x00\x00\x00\xcb\x00\x00\x00y\x00\x00\x00\x97\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x93\x00\x00\x00\xad\x00\x00\x00\xe1\x00\x00\x00\xa6\x00\x00\x00\xd0\x00\x00\x00r\x00\x00\x00+\x00\x00\x006\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00h\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xd1\x00\x00\x00\xde\x00\x00\x00;\x00\x00\x00\x00\x00\x00\x00\xe9\x00\x00\x00\xe7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00/\x00\x00\x00V\x00\x00\x00\x8d\x00\x00\x00\xe3\x00\x00\x00!\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x00\x00\x00\x88\x00\x00\x00l\x00\x00\x00s\x00\x00\x00g\x00\x00\x00\x05\x00\x00\x00\xc6\x00\x00\x00#\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00\x00\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x00\x00S\x00\x00\x00G\x00\x00\x00$\x00\x00\x00\xc1\x00\x00\x00\xb5\x00\x00\x00X\x00\x00\x00m\x00\x00\x00\t\x00\x00\x00x\x00\x00\x00\xb8\x00\x00\x00\xbd\x00\x00\x00k\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00E\x00\x00\x00\xbf\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x82\x00\x00\x00\x81\x00\x00\x00&\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00I\x00\x00\x00e\x00\x00\x00\x04\x00\x00\x00>\x00\x00\x00\b\x00\x00\x00\x94\x00\x00\x00\x8f\x00\x00\x00\xce\x00\x00\x00?\x00\x00\x00Y\x00\x00\x00\xda\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x004\x00\x00\x00\xcc\x00\x00\x00\f\x00\x00\x005\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00 \x00\x00\x00)\x00\x00\x00\xcf\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00Z\x00\x00\x00\"\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00]\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00j\x00\x00\x008\x00\x00\x00\xa3\x00\x00\x00q\x00\x00\x00t\x00\x00\x00_\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00@\x00\x00\x00\xd2\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x95\x00\x00\x00\x06\x00\x00\x00\xa8\x00\x00\x00\xae\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x0e\x00\x00\x00{\x00\x00\x00\xa7\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00w\x00\x00\x00\x12\x00\x00\x00=\x00\x00\x00\xaf\x00\x00\x00\a\x00\x00\x00\xdf\x00\x00\x00\xc0\x00\x00\x00N\x00\x00\x00%\x00\x00\x009\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\xbe\x00\x00\x00\xe2\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\xb3\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00D\x00\x00\x00B\x00\x00\x00n\x00\x00\x00\x00\x00\x00\x00\xd6\x00\x00\x00\x83\x00\x00\x00\n\x00\x00\x00W\x00\x00\x00\x14\x00\x00\x00Q\x00\x00\x00\xd4\x00\x00\x00d\x00\x00\x00\xac\x00\x00\x00\x16\x00\x00\x00\x96\x00\x00\x00K\x00\x00\x002\x00\x00\x00\x1a\x00\x00\x00\xb4\x00\x00\x00f\x00\x00\x00\xa2\x00\x00\x00\xe8\x00\x00\x00\x02\x00\x00\x00A\x00\x00\x00\xe4\x00\x00\x00\x8c\x00\x00\x00\x9a\x00\x00\x00`\x00\x00\x00\xab\x00\x00\x00M\x00\x00\x007\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9b\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\xdd\x00\x00\x00\x8e\x00\x00\x00\xca\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x003\x00\x00\x00T\x00\x00\x00\x87\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\xaa\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x00\xc7\x00\x00\x00\x8b\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: kubernetes\nReport-Msgid-Bugs-To: EMAIL\nPOT-Creation-Date: 2017-03-14 21:32-0700\nPO-Revision-Date: 2017-08-28 15:20+0200\nLanguage: it_IT\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n != 1);\nLast-Translator: Luca Berton \nLanguage-Team: Luca Berton \nX-Generator: Poedit 1.8.7.1\nX-Poedit-SourceCharset: UTF-8\n\x00\n\t\t # Creare un ClusterRoleBinding per user1, user2 e group1 utilizzando il cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Crea un RoleBinding per user1, user2, and group1 utilizzando l'admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Crea un nuovo configmap denominato my-config in base alla cartella bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Crea un nuovo configmap denominato my-config con le chiavi specificate anzich\u00e9 i nomi dei file su disco\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Crea un nuovo configmap denominato my-config con key1 = config1 e key2 = config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # Se non si dispone ancora di un file .dockercfg, \u00e8 possibile creare un secret dockercfg direttamente utilizzando:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Mostra metriche per tutti i nodi\n\t\t kubectl top node\n\n\t\t # Mostra metriche per un determinato nodo\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Applica la configurazione pod.json a un pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Applicare il JSON passato in stdin a un pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Nota: --prune \u00e8 ancora in in Alpha\n\t\t# Applica la configurazione manifest.yaml che corrisponde alla label app = nginx ed elimina tutte le altre risorse che non sono nel file e nella label corrispondente app = nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Applica la configurazione manifest.yaml ed elimina tutti gli altri configmaps non presenti nel file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale un deployment \"foo\", con il numero di pod compresi tra 2 e 10, utilizzo della CPU target specificato in modo da utilizzare una politica di autoscaling predefinita:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale un controller di replica \"foo\", con il numero di pod compresi tra 1 e 5, utilizzo dell'utilizzo della CPU a 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Converte 'pod.yaml' alla versione pi\u00f9 recente e stampa in stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Converte lo stato live della risorsa specificata da 'pod.yaml' nella versione pi\u00f9 recente.\n\t\t# e stampa in stdout nel formato json.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Converte tutti i file nella directory corrente alla versione pi\u00f9 recente e li crea tutti.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Crea un ClusterRole denominato \"pod-reader\" che consente all'utente di eseguire \"get\", \"watch\" e \"list\" sui pod\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Crea un ClusterRole denominato \"pod-reader\" con ResourceName specificato\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Crea un ruolo denominato \"pod-reader\" che consente all'utente di eseguire \"get\", \"watch\" e \"list\" sui pod\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Crea un ruolo denominato \"pod-reader\" con ResourceName specificato\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Crea una nuova resourcequota chiamata my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Creare una nuova resourcequota denominata best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Crea un pod disruption budget chiamato my-pdb che seleziona tutti i pod con label app = rail\n\t\t# e richiede che almeno uno di essi sia disponibile in qualsiasi momento.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Crea un pod disruption budget con nome my-pdb che seleziona tutti i pod con label app = nginx \n\t\t# e richiede che almeno la met\u00e0 dei pod selezionati sia disponibile in qualsiasi momento.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Crea un pod utilizzando i dati in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Crea un pod basato sul JSON passato in stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Modifica i dati in docker-registry.yaml in JSON utilizzando il formato API v1 quindi creare la risorsa utilizzando i dati modificati.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Crea un servizio per un nginx replicato, che serve nella porta 80 e si collega ai container sulla porta 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Crea un servizio per un controller di replica identificato per tipo e nome specificato in \"nginx-controller.yaml\", che serve nella porta 80 e si collega ai container sulla porta 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Crea un servizio per un pod valid-pod, che serve nella porta 444 con il nome \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Crea un secondo servizio basato sul servizio sopra, esponendo la porta container 8443 come porta 443 con il nome \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Crea un servizio per un'applicazione di replica in porta 4100 che bilanci il traffico UDP e denominato \"video stream\".\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Crea un servizio per un nginx replicato utilizzando l'insieme di replica, che serve nella porta 80 e si collega ai contenitori sulla porta 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Crea un servizio per una distribuzione di nginx, che serve nella porta 80 e si collega ai contenitori della porta 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Elimina un pod utilizzando il tipo e il nome specificati in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Elimina un pod in base al tipo e al nome del JSON passato in stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Elimina i baccelli ei servizi con gli stessi nomi \"baz\" e \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Elimina i baccelli ei servizi con il nome dell'etichetta = myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Eliminare un pod con un ritardo minimo\n\t\tkubectl delete pod foo --now\n\n\t\t# Forza elimina un pod in un nodo morto\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Elimina tutti i pod\n\t\tkubectl delete pods --all\x00\n\t\t# Descrive un nodo\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Descrive un pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Descrive un pod identificato da tipo e nome in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Descrive tutti i pod\n\t\tkubectl describe pods\n\n\t\t# Descrive i pod con label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Descrivere tutti i pod gestiti dal controller di replica \"frontend\" (rc-created pods\n\t\t# ottiene il nome del rc come un prefisso del nome pod).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", anche se ci sono i baccelli non gestiti da ReplicationController, ReplicaSet, Job, DaemonSet o StatefulSet su di esso.\n\t\t$ kubectl drain foo --force\n\n\t\t# Come sopra, ma interrompere se ci sono i baccelli non gestiti da ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, e utilizzare un periodo di grazia di 15 minuti.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Modifica il servizio denominato 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Usa un editor alternativo\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Modifica il lavoro 'myjob' in JSON utilizzando il formato API v1:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Modifica la distribuzione 'mydeployment' in YAML e salvare la configurazione modificata nella sua annotazione:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Ottieni l'output dalla 'data' di esecuzione del pod 123456-7890, utilizzando il primo contenitore per impostazione predefinita\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Ottieni l'output dalla data di esecuzione in ruby-container del pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Passare alla modalit\u00e0 raw terminal, invia stdin a 'bash' in ruby-container del pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Ottieni l'output dal pod 123456-7890 in esecuzione, utilizzando il primo contenitore per impostazione predefinita\n\t\tkubectl attach 123456-7890\n\n\t\t# Ottieni l'output dal ruby-container del pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Passa alla modalit\u00e0 raw terminal, invia stdin a 'bash' in ruby-container del pod 123456-7890\n\t\t# e invia stdout/stderr da 'bash' al client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Ottieni l'output dal primo pod di una ReplicaSet denominata nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Ottieni la documentazione della risorsa e i relativi campi\n\t\tkubectl explain pods\n\n\t\t# Ottieni la documentazione di un campo specifico di una risorsa\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Installa il completamento di bash su un Mac utilizzando homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Carica il codice di completamento kubectl per bash nella shell corrente\n\t\tsource <(kubectl completion bash)\n\n\t\t# Scrive il codice di completamento bash in un file e lo carica da .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Carica il codice di completamento kubectl per zsh [1] nella shell corrente\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# Elenca tutti i pod in formato output ps.\n\t\tkubectl get pods\n\n\t\t# Elenca tutti i pod in formato output ps con maggiori informazioni (ad esempio il nome del nodo).\n\t\tkubectl get pods -o wide\n\n\t\t# Elenca un controller di replica singolo con NAME specificato nel formato di output ps.\n\t\tkubectl get replicationcontroller web\n\n\t\t# Elenca un singolo pod nel formato di uscita JSON.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# Elenca un pod identificato per tipo e nome specificato in \"pod.yaml\" nel formato di uscita JSON.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Restituisce solo il valore di fase del pod specificato.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# Elenca tutti i controller e servizi di replica insieme in formato output ps.\n\t\tkubectl get rc,services\n\n\t\t# Elenca una o pi\u00f9 risorse per il tipo e per i nomi.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# Elenca tutte le risorse con tipi diversi.\n\t\tkubectl get all\x00\n\t\t# Ascolta localmente le porte 5000 e 6000, inoltrando i dati da/verso le porte 5000 e 6000 nel pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Ascolta localmente la porta 8888, inoltra a 5000 nel pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Ascolta localmente una porta casuale, inoltra a 5000 nel pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Ascolta localmente una porta casuale, inoltra a 5000 nel pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Segna il nodo \"foo\" come programmabile.\n\t\t$ Kubectl uncordon foo\x00\n\t\t# Segna il nodo \"foo\" come non programmabile.\n\t\tkubectl cordon foo\x00\n\t\t# Aggiorna parzialmente un nodo utilizzando merge patch strategica\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Aggiorna parzialmente un nodo identificato dal tipo e dal nome specificato in \"node.json\" utilizzando merge patch strategica\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Aggiorna l'immagine di un contenitore; spec.containers [*]. name \u00e8 richiesto perch\u00e9 \u00e8 una chiave di fusione\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Aggiorna l'immagine di un contenitore utilizzando una patch json con array posizionali\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Stampa i flag ereditati da tutti i comandi\n\t\tkubectl options\x00\n\t\t# Stampa l'indirizzo dei servizi master e cluster\n\t\tkubectl cluster-info\x00\n\t\t# Stampa le versioni client e server per il current context\n\t\tkubectl version\x00\n\t\t# Stampa le versioni API supportate\n\t\tkubectl api-versions\x00\n\t\t# Sostituire un pod utilizzando i dati in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Sostituire un pod usando il JSON passato da stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Aggiorna la versione dell'immagine (tag) di un singolo container di pod a v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Forza la sostituzione, cancellazione e quindi ricreare la risorsa\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Restituisce snapshot log dal pod nginx con un solo container\n\t\tkubectl logs nginx\n\n\t\t# Restituisce snapshot log dei pod definiti dalla label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Restituisce snapshot log del container ruby terminato nel pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Iniziare a trasmettere i log del contenitore ruby nel pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Visualizza solo le ultime 20 righe di output del pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Mostra tutti i log del pod nginx scritti nell'ultima ora\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Restituisce snapshot log dal primo contenitore di un lavoro chiamato hello\n\t\tkubectl logs job/hello\n\n\t\t# Restituisce snapshot logs del container nginx-1 del deployment chiamato nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Esegui un proxy verso kubernetes apiserver sulla porta 8011, che fornisce contenuti statici da ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Esegui un proxy verso kubernetes apiserver su una porta locale arbitraria.\n\t\t# La porta selezionata per il server verr\u00e0 inviata a stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Esegui un proxy verso kubernetes apiserver, cambiando il prefisso api in k8s-api\n\t\t# Questo comporta, ad es., pod api disponibili presso localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scala un replicaset denominato 'foo' a 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scala una risorsa identificata per tipo e nome specificato in \"foo.yaml\" a 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# Se la distribuzione corrente di mysql \u00e8 2, scala mysql a 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scalare pi\u00f9 controllori di replica.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scala il lavoro denominato 'cron' a 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Imposta l'ultima-configurazione-applicata di una risorsa che corrisponda al contenuto di un file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Esegue set-last-applied per ogni file di configurazione in una directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Imposta la configurazione dell'ultima applicazione di una risorsa che corrisponda al contenuto di un file, creer\u00e0 l'annotazione se non esiste gi\u00e0.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Mostra metriche di tutti i pod nello spazio dei nomi predefinito\n\t\tkubectl top pod\n\n\t\t# Mostra metriche di tutti i pod nello spazio dei nomi specificato\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Mostra metriche per un pod e i suoi relativi container\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Mostra metriche per i pod definiti da label name = myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Spegni foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop di tutti i pod e servizi con label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Spegnere il servizio definito in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Spegnere tutte le resources in path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Avviare un'unica istanza di nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Avviare un'unica istanza di hazelcast e lasciare che il container esponga la porta 5701.\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Avviare una singola istanza di hazelcast ed imposta le variabili ambiente \"DNS_DOMAIN=cluster\" e \"POD_NAMESPACE=default\" nel container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Avviare un'istanza replicata di nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Stampare gli oggetti API corrispondenti senza crearli.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Avviare un'unica istanza di nginx, ma overload le spec del deployment con un insieme parziale di valori analizzati da JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Avviare un pod di busybox e tenerlo in primo piano, non riavviarlo se esce.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Avviare il container nginx utilizzando il comando predefinito, ma utilizzare argomenti personalizzati (arg1 .. argN) per quel comando.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Avviare il container nginx utilizzando un diverso comando e argomenti personalizzati.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Avviare il contenitore perl per calcolare \u03c0 a 2000 posti e stamparlo.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Avviare il cron job per calcolare \u03c0 a 2000 posti e stampare ogni 5 minuti.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Aggiorna il nodo \"foo\" con un marcatore con il tasto 'dedicated' e il valore 'special-user' ed effettua 'NoSchedule'.\n\t\t# Se un marcatore con quel tasto e l'effetto gi\u00e0 esiste, il suo valore viene sostituito come specificato.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Rimuove dal nodo 'foo' il marcatore con il tasto 'dedicated' ed effettua 'NoSchedule' se esiste.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Rimuovi dal nodo 'foo' tutti i marcatori con chiave 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Aggiorna il pod 'foo' con l'etichetta 'unhealthy' e il valore 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Aggiorna il pod 'foo' con l'etichetta 'status' e il valore 'unhealthy', sovrascrivendo qualsiasi valore esistente.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Aggiorna tutti i pod nello spazio dei nomi\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Aggiorna un pod identificato dal tipo e dal nome in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Aggiorna il pod 'foo' solo se la risorsa \u00e8 invariata dalla versione 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Aggiorna il pod 'foo' rimuovendo un'etichetta denominata 'bar' se esiste.\n\t\t# Non richiede la flag -overwrite.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Aggiorna i pod di frontend-v1 usando i dati del replication controller in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Aggiorna i pod di frontend-v1 usando i dati JSON passati da stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Aggiorna i pod di frontend-v1 in frontend-v2 solo cambiando l'immagine e modificando\n\t\t# il nome del replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Aggiorna i pod di frontend solo cambiando l'immaginee mantenendo il vecchio none.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Interrompee ed invertire un rollout esistente in corso (da frontend-v1 a frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# Visualizza le annotazioni dell'ultima-configurazione-applicata per tipo/nome in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# # Visualizza le annotazioni dell'ultima-configurazione-applicata per file in JSON.\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApplicare una configurazione a una risorsa per nomefile o stdin.\n\t\tQuesta risorsa verr\u00e0 creata se non esiste ancora.\n\t\tPer utilizzare 'apply', creare sempre la risorsa inizialmente con 'apply' o 'create --save-config'.\n\n\t\tSono accettati i formati JSON e YAML.\n\n\t\tDisclaimer Alpha: la funzionalit\u00e0 --prune non \u00e8 ancora completa. Non utilizzare a meno che non si sia a conoscenza di quale sia lo stato attuale. Vedi https://issues.k8s.io/34274.\x00\n\t\tConvertire i file di configurazione tra diverse versioni API. Sono\n\t\taccettati i formati YAML e JSON.\n\n\t\tIl comando prende il nome di file, la directory o l'URL come input e lo converte nel formato\n\t\tdi versione specificata dal flag -output-version. Se la versione di destinazione non \u00e8 specificata o\n\t\tnon supportata, viene convertita nella versione pi\u00f9 recente.\n\n\t\tL'output predefinito verr\u00e0 stampato su stdout nel formato YAML. Si pu\u00f2 usare l'opzione -o\n\t\tper cambiare la destinazione di output.\x00\n\t\nCrea un ClusterRole.\x00\n\t\tCrea un ClusterRoleBinding per un ClusterRole particolare.\x00\n\t\tCrea un RoleBinding per un particolare Ruolo o ClusterRole.\x00\n\t\tCrea un TLS secret dalla coppia di chiavi pubblica/privata.\n\n\t\tLa coppia di chiavi pubblica/privata deve esistere prima. Il certificato chiave pubblica deve essere .PEM codificato e corrispondere alla chiave privata data.\x00\n\t\tCreare un configmap basato su un file, una directory o un valore literal specificato.\n\n\t\tUn singolo configmap pu\u00f2 includere una o pi\u00f9 coppie chiave/valore.\n\n\t\tQuando si crea una configmap basata su un file, il valore predefinito sar\u00e0 il nome di base del file e il valore sar\u00e0\n\t\tpredefinito per il contenuto del file. Se il nome di base \u00e8 una chiave non valida, \u00e8 possibile specificare un tasto alternativo.\n\n\t\tQuando si crea un configmap basato su una directory, ogni file il cui nome di base \u00e8 una chiave valida nella directory verr\u00e0\n\t\tpacchettizzata nel configmap. Le voci di directory tranne i file regolari vengono ignorati (ad esempio sottodirectory,\n\t\tsymlinks, devices, pipes, ecc).\x00\n\t\tCreare un namespace con il nome specificato.\x00\n\t\tCreare un nuovo secret per l'utilizzo con i registri Docker.\n\n\t\tDockercfg secrets vengono utilizzati per autenticare i registri Docker.\n\n\t\tQuando utilizzi la riga di comando Docker per il push delle immagini, \u00e8 possibile eseguire l'autenticazione eseguendo correttamente un determinato registry\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n Questo produce un file ~ / .dockercfg che viene utilizzato dai successivi comandi \"docker push\" e \"docker pull\"\n\t\tper autenticarsi nel registry. L'indirizzo email \u00e8 facoltativo.\n\n\t\tDurante la creazione di applicazioni, \u00e8 possibile avere un Docker registry che richiede l'autenticazione. Affinch\u00e9 i \n\t\tnodi eseguano pull di immagini per vostro conto, devono avere le credenziali. \u00c8 possibile fornire queste informazioni \n\t\tcreando un dockercfg secret e collegandolo al tuo account di servizio.\x00\n\t\tCrea un pod disruption budget con il nome specificato, selector e il numero minimo di pod disponibili\x00\n\t\tCrea una risorsa per nome file o stdin.\n\n\t\tSono accettati i formati JSON e YAML.\x00\n\t\tCrea una resourcequota con il nome specificato, hard limits e gli scope opzionali\x00\n\t\tCrea un ruolo con una singola regola.\x00\n\t\tCrea un secret basato su un file, una directory o un valore specifico literal.\n\n\t\tUn singolo secret pu\u00f2 includere una o pi\u00f9 coppie chiave/valore.\n\n\t\tQuando si crea un secret basato su un file, la chiave per impostazione predefinita sar\u00e0 il nome di base del file e il valore sar\u00e0\n\t\tpredefinito al contenuto del file. Se il nome di base \u00e8 una chiave non valida, \u00e8 possibile specificare un tasto alternativo.\n\n\n\t\tQuando si crea un segreto basato su una directory, ogni file il cui nome di base \u00e8 una chiave valida nella directory verr\u00e0 \n\t\\paccehttizzataw in un secret. Le voci di directory tranne i file regolari vengono ignorati (ad esempio sottodirectory,\n\t\tsymlinks, devices, pipes, ecc).\x00\n\t\tCreare un service account con il nome specificato.\x00\n\t\tCrea ed esegue un'immagine particolare, eventualmente replicata.\n\n\t\tCrea un deployment o un job per gestire i container creati.\x00\n\t\tCrea un autoscaler che automaticamente sceglie e imposta il numero di pod che vengono eseguiti in un cluster di kubernets.\n\n\t\tEsegue una ricerca di un Deployment, ReplicaSet o ReplicationController per nome e crea un autoscaler che utilizza la risorsa indicata come riferimento.\n\t\tUn autoscaler pu\u00f2 aumentare o diminuire automaticamente il numero di pod distribuiti all'interno del sistema se necessario.\x00\n\t\tCancella risorse secondo nomi di file, stdin, risorse e nomi, o per selettori di risorse e etichette.\n\n\t\tSono accettati i formati JSON e YAML. \u00c8 possibile specificare un solo tipo di argomenti: nome file,\n\t\trisorse e nomi, o risorse e selettore di etichette.\n\n\t\tAlcune risorse, come i pod, supportano cacellazione corretta. Queste risorse definiscono un periodo di default\n\t\tprima che siano forzatamente terminate (il grace period) ma si pu\u00f2 sostituire quel valore con\n\t\til falg --grace-period, o passare --now per impostare il grace-period a 1. Poich\u00e9 queste risorse spesso\n\t\trappresentano entit\u00e0 del cluster, la cancellazione non pu\u00f2 essere presa in carico immediatamente. Se il nodo\n\t\tche ospita un pod \u00e8 spento o non raggiungibile da API server, termination pu\u00f2 richiedere molto pi\u00f9 tempo\n\t\tdel grace period. Per forzare la cancellazione di una resource,\tdevi obbligatoriamente indicare un grace\tperiod di 0 e specificare\n\t\til flag --force.\n\n\t\tIMPORTANTE: Fozare la cancellazione dei pod non attende conferma che i processi del pod siano\n\t\tterminati, che pu\u00f2 lasciare questi processi in esecuzione fino a quando il nodo rileva la cancellazione\n\t\tcompletata correttamente. Se i tuoi processi utilizzano l'archiviazione condivisa o parlano con un'API remota e\n\t\tdipendono dal nome del pod per identificarsi, la forzata eliminazione di questi pod pu\u00f2 comportare\n\t\tpi\u00f9 processi in esecuzione su macchine diverse che utilizzando la stessa identificazione che pu\u00f2 portare\n\t\tcorruzione o inconsistenza dei dati. Forza i pod solo quando si \u00e8 sicuri che il pod sia\n\t\tterminato, o se la tua applicazione pu\u00f2 can tollerare pi\u00f9 copie dello stesso pod in esecuzione contemporaneamente.\n\t\tInoltre, se forzate l'eliminazione dei i nodi, lo scheduler pu\u00f2 pu\u00f2 creare nuovi nodi su questi nodi prima che il nodo\n\t\tabbia liberato quelle risorse e provocando immediatamente evict di tali pod.\n\n\n\t\tNotare che il comando di eliminazione NON fa verificare la versione delle risorse, quindi se qualcuno\n\t\tinvia un aggiornamento ad una risorsa quando invii un eliminazione, il loro aggiornamento\n\t\tsaranno persi insieme al resto della risorsa.\x00\n\t\tDeprecated: chiudere correttamente una risorsa per nome o nome file.\n\n\t\tIl comando stop \u00e8 deprecato, tutte le sue funzionalit\u00e0 sono coperte dal comando delete.\n\t\tVedere 'kubectl delete --help' per ulteriori dettagli.\n\n\t\tTenta di arrestare ed eliminare una risorsa che supporta la corretta terminazione.\n\t\tSe la risorsa \u00e8 scalabile, verr\u00e0 scalata a 0 prima dell'eliminazione.\x00\n\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage) dei nodi.\n\n\t\tIl comando top-node consente di visualizzare il consumo di risorse dei nodi.\x00\n\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage) dei pod.\n\n\t\tIl comando \"top pod\" consente di visualizzare il consumo delle risorse dei pod.\n\n\t\tA causa del ritardo della pipeline metrica, potrebbero non essere disponibili per alcuni minuti\n\t\teal momento della creazione dei pod.\x00\n\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage).\n\n\t\tIl comando top consente di visualizzare il consumo di risorse per nodi o pod.\n\n\t\tQuesto comando richiede che Heapster sia configurato correttamente e che funzioni sul server.\x00\n\t\tDrain node in preparazione alla manutenzione.\n\n\t\tIl nodo indicato verr\u00e0 contrassegnato unschedulable per impedire che nuovi pod arrivino.\n\t\t'drain' evict i pod se l'APIServer supporta eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Altrimenti, usa il normale DELETE\n\t\tper eliminare i pod.\n\t\tIl 'drain' evicts o la cancellazione di tutti all pod tranne mirror pods (che non possono essere eliminati\n\t\tattraverso API server). Se ci sono i pod gestiti da DaemonSet, drain non proceder\u00e0\n\t\tsenza --ignore-daemonsets e, a prescindere da ci\u00f2, non canceller\u00e0 alcun\n\t\tpod gestitto da DaemonSet,poich\u00e9 questi pods verrebbero immediatamente sostituiti dal\n\t\tDaemonSet controller, che ignora le marcature unschedulable. Se ci sono\n\t\tpod che non sono n\u00e9 mirror pod n\u00e9 gestiti dal ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet o Job, allora drain non canceller\u00e0 alcun pod finch\u00e9 non\n\t\tuserai --force. --force permetter\u00e0 alla cancellazione di procedere se la risorsa gestita da uno\n\t\to pi\u00f9 pod \u00e8 mancante.\n\n\t\t'drain' attende il termine corretto. Non devi operare sulla macchina finch\u00e9\n\t\til comando non viene completato.\n\n\t\tQuando sei pronto per riportare il nodo al servizio, utilizza kubectl uncordon, per\n\t\trimettere il nodo schedulable nuovamente.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tModificare una risorsa dall'editor predefinito.\n\n\t\tIl comando di modifica consente di modificare direttamente qualsiasi risorsa API che \u00e8 possibile recuperare tramite gli\n\t\tstrumenti di riga di comando. Apre l'editor definito dalle variabili d'ambiente\n\t\tKUBE_EDITOR o EDITOR, o ritornare a 'vi' per Linux o 'notepad' per Windows.\n\t\t\u00c8 possibile modificare pi\u00f9 oggetti, anche se le modifiche vengono applicate una alla volta. Il comando\n\t\taccetta sia nomi di file che argomenti da riga di comando, anche se i file a cui fa riferimento devono\n\t\tessere state salvate precedentemente le versioni delle risorse.\n\n\t\tLa modifica viene eseguita con la versione API utilizzata per recuperare la risorsa.\n\t\tPer modificare utilizzando una specifica versione API, fully-qualify la risorsa, versione e il gruppo.\n\n\t\tIl formato predefinito \u00e8 YAML. Per modificare in JSON, specificare \"-o json\".\n\n\t\tIl flag --windows-line-endings pu\u00f2 essere utilizzato per forzare i fine linea Windows,\n\t\taltrimenti verr\u00e0 utilizzato il default per il sistema operativo.\n\n\t\tNel caso in cui si verifica un errore durante l'aggiornamento, verr\u00e0 creato un file temporaneo sul disco\n\t\tche contiene le modifiche non apportate. L'errore pi\u00f9 comune durante l'aggiornamento di una risorsa\n\t\t\u00e8 una modifica da pare di un altro editor della risorsa sul server. Quando questo si verifica, dovrai\n\t\tapplicare le modifiche alla versione pi\u00f9 recente della risorsa o aggiornare il tua copia\n\t\ttemporanea salvata per includere l'ultima versione delle risorse.\x00\n\t\tContrassegna il nodo come programmabile.\x00\n\t\tContrassegnare il nodo come non programmabile.\x00\n\t\tIn output codice di completamento shell output per la shell specificata (bash o zsh).\n\t\tIl codice di shell deve essere valorizzato per fornire completamento\n\t\tinterattivo dei comandi kubectl. Questo pu\u00f2 essere eseguito richiamandolo\n\t\tda .bash_profile.\n\n\t\tNota: questo richiede il framework di completamento bash, che non \u00e8 installato\n\t\tper impostazione predefinita su Mac. Questo pu\u00f2 essere installato utilizzando homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tUna volta installato, bash_completion deve essere valutato. Ci\u00f2 pu\u00f2 essere fatto aggiungendo la\n\t\tseguente riga al file .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNota per gli utenti zsh: [1] i completamenti zsh sono supportati solo nelle versioni zsh> = 5.2\x00\n\t\tEseguire un rolling update del ReplicationController specificato.\n\n\t\tSostituisce il replication controller specificato con un nuovo replication controller aggiornando un pod alla volta per usare il\n\t\tnuovo PodTemplate. Il new-controller.json deve specificare lo stesso namespace del\n\t\tcontroller di replica esistente e sovrascrivere almeno una etichetta (comune) nella sua replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tSostituire una risorsa per nomefile o stdin.\n\n\t\tSono accettati i formati JSON e YAML. Se si sostituisce una risorsa esistente, \n\t\t\u00e8 necessario fornire la specifica completa delle risorse. Questo pu\u00f2 essere ottenuta da\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tFare riferimento ai modelli https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html per trovare se un campo \u00e8 mutevole.\x00\n\t\tImposta una nuova dimensione per Deployment, ReplicaSet, Replication Controller, o Job.\n\n\t\tScala consente anche agli utenti di specificare una o pi\u00f9 condizioni preliminari per l'azione della scala.\n\n\t\tSe --current-replicas o --resource-version sono specificate, viene convalidata prima di\n\t\ttentare scale, ed \u00e8 garantito che la precondizione vale quando\n\t\tscale viene inviata al server..\x00\n\t\tImposta le annotazioni dell'ultima-configurazione-applicata impostandola in modo che corrisponda al contenuto di un file.\n\t\tCi\u00f2 determina l'aggiornamento dell'ultima-configurazione-applicata come se 'kubectl apply -f ' fosse stato eseguito,\n\t\tsenza aggiornare altre parti dell'oggetto.\x00\n\t\tPer proxy tutti i kubernetes api e nient'altro, utilizzare:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tPer proxy solo una parte dei kubernetes api e anche alcuni file static\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tQuanto sopra consente 'curl localhost:8001/api/v1/pods'.\n\n\t\tPer eseguire il proxy tutti i kubernetes api in una radice diversa, utilizzare:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tQuanto sopra ti permette 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tAggiorna i campi di una risorsa utilizzando la merge patch strategica\n\n\t\tSono accettati i formati JSON e YAML.\n\n\t\tSi prega di fare riferimento ai modelli in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html per trovare se un campo \u00e8 mutevole.\x00\n\t\tAggiorna le label di una risorsa.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tAggiorna i marcatori su uno o pi\u00f9 nodi.\n\n\t\t* Un marcatore \u00e8 costituita da una chiave, un valore e un effetto. Come argomento qui, viene espresso come chiave = valore: effetto.\n\t\t* La chiave deve iniziare con una lettera o un numero e pu\u00f2 contenere lettere, numeri, trattini, punti e sottolineature, fino a% [1] d caratteri.\n\t\t* Il valore deve iniziare con una lettera o un numero e pu\u00f2 contenere lettere, numeri, trattini, punti e sottolineature, fino a% [2] d caratteri.\n\t\t* L'effetto deve essere NoSchedule, PreferNoSchedule o NoExecute.\n\t\t* Attualmente il marcatore pu\u00f2 essere applicato solo al nodo.\x00\n\t\tVisualizza le annotazioni dell'ultima-configurazione-applicata per tipo/nome o file.\n\n\t\tL'output predefinito verr\u00e0 stampato su stdout nel formato YAML. Si pu\u00f2 usare l'opzione -o\n\t\tPer cambiare il formato di output.\x00\n\t # !!!Nota importante!!!\n\t # Richiede che il binario 'tar' sia presente nel tuo contenitore\n\t # immagine. Se 'tar' non \u00e8 presente, 'kubectl cp' non riesce.\n\n\t # Copia /tmp/foo_dir directory locale in /tmp/bar_dir in un pod remoto nello spazio dei nomi predefinito\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copia /tmp/foo file locale in /tmp/bar in un pod remoto in un contenitore specifico\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copia /tmp/foo file locale in /tmp/bar in un pod remoto nello spazio dei nomi \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copia /tmp/foo da un pod remoto in /tmp/bar localmente\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Crea un nuovo secret TLS denominato tls-secret con la coppia di dati fornita:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Crea un nuovo namespace denominato my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Crea un nuovo secret denominato my-secret con i tasti per ogni file nella barra delle cartelle\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Crea un nuovo secret denominato my-secret con le chiavi specificate anzich\u00e9 i nomi sul disco\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Crea un nuovo secret denominato my-secret con key1 = supersecret e key2 = topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Crea un nuovo service account denominato my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Crea un nuovo servizio ExternalName denominato my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCrea un servizio ExternalName con il nome specificato.\n\n\tIl servizio ExternalName fa riferimento a un indirizzo DNS esterno \n\tsolo pod, che permetteranno agli autori delle applicazioni di utilizzare i servizi di riferimento\n\tche esistono fuori dalla piattaforma, su altri cluster, o localmente..\x00\n\tHelp fornisce assistenza per qualsiasi comando nell'applicazione.\n\tBasta digitare kubectl help [path to command] per i dettagli completi.\x00\n # Creare un nuovo servizio LoadBalancer denominato my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Creare un nuovo servizio clusterIP denominato my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Creare un nuovo servizio clusterIP denominato my-cs (in modalit\u00e0 headless)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Crea una nuovo deployment chiamato my-dep che esegue l'immagine busybox.\n kubectl create deployment my-dep --image=busybox\x00\n # Creare un nuovo servizio nodeport denominato my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump dello stato corrente del cluster verso stdout\n kubectl cluster-info dump\n\n # Dump dello stato corrente del cluster verso /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump di tutti i namespaces verso stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump di un set di namespace verso /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Aggiorna il pod 'foo' con annotazione 'description'e il valore 'my frontend'.\n # Se la stessa annotazione \u00e8 impostata pi\u00f9 volte, verr\u00e0 applicato solo l'ultimo valore\n kubectl annotate pods foo description='my frontend'\n\n # Aggiorna un pod identificato per tipo e nome in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Aggiorna pod 'foo' con la annotazione 'description' e il valore 'my frontend running nginx', sovrascrivendo qualsiasi valore esistente.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Aggiorna tutti i baccelli nel namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Aggiorna il pod 'foo' solo se la risorsa \u00e8 invariata dalla versione 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Aggiorna il pod 'foo' rimuovendo un'annotazione denominata 'descrizione' se esiste.\n # Non richiede flag -overwrite.\n kubectl annotate pods foo description-\x00\n Crea un servizio LoadBalancer con il nome specificato.\x00\n Crea un servizio clusterIP con il nome specificato.\x00\n Creare un deployment con il nome specificato.\x00\n Creare un servizio nodeport con il nome specificato.\x00\n Dump delle informazioni di cluster idonee per il debug e la diagnostica di problemi di cluster. Per impostazione predefinita, tutto\n\u00a0\u00a0\u00a0\u00a0verso stdout. \u00c8 possibile specificare opzionalmente una directory con --output-directory. Se si specifica una directory, kubernetes \n creear\u00e0 un insieme di file in quella directory. Per impostazione predefinita, dumps solo i dati del namespace \"kube-system\", ma \u00e8\n possibile passare ad namespace diverso con il flag --namespaces o specificare --all-namespaces per il dump di tutti i namespace.\n\n\u00a0\u00a0\u00a0\u00a0 Il comando esegue dump anche dei log di tutti i pod del cluster, questi log vengono scaricati in directory differenti\n\u00a0\u00a0\u00a0\u00a0 basati sul namespace e sul nome del pod.\x00\n Visualizza gli indirizzi del master e dei servizi con label kubernetes.io/cluster-service=true\n\u00a0\u00a0Per ulteriore debug e diagnosticare i problemi di cluster, utilizzare 'kubectl cluster-info dump'.\x00Un insieme delimitato-da-virgole di quota scopes che devono corrispondere a ciascun oggetto gestito dalla quota.\x00Un insieme delimitato-da-virgola di coppie risorsa = quantit\u00e0 che definiscono un hard limit.\x00Un label selector da utilizzare per questo budget. Sono supportati solo i selettori equality-based selector.\x00Un selettore di label da utilizzare per questo servizio. Sono supportati solo equality-based selector. Se vuota (default) dedurre il selettore dal replication controller o replica set.)\x00Un calendario in formato Cron del lavoro che deve essere eseguito.\x00Indirizzo IP esterno aggiuntivo (non gestito da Kubernetes) da accettare per il servizio. Se questo IP viene indirizzato a un nodo, \u00e8 possibile accedere da questo IP in aggiunta al service IP generato.\x00Un override JSON inline per l'oggetto generato. Se questo non \u00e8 vuoto, viene utilizzato per ignorare l'oggetto generato. Richiede che l'oggetto fornisca un campo valido apiVersion.\x00Un override JSON inline per l'oggetto di servizio generato. Se questo non \u00e8 vuoto, viene utilizzato per ignorare l'oggetto generato. Richiede che l'oggetto fornisca un campo valido apiVersion. Utilizzato solo se --expose \u00e8 true.\x00Applica una configurazione risorsa per nomefile o stdin\x00Approva una richiesta di firma del certificato\x00Assegnare il proprio ClusterIP o impostare su 'None' per un servizio 'headless' (nessun bilanciamento del carico).\x00Collega a un container in esecuzione\x00Auto-scale a Deployment, ReplicaSet, o ReplicationController\x00ClusterIP da assegnare al servizio. Lasciare vuoto per allocare automaticamente o impostare su 'None' per creare un servizio headless.\x00ClusterRole a cui questo ClusterRoleBinding fa riferimento\x00ClusterRole a cui questo RoleBinding fa riferimento\x00Nome container che avr\u00e0 la sua immagine aggiornata. Soltanto rilevante quando --image \u00e8 specificato, altrimenti ignorato. Necessario quando si utilizza --image su un contenitore a pi\u00f9 contenitori\x00Convertire i file di configurazione tra diverse versioni APIs\x00Copiare file e directory da e verso i container.\x00Crea un ClusterRoleBinding per un ClusterRole particolare\x00Creare un servizio LoadBalancer.\x00Crea un servizio NodePort.\x00Crea un RoleBinding per un particolare Role o ClusterRole\x00Crea un secret TLS\x00Crea un servizio clusterIP.\x00Crea un configmap da un file locale, una directory o un valore letterale\x00Creare un deployment con il nome specificato.\x00Crea un namespace con il nome specificato\x00Crea un pod disruption budget con il nome specificato.\x00Crea una quota con il nome specificato.\x00Crea una risorsa per nome file o stdin\x00Crea un secret da utilizzare con un registro Docker\x00Crea un secret da un file locale, una directory o un valore letterale\x00Crea un secret utilizzando un subcommand specificato\x00Creare un account di servizio con il nome specificato\x00Crea un servizio utilizzando il subcommand specificato.\x00Crea un servizio ExternalName.\x00Elimina risorse selezionate per nomi di file, stdin, risorse e nomi, o per risorsa e selettore di label\x00Elimina il cluster specificato dal kubeconfig\x00Elimina il context specificato dal kubeconfig\x00Nega una richiesta di firma del certificato\x00Deprecated: spegne correttamente una risorsa per nome o nome file\x00Descrive uno o pi\u00f9 context\x00Visualizza l'utilizzo di risorse (CPU/Memoria) per nodo\x00Visualizza l'utilizzo di risorse (CPU/Memoria) per pod.\x00Visualizza l'utilizzo di risorse (CPU/Memoria).\x00Visualizza informazioni sul cluster\x00Mostra i cluster definiti nel kubeconfig\x00Visualizza le impostazioni merged di kubeconfig o un file kubeconfig specificato\x00Visualizza una o pi\u00f9 risorse\x00Visualizza il current-context\x00Documentazione delle risorse\x00Drain node in preparazione alla manutenzione\x00Dump di un sacco di informazioni pertinenti per il debug e la diagnosi\x00Modificare una risorsa sul server\x00Email per il registro Docker\x00Esegui un comando in un contenitore\x00Politica esplicita per il pull delle immagini container. Richiesto quando --image \u00e8 uguale all'immagine esistente, altrimenti ignorata.\x00Inoltra una o pi\u00f9 porte locali a un pod\x00Aiuto per qualsiasi comando\x00IP da assegnare al Load Balancer. Se vuota, un IP effimero verr\u00e0 creato e utilizzato (specifico per provider cloud).\x00Se non \u00e8 vuoto, impostare l'affinit\u00e0 di sessione per il servizio; Valori validi: 'None', 'ClientIP'\x00Se non \u00e8 vuoto, l'aggiornamento delle annotazioni avr\u00e0 successo solo se questa \u00e8 la resource-version corrente per l'oggetto. Valido solo quando si specifica una singola risorsa.\x00Se non vuoto, l'aggiornamento delle label avr\u00e0 successo solo se questa \u00e8 la resource-version corrente per l'oggetto. Valido solo quando si specifica una singola risorsa.\x00Immagine da utilizzare per aggiornare il replication controller. Deve essere diversa dall'immagine esistente (nuova immagine o nuovo tag immagine). Non pu\u00f2 essere utilizzata con --filename/-f\x00Gestisci un deployment rollout\x00Contrassegnare il nodo come programmabile\x00Contrassegnare il nodo come non programmabile\x00Imposta la risorsa indicata in pausa\x00Modificare le risorse del certificato.\x00Modifica i file kubeconfig\x00Nome o numero di porta nel container verso il quale il servizio deve dirigere il traffico. Opzionale.\x00Restituisce solo i log dopo una data specificata (RFC3339). Predefinito tutti i log. \u00c8 possibile utilizzare solo uno tra data-inizio/a-partire-da.\x00Codice di completamento shell di output per la shell specificata (bash o zsh)\x00Output dell'oggetto formattato con la versione del gruppo fornito (per esempio: 'extensions/v1beta1').)\x00Password per l'autenticazione al registro di Docker\x00Percorso certificato di chiave pubblica codificato PEM.\x00Percorso alla chiave privata associata a un certificato specificato.\x00Eseguire un rolling update del ReplicationController specificato\x00Prerequisito per la versione delle risorse. Richiede che la versione corrente delle risorse corrisponda a questo valore per scalare.\x00Stampa per client e server le informazioni sulla versione\x00Stampa l'elenco flag ereditati da tutti i comandi\x00Stampa i log per container in un pod\x00Sostituire una risorsa per nomefile o stdin\x00Riprendere una risorsa in pausa\x00Ruolo di riferimento per RoleBinding\x00Esegui una particolare immagine nel cluster\x00Eseguire un proxy al server Kubernetes API\x00Posizione del server per il Registro Docker\x00Imposta una nuova dimensione per Deployment, ReplicaSet, Replication Controller, o Job\x00Imposta caratteristiche specifiche sugli oggetti\x00Imposta l'annotazione dell'ultima-configurazione-applicata ad un oggetto live per abbinare il contenuto di un file.\x00Impostare il selettore di una risorsa\x00Imposta una voce cluster in kubeconfig\x00Imposta una voce context in kubeconfig\x00Imposta una voce utente in kubeconfig\x00Imposta un singolo valore in un file kubeconfig\x00Imposta il current-context in un file kubeconfig\x00Mostra i dettagli di una specifiche risorsa o un gruppo di risorse\x00Mostra lo stato del rollout\x00Sinonimo di --target-port\x00Prende un replication controller, service, deployment o un pod e lo espone come nuovo servizio Kubernetes\x00L'immagine per il container da eseguire.\x00La politica di pull dell'immagine per il container. Se lasciato vuoto, questo valore non verr\u00e0 specificato dal client e predefinito dal server\x00La chiave da utilizzare per distinguere tra due controller diversi, predefinito \"deployment\". Rilevante soltanto quando --image \u00e8 specificato, altrimenti ignorato\x00Il numero minimo o la percentuale di pod disponibili che questo budget richiede.\x00Il nome dell'oggetto appena creato.\x00Il nome dell'oggetto appena creato. Se non specificato, verr\u00e0 utilizzato il nome della risorsa di input.\x00Il nome del generatore API da utilizzare, si veda http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators per un elenco.\x00Il nome del generatore API da utilizzare. Attualmente c'\u00e8 solo 1 generatore.\x00Il nome del generatore API da utilizzare. Ci sono 2 generatori: 'service/v1' e 'service/v2'. L'unica differenza tra loro \u00e8 che la porta di servizio in v1 \u00e8 denominata \"predefinita\", mentre viene lasciata unnamed in v2. Il valore predefinito \u00e8 'service/v2'.\x00Il nome del generatore da utilizzare per la creazione di un servizio. Utilizzato solo se --expose \u00e8 true\x00Il protocollo di rete per il servizio da creare. Il valore predefinito \u00e8 'TCP'.\x00La porta che il servizio deve servire. Copiato dalla risorsa esposta, se non specificata\x00La porta che questo contenitore espone. Se --expose \u00e8 true, questa \u00e8 anche la porta utilizzata dal servizio creato.\x00I limiti delle richieste di risorse per questo contenitore. Ad esempio, 'cpu=200m,memory=512Mi'. Si noti che i componenti lato server possono assegnare i limiti a seconda della configurazione del server, ad esempio intervalli di limiti.\x00La risorsa necessita di richieste di requisiti per questo pod. Ad esempio, 'cpu = 100m, memoria = 256Mi'. Si noti che i componenti lato server possono assegnare i requisiti a seconda della configurazione del server, ad esempio intervalli di limiti.\x00La politica di riavvio per questo Pod. Valori accettati [Always, OnFailure, Never]. Se impostato su 'Always' viene creato un deployment, se impostato su 'OnFailure' viene creato un job, se impostato su 'Never', viene creato un pod. Per questi ultimi due le - repliche devono essere 1. Predefinito 'Always', per CronJobs `Never`.\x00Tipo di segreto da creare\x00Digitare per questo servizio: ClusterIP, NodePort o LoadBalancer. Ppredefinito \u00e8 'ClusterIP'.\x00Annulla un precedente rollout\x00Annulla singolo valore in un file kubeconfig\x00Aggiornare campo/i risorsa utilizzando merge patch strategici\x00Aggiorna immagine di un pod template\x00Aggiorna richieste di risorse/limiti sugli oggetti con pod template\x00Aggiorna annotazioni di risorsa\x00Aggiorna label di una risorsa\x00Aggiorna i taints su uno o pi\u00f9 nodi\x00Nome utente per l'autenticazione nel registro Docker\x00Visualizza ultime annotazioni dell'ultima configurazione applicata per risorsa/oggetto\x00Visualizza la storia del rollout\x00Dove eseguire l'output dei file. Se vuota o '-' utilizza lo stdout, altrimenti crea una gerarchia di directory in quella directory\x00flag di riavvio finto)\x00nome esterno del servizio\x00Kubectl controlla il gestore cluster di Kubernetes\x00") + +func translationsKubectlIt_itLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlIt_itLc_messagesK8sMo, nil +} + +func translationsKubectlIt_itLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlIt_itLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/it_IT/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlIt_itLc_messagesK8sPo = []byte(`# Italian translation. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR evolution85@gmail.com, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: kubernetes\n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-03-14 21:32-0700\n" +"PO-Revision-Date: 2017-08-28 15:20+0200\n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Last-Translator: Luca Berton \n" +"Language-Team: Luca Berton \n" +"X-Generator: Poedit 1.8.7.1\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Creare un ClusterRoleBinding per user1, user2 e group1 utilizzando il " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Crea un RoleBinding per user1, user2, and group1 utilizzando l'admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead of " +"file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" +"\n" +"\t\t # Crea un nuovo configmap denominato my-config in base alla cartella " +"bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Crea un nuovo configmap denominato my-config con le chiavi " +"specificate anziché i nomi dei file su disco\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Crea un nuovo configmap denominato my-config con key1 = config1 e " +"key2 = config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # Se non si dispone ancora di un file .dockercfg, è possibile creare un " +"secret dockercfg direttamente utilizzando:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # Mostra metriche per tutti i nodi\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Mostra metriche per un determinato nodo\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" +"\n" +"\t\t# Applica la configurazione pod.json a un pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Applicare il JSON passato in stdin a un pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Nota: --prune è ancora in in Alpha\n" +"\t\t# Applica la configurazione manifest.yaml che corrisponde alla label app " +"= nginx ed elimina tutte le altre risorse che non sono nel file e nella label " +"corrispondente app = nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Applica la configurazione manifest.yaml ed elimina tutti gli altri " +"configmaps non presenti nel file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# Auto scale un deployment \"foo\", con il numero di pod compresi tra 2 " +"e 10, utilizzo della CPU target specificato in modo da utilizzare una " +"politica di autoscaling predefinita:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale un controller di replica \"foo\", con il numero di pod " +"compresi tra 1 e 5, utilizzo dell'utilizzo della CPU a 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# Converte 'pod.yaml' alla versione più recente e stampa in stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Converte lo stato live della risorsa specificata da 'pod.yaml' nella " +"versione più recente.\n" +"\t\t# e stampa in stdout nel formato json.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Converte tutti i file nella directory corrente alla versione più " +"recente e li crea tutti.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Crea un ClusterRole denominato \"pod-reader\" che consente all'utente " +"di eseguire \"get\", \"watch\" e \"list\" sui pod\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Crea un ClusterRole denominato \"pod-reader\" con ResourceName " +"specificato\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", " +"\"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Crea un ruolo denominato \"pod-reader\" che consente all'utente di " +"eseguire \"get\", \"watch\" e \"list\" sui pod\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Crea un ruolo denominato \"pod-reader\" con ResourceName specificato\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# Crea una nuova resourcequota chiamata my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Creare una nuova resourcequota denominata best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# Crea un pod disruption budget chiamato my-pdb che seleziona tutti i pod " +"con label app = rail\n" +"\t\t# e richiede che almeno uno di essi sia disponibile in qualsiasi " +"momento.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Crea un pod disruption budget con nome my-pdb che seleziona tutti i pod " +"con label app = nginx \n" +"\t\t# e richiede che almeno la metà dei pod selezionati sia disponibile in " +"qualsiasi momento.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# Crea un pod utilizzando i dati in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Crea un pod basato sul JSON passato in stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Modifica i dati in docker-registry.yaml in JSON utilizzando il formato " +"API v1 quindi creare la risorsa utilizzando i dati modificati.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with the " +"name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which serves " +"on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# Crea un servizio per un nginx replicato, che serve nella porta 80 e si " +"collega ai container sulla porta 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Crea un servizio per un controller di replica identificato per tipo e " +"nome specificato in \"nginx-controller.yaml\", che serve nella porta 80 e si " +"collega ai container sulla porta 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Crea un servizio per un pod valid-pod, che serve nella porta 444 con il " +"nome \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Crea un secondo servizio basato sul servizio sopra, esponendo la porta " +"container 8443 come porta 443 con il nome \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Crea un servizio per un'applicazione di replica in porta 4100 che " +"bilanci il traffico UDP e denominato \"video stream\".\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Crea un servizio per un nginx replicato utilizzando l'insieme di " +"replica, che serve nella porta 80 e si collega ai contenitori sulla porta " +"8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Crea un servizio per una distribuzione di nginx, che serve nella porta " +"80 e si collega ai contenitori della porta 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# Elimina un pod utilizzando il tipo e il nome specificati in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Elimina un pod in base al tipo e al nome del JSON passato in stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Elimina i baccelli ei servizi con gli stessi nomi \"baz\" e \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Elimina i baccelli ei servizi con il nome dell'etichetta = myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Eliminare un pod con un ritardo minimo\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Forza elimina un pod in un nodo morto\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Elimina tutti i pod\n" +"\t\tkubectl delete pods --all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# Descrive un nodo\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Descrive un pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Descrive un pod identificato da tipo e nome in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Descrive tutti i pod\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Descrive i pod con label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Descrivere tutti i pod gestiti dal controller di replica \"frontend" +"\" (rc-created pods\n" +"\t\t# ottiene il nome del rc come un prefisso del nome pod).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# Drain node \"foo\", anche se ci sono i baccelli non gestiti da " +"ReplicationController, ReplicaSet, Job, DaemonSet o StatefulSet su di esso.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# Come sopra, ma interrompere se ci sono i baccelli non gestiti da " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, e " +"utilizzare un periodo di grazia di 15 minuti.\n" +"\t\t$ kubectl drain foo --grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config " +"in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# Modifica il servizio denominato 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Usa un editor alternativo\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Modifica il lavoro 'myjob' in JSON utilizzando il formato API v1:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Modifica la distribuzione 'mydeployment' in YAML e salvare la " +"configurazione modificata nella sua annotazione:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# Ottieni l'output dalla 'data' di esecuzione del pod 123456-7890, " +"utilizzando il primo contenitore per impostazione predefinita\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Ottieni l'output dalla data di esecuzione in ruby-container del pod " +"123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Passare alla modalità raw terminal, invia stdin a 'bash' in ruby-" +"container del pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Ottieni l'output dal pod 123456-7890 in esecuzione, utilizzando il " +"primo contenitore per impostazione predefinita\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Ottieni l'output dal ruby-container del pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Passa alla modalità raw terminal, invia stdin a 'bash' in ruby-" +"container del pod 123456-7890\n" +"\t\t# e invia stdout/stderr da 'bash' al client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Ottieni l'output dal primo pod di una ReplicaSet denominata nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# Ottieni la documentazione della risorsa e i relativi campi\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Ottieni la documentazione di un campo specifico di una risorsa\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# Installa il completamento di bash su un Mac utilizzando homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Carica il codice di completamento kubectl per bash nella shell " +"corrente\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Scrive il codice di completamento bash in un file e lo carica da ." +"bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Carica il codice di completamento kubectl per zsh [1] nella shell " +"corrente\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# Elenca tutti i pod in formato output ps.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# Elenca tutti i pod in formato output ps con maggiori informazioni (ad " +"esempio il nome del nodo).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# Elenca un controller di replica singolo con NAME specificato nel " +"formato di output ps.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# Elenca un singolo pod nel formato di uscita JSON.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# Elenca un pod identificato per tipo e nome specificato in \"pod.yaml\" " +"nel formato di uscita JSON.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Restituisce solo il valore di fase del pod specificato.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# Elenca tutti i controller e servizi di replica insieme in formato " +"output ps.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# Elenca una o più risorse per il tipo e per i nomi.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# Elenca tutte le risorse con tipi diversi.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" +"\n" +"\t\t# Ascolta localmente le porte 5000 e 6000, inoltrando i dati da/verso le " +"porte 5000 e 6000 nel pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Ascolta localmente la porta 8888, inoltra a 5000 nel pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Ascolta localmente una porta casuale, inoltra a 5000 nel pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Ascolta localmente una porta casuale, inoltra a 5000 nel pod\n" +"\t\tkubectl port-forward mypod 0:5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# Segna il nodo \"foo\" come programmabile.\n" +"\t\t$ Kubectl uncordon foo" + +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# Segna il nodo \"foo\" come non programmabile.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required because " +"it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# Aggiorna parzialmente un nodo utilizzando merge patch strategica\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Aggiorna parzialmente un nodo identificato dal tipo e dal nome " +"specificato in \"node.json\" utilizzando merge patch strategica\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Aggiorna l'immagine di un contenitore; spec.containers [*]. name è " +"richiesto perché è una chiave di fusione\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Aggiorna l'immagine di un contenitore utilizzando una patch json con " +"array posizionali\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" + +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# Stampa i flag ereditati da tutti i comandi\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# Stampa l'indirizzo dei servizi master e cluster\n" +"\t\tkubectl cluster-info" + +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# Stampa le versioni client e server per il current context\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# Stampa le versioni API supportate\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# Sostituire un pod utilizzando i dati in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Sostituire un pod usando il JSON passato da stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Aggiorna la versione dell'immagine (tag) di un singolo container di pod " +"a v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Forza la sostituzione, cancellazione e quindi ricreare la risorsa\n" +"\t\tkubectl replace --force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# Restituisce snapshot log dal pod nginx con un solo container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Restituisce snapshot log dei pod definiti dalla label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Restituisce snapshot log del container ruby terminato nel pod web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Iniziare a trasmettere i log del contenitore ruby nel pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Visualizza solo le ultime 20 righe di output del pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Mostra tutti i log del pod nginx scritti nell'ultima ora\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Restituisce snapshot log dal primo contenitore di un lavoro chiamato " +"hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Restituisce snapshot logs del container nginx-1 del deployment chiamato " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# Esegui un proxy verso kubernetes apiserver sulla porta 8011, che " +"fornisce contenuti statici da ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Esegui un proxy verso kubernetes apiserver su una porta locale " +"arbitraria.\n" +"\t\t# La porta selezionata per il server verrà inviata a stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Esegui un proxy verso kubernetes apiserver, cambiando il prefisso api " +"in k8s-api\n" +"\t\t# Questo comporta, ad es., pod api disponibili presso localhost:8001/k8s-" +"api/v1/pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Scala un replicaset denominato 'foo' a 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scala una risorsa identificata per tipo e nome specificato in \"foo.yaml" +"\" a 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# Se la distribuzione corrente di mysql è 2, scala mysql a 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scalare più controllori di replica.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scala il lavoro denominato 'cron' a 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Imposta l'ultima-configurazione-applicata di una risorsa che " +"corrisponda al contenuto di un file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Esegue set-last-applied per ogni file di configurazione in una " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Imposta la configurazione dell'ultima applicazione di una risorsa che " +"corrisponda al contenuto di un file, creerà l'annotazione se non esiste già.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# Mostra metriche di tutti i pod nello spazio dei nomi predefinito\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Mostra metriche di tutti i pod nello spazio dei nomi specificato\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Mostra metriche per un pod e i suoi relativi container\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Mostra metriche per i pod definiti da label name = myLabel\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Spegni foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop di tutti i pod e servizi con label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Spegnere il servizio definito in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Spegnere tutte le resources in path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle " +"'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every 5 " +"minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Avviare un'unica istanza di nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Avviare un'unica istanza di hazelcast e lasciare che il container " +"esponga la porta 5701.\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Avviare una singola istanza di hazelcast ed imposta le variabili " +"ambiente \"DNS_DOMAIN=cluster\" e \"POD_NAMESPACE=default\" nel container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Avviare un'istanza replicata di nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Stampare gli oggetti API corrispondenti senza crearli.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Avviare un'unica istanza di nginx, ma overload le spec del " +"deployment con un insieme parziale di valori analizzati da JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Avviare un pod di busybox e tenerlo in primo piano, non riavviarlo se " +"esce.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Avviare il container nginx utilizzando il comando predefinito, ma " +"utilizzare argomenti personalizzati (arg1 .. argN) per quel comando.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Avviare il container nginx utilizzando un diverso comando e argomenti " +"personalizzati.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Avviare il contenitore perl per calcolare π a 2000 posti e stamparlo.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle " +"'print bpi(2000)'\n" +"\n" +"\t\t# Avviare il cron job per calcolare π a 2000 posti e stampare ogni 5 " +"minuti.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Aggiorna il nodo \"foo\" con un marcatore con il tasto 'dedicated' e il " +"valore 'special-user' ed effettua 'NoSchedule'.\n" +"\t\t# Se un marcatore con quel tasto e l'effetto già esiste, il suo valore " +"viene sostituito come specificato.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Rimuove dal nodo 'foo' il marcatore con il tasto 'dedicated' ed " +"effettua 'NoSchedule' se esiste.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Rimuovi dal nodo 'foo' tutti i marcatori con chiave 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Aggiorna il pod 'foo' con l'etichetta 'unhealthy' e il valore 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Aggiorna il pod 'foo' con l'etichetta 'status' e il valore 'unhealthy', " +"sovrascrivendo qualsiasi valore esistente.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Aggiorna tutti i pod nello spazio dei nomi\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Aggiorna un pod identificato dal tipo e dal nome in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Aggiorna il pod 'foo' solo se la risorsa è invariata dalla versione 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Aggiorna il pod 'foo' rimuovendo un'etichetta denominata 'bar' se " +"esiste.\n" +"\t\t# Non richiede la flag -overwrite.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping the " +"old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Aggiorna i pod di frontend-v1 usando i dati del replication controller " +"in frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Aggiorna i pod di frontend-v1 usando i dati JSON passati da stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Aggiorna i pod di frontend-v1 in frontend-v2 solo cambiando l'immagine " +"e modificando\n" +"\t\t# il nome del replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Aggiorna i pod di frontend solo cambiando l'immaginee mantenendo il " +"vecchio none.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Interrompee ed invertire un rollout esistente in corso (da frontend-v1 " +"a frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# Visualizza le annotazioni dell'ultima-configurazione-applicata per tipo/" +"nome in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# # Visualizza le annotazioni dell'ultima-configurazione-applicata per " +"file in JSON.\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues.k8s." +"io/34274." +msgstr "" +"\n" +"\t\tApplicare una configurazione a una risorsa per nomefile o stdin.\n" +"\t\tQuesta risorsa verrà creata se non esiste ancora.\n" +"\t\tPer utilizzare 'apply', creare sempre la risorsa inizialmente con 'apply' " +"o 'create --save-config'.\n" +"\n" +"\t\tSono accettati i formati JSON e YAML.\n" +"\n" +"\t\tDisclaimer Alpha: la funzionalità --prune non è ancora completa. Non " +"utilizzare a meno che non si sia a conoscenza di quale sia lo stato attuale. " +"Vedi https://issues.k8s.io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use -" +"o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\tConvertire i file di configurazione tra diverse versioni API. Sono\n" +"\t\taccettati i formati YAML e JSON.\n" +"\n" +"\t\tIl comando prende il nome di file, la directory o l'URL come input e lo " +"converte nel formato\n" +"\t\tdi versione specificata dal flag -output-version. Se la versione di " +"destinazione non è specificata o\n" +"\t\tnon supportata, viene convertita nella versione più recente.\n" +"\n" +"\t\tL'output predefinito verrà stampato su stdout nel formato YAML. Si può " +"usare l'opzione -o\n" +"\t\tper cambiare la destinazione di output." + +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\n" +"Crea un ClusterRole." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\tCrea un ClusterRoleBinding per un ClusterRole particolare." + +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\tCrea un RoleBinding per un particolare Ruolo o ClusterRole." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\tCrea un TLS secret dalla coppia di chiavi pubblica/privata.\n" +"\n" +"\t\tLa coppia di chiavi pubblica/privata deve esistere prima. Il certificato " +"chiave pubblica deve essere .PEM codificato e corrispondere alla chiave " +"privata data." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreare un configmap basato su un file, una directory o un valore literal " +"specificato.\n" +"\n" +"\t\tUn singolo configmap può includere una o più coppie chiave/valore.\n" +"\n" +"\t\tQuando si crea una configmap basata su un file, il valore predefinito " +"sarà il nome di base del file e il valore sarà\n" +"\t\tpredefinito per il contenuto del file. Se il nome di base è una chiave " +"non valida, è possibile specificare un tasto alternativo.\n" +"\n" +"\t\tQuando si crea un configmap basato su una directory, ogni file il cui " +"nome di base è una chiave valida nella directory verrà\n" +"\t\tpacchettizzata nel configmap. Le voci di directory tranne i file regolari " +"vengono ignorati (ad esempio sottodirectory,\n" +"\t\tsymlinks, devices, pipes, ecc)." + +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\tCreare un namespace con il nome specificato." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tCreare un nuovo secret per l'utilizzo con i registri Docker.\n" +"\n" +"\t\tDockercfg secrets vengono utilizzati per autenticare i registri Docker.\n" +"\n" +"\t\tQuando utilizzi la riga di comando Docker per il push delle immagini, è " +"possibile eseguire l'autenticazione eseguendo correttamente un determinato " +"registry\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" Questo produce un file ~ / .dockercfg che viene utilizzato dai successivi " +"comandi \"docker push\" e \"docker pull\"\n" +"\t\tper autenticarsi nel registry. L'indirizzo email è facoltativo.\n" +"\n" +"\t\tDurante la creazione di applicazioni, è possibile avere un Docker " +"registry che richiede l'autenticazione. Affinché i \n" +"\t\tnodi eseguano pull di immagini per vostro conto, devono avere le " +"credenziali. È possibile fornire queste informazioni \n" +"\t\tcreando un dockercfg secret e collegandolo al tuo account di servizio." + +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" +"\n" +"\t\tCrea un pod disruption budget con il nome specificato, selector e il " +"numero minimo di pod disponibili" + +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\tCrea una risorsa per nome file o stdin.\n" +"\n" +"\t\tSono accettati i formati JSON e YAML." + +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" +"\n" +"\t\tCrea una resourcequota con il nome specificato, hard limits e gli scope " +"opzionali" + +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\tCrea un ruolo con una singola regola." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files are " +"ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCrea un secret basato su un file, una directory o un valore specifico " +"literal.\n" +"\n" +"\t\tUn singolo secret può includere una o più coppie chiave/valore.\n" +"\n" +"\t\tQuando si crea un secret basato su un file, la chiave per impostazione " +"predefinita sarà il nome di base del file e il valore sarà\n" +"\t\tpredefinito al contenuto del file. Se il nome di base è una chiave non " +"valida, è possibile specificare un tasto alternativo.\n" +"\n" +"\n" +"\t\tQuando si crea un segreto basato su una directory, ogni file il cui nome " +"di base è una chiave valida nella directory verrà \n" +"\t\\paccehttizzataw in un secret. Le voci di directory tranne i file " +"regolari vengono ignorati (ad esempio sottodirectory,\n" +"\t\tsymlinks, devices, pipes, ecc)." + +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\tCreare un service account con il nome specificato." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tCrea ed esegue un'immagine particolare, eventualmente replicata.\n" +"\n" +"\t\tCrea un deployment o un job per gestire i container creati." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" +"\n" +"\t\tCrea un autoscaler che automaticamente sceglie e imposta il numero di pod " +"che vengono eseguiti in un cluster di kubernets.\n" +"\n" +"\t\tEsegue una ricerca di un Deployment, ReplicaSet o ReplicationController " +"per nome e crea un autoscaler che utilizza la risorsa indicata come " +"riferimento.\n" +"\t\tUn autoscaler può aumentare o diminuire automaticamente il numero di pod " +"distribuiti all'interno del sistema se necessario." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may be " +"specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or talk " +"to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tCancella risorse secondo nomi di file, stdin, risorse e nomi, o per " +"selettori di risorse e etichette.\n" +"\n" +"\t\tSono accettati i formati JSON e YAML. È possibile specificare un solo " +"tipo di argomenti: nome file,\n" +"\t\trisorse e nomi, o risorse e selettore di etichette.\n" +"\n" +"\t\tAlcune risorse, come i pod, supportano cacellazione corretta. Queste " +"risorse definiscono un periodo di default\n" +"\t\tprima che siano forzatamente terminate (il grace period) ma si può " +"sostituire quel valore con\n" +"\t\til falg --grace-period, o passare --now per impostare il grace-period a " +"1. Poiché queste risorse spesso\n" +"\t\trappresentano entità del cluster, la cancellazione non può essere presa " +"in carico immediatamente. Se il nodo\n" +"\t\tche ospita un pod è spento o non raggiungibile da API server, termination " +"può richiedere molto più tempo\n" +"\t\tdel grace period. Per forzare la cancellazione di una resource,\tdevi " +"obbligatoriamente indicare un grace\tperiod di 0 e specificare\n" +"\t\til flag --force.\n" +"\n" +"\t\tIMPORTANTE: Fozare la cancellazione dei pod non attende conferma che i " +"processi del pod siano\n" +"\t\tterminati, che può lasciare questi processi in esecuzione fino a quando " +"il nodo rileva la cancellazione\n" +"\t\tcompletata correttamente. Se i tuoi processi utilizzano l'archiviazione " +"condivisa o parlano con un'API remota e\n" +"\t\tdipendono dal nome del pod per identificarsi, la forzata eliminazione di " +"questi pod può comportare\n" +"\t\tpiù processi in esecuzione su macchine diverse che utilizzando la stessa " +"identificazione che può portare\n" +"\t\tcorruzione o inconsistenza dei dati. Forza i pod solo quando si è sicuri " +"che il pod sia\n" +"\t\tterminato, o se la tua applicazione può can tollerare più copie dello " +"stesso pod in esecuzione contemporaneamente.\n" +"\t\tInoltre, se forzate l'eliminazione dei i nodi, lo scheduler può può " +"creare nuovi nodi su questi nodi prima che il nodo\n" +"\t\tabbia liberato quelle risorse e provocando immediatamente evict di tali " +"pod.\n" +"\n" +"\n" +"\t\tNotare che il comando di eliminazione NON fa verificare la versione delle " +"risorse, quindi se qualcuno\n" +"\t\tinvia un aggiornamento ad una risorsa quando invii un eliminazione, il " +"loro aggiornamento\n" +"\t\tsaranno persi insieme al resto della risorsa." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tDeprecated: chiudere correttamente una risorsa per nome o nome file.\n" +"\n" +"\t\tIl comando stop è deprecato, tutte le sue funzionalità sono coperte dal " +"comando delete.\n" +"\t\tVedere 'kubectl delete --help' per ulteriori dettagli.\n" +"\n" +"\t\tTenta di arrestare ed eliminare una risorsa che supporta la corretta " +"terminazione.\n" +"\t\tSe la risorsa è scalabile, verrà scalata a 0 prima dell'eliminazione." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage) dei nodi.\n" +"\n" +"\t\tIl comando top-node consente di visualizzare il consumo di risorse dei " +"nodi." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage) dei pod.\n" +"\n" +"\t\tIl comando \"top pod\" consente di visualizzare il consumo delle risorse " +"dei pod.\n" +"\n" +"\t\tA causa del ritardo della pipeline metrica, potrebbero non essere " +"disponibili per alcuni minuti\n" +"\t\teal momento della creazione dei pod." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" +"\n" +"\t\tVisualizza l'utilizzo di risorse (CPU/Memoria/Storage).\n" +"\n" +"\t\tIl comando top consente di visualizzare il consumo di risorse per nodi o " +"pod.\n" +"\n" +"\t\tQuesto comando richiede che Heapster sia configurato correttamente e che " +"funzioni sul server." + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there are " +"any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any " +"pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the managing " +"resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\tDrain node in preparazione alla manutenzione.\n" +"\n" +"\t\tIl nodo indicato verrà contrassegnato unschedulable per impedire che " +"nuovi pod arrivino.\n" +"\t\t'drain' evict i pod se l'APIServer supporta eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Altrimenti, usa il " +"normale DELETE\n" +"\t\tper eliminare i pod.\n" +"\t\tIl 'drain' evicts o la cancellazione di tutti all pod tranne mirror pods " +"(che non possono essere eliminati\n" +"\t\tattraverso API server). Se ci sono i pod gestiti da DaemonSet, drain " +"non procederà\n" +"\t\tsenza --ignore-daemonsets e, a prescindere da ciò, non cancellerà alcun\n" +"\t\tpod gestitto da DaemonSet,poiché questi pods verrebbero immediatamente " +"sostituiti dal\n" +"\t\tDaemonSet controller, che ignora le marcature unschedulable. Se ci " +"sono\n" +"\t\tpod che non sono né mirror pod né gestiti dal ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet o Job, allora drain non cancellerà " +"alcun pod finché non\n" +"\t\tuserai --force. --force permetterà alla cancellazione di procedere se la " +"risorsa gestita da uno\n" +"\t\to più pod è mancante.\n" +"\n" +"\t\t'drain' attende il termine corretto. Non devi operare sulla macchina " +"finché\n" +"\t\til comando non viene completato.\n" +"\n" +"\t\tQuando sei pronto per riportare il nodo al servizio, utilizza kubectl " +"uncordon, per\n" +"\t\trimettere il nodo schedulable nuovamente.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when updating " +"a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\tModificare una risorsa dall'editor predefinito.\n" +"\n" +"\t\tIl comando di modifica consente di modificare direttamente qualsiasi " +"risorsa API che è possibile recuperare tramite gli\n" +"\t\tstrumenti di riga di comando. Apre l'editor definito dalle variabili " +"d'ambiente\n" +"\t\tKUBE_EDITOR o EDITOR, o ritornare a 'vi' per Linux o 'notepad' per " +"Windows.\n" +"\t\tÈ possibile modificare più oggetti, anche se le modifiche vengono " +"applicate una alla volta. Il comando\n" +"\t\taccetta sia nomi di file che argomenti da riga di comando, anche se i " +"file a cui fa riferimento devono\n" +"\t\tessere state salvate precedentemente le versioni delle risorse.\n" +"\n" +"\t\tLa modifica viene eseguita con la versione API utilizzata per recuperare " +"la risorsa.\n" +"\t\tPer modificare utilizzando una specifica versione API, fully-qualify la " +"risorsa, versione e il gruppo.\n" +"\n" +"\t\tIl formato predefinito è YAML. Per modificare in JSON, specificare \"-o " +"json\".\n" +"\n" +"\t\tIl flag --windows-line-endings può essere utilizzato per forzare i fine " +"linea Windows,\n" +"\t\taltrimenti verrà utilizzato il default per il sistema operativo.\n" +"\n" +"\t\tNel caso in cui si verifica un errore durante l'aggiornamento, verrà " +"creato un file temporaneo sul disco\n" +"\t\tche contiene le modifiche non apportate. L'errore più comune durante " +"l'aggiornamento di una risorsa\n" +"\t\tè una modifica da pare di un altro editor della risorsa sul server. " +"Quando questo si verifica, dovrai\n" +"\t\tapplicare le modifiche alla versione più recente della risorsa o " +"aggiornare il tua copia\n" +"\t\ttemporanea salvata per includere l'ultima versione delle risorse." + +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\tContrassegna il nodo come programmabile." + +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\tContrassegnare il nodo come non programmabile." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions of " +"zsh >= 5.2" +msgstr "" +"\n" +"\t\tIn output codice di completamento shell output per la shell specificata " +"(bash o zsh).\n" +"\t\tIl codice di shell deve essere valorizzato per fornire completamento\n" +"\t\tinterattivo dei comandi kubectl. Questo può essere eseguito " +"richiamandolo\n" +"\t\tda .bash_profile.\n" +"\n" +"\t\tNota: questo richiede il framework di completamento bash, che non è " +"installato\n" +"\t\tper impostazione predefinita su Mac. Questo può essere installato " +"utilizzando homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tUna volta installato, bash_completion deve essere valutato. Ciò può " +"essere fatto aggiungendo la\n" +"\t\tseguente riga al file .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNota per gli utenti zsh: [1] i completamenti zsh sono supportati solo " +"nelle versioni zsh> = 5.2" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) label " +"in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\tEseguire un rolling update del ReplicationController specificato.\n" +"\n" +"\t\tSostituisce il replication controller specificato con un nuovo " +"replication controller aggiornando un pod alla volta per usare il\n" +"\t\tnuovo PodTemplate. Il new-controller.json deve specificare lo stesso " +"namespace del\n" +"\t\tcontroller di replica esistente e sovrascrivere almeno una etichetta " +"(comune) nella sua replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tSostituire una risorsa per nomefile o stdin.\n" +"\n" +"\t\tSono accettati i formati JSON e YAML. Se si sostituisce una risorsa " +"esistente, \n" +"\t\tè necessario fornire la specifica completa delle risorse. Questo può " +"essere ottenuta da\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tFare riferimento ai modelli https://htmlpreview.github.io/?https://github." +"com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html " +"per trovare se un campo è mutevole." + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is validated " +"before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds true " +"when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tImposta una nuova dimensione per Deployment, ReplicaSet, Replication " +"Controller, o Job.\n" +"\n" +"\t\tScala consente anche agli utenti di specificare una o più condizioni " +"preliminari per l'azione della scala.\n" +"\n" +"\t\tSe --current-replicas o --resource-version sono specificate, viene " +"convalidata prima di\n" +"\t\ttentare scale, ed è garantito che la precondizione vale quando\n" +"\t\tscale viene inviata al server.." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tImposta le annotazioni dell'ultima-configurazione-applicata impostandola " +"in modo che corrisponda al contenuto di un file.\n" +"\t\tCiò determina l'aggiornamento dell'ultima-configurazione-applicata come " +"se 'kubectl apply -f ' fosse stato eseguito,\n" +"\t\tsenza aggiornare altre parti dell'oggetto." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tPer proxy tutti i kubernetes api e nient'altro, utilizzare:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tPer proxy solo una parte dei kubernetes api e anche alcuni file static\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tQuanto sopra consente 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tPer eseguire il proxy tutti i kubernetes api in una radice diversa, " +"utilizzare:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tQuanto sopra ti permette 'curl localhost:8001/custom/api/v1/pods'" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tAggiorna i campi di una risorsa utilizzando la merge patch strategica\n" +"\n" +"\t\tSono accettati i formati JSON e YAML.\n" +"\n" +"\t\tSi prega di fare riferimento ai modelli in https://htmlpreview.github.io/?" +"https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/" +"definitions.html per trovare se un campo è mutevole." + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this resource " +"version, otherwise the existing resource-version will be used." +msgstr "" +"\n" +"\t\tAggiorna le label di una risorsa.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this resource " +"version, otherwise the existing resource-version will be used." + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" +"\n" +"\t\tAggiorna i marcatori su uno o più nodi.\n" +"\n" +"\t\t* Un marcatore è costituita da una chiave, un valore e un effetto. Come " +"argomento qui, viene espresso come chiave = valore: effetto.\n" +"\t\t* La chiave deve iniziare con una lettera o un numero e può contenere " +"lettere, numeri, trattini, punti e sottolineature, fino a% [1] d caratteri.\n" +"\t\t* Il valore deve iniziare con una lettera o un numero e può contenere " +"lettere, numeri, trattini, punti e sottolineature, fino a% [2] d caratteri.\n" +"\t\t* L'effetto deve essere NoSchedule, PreferNoSchedule o NoExecute.\n" +"\t\t* Attualmente il marcatore può essere applicato solo al nodo." + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use -" +"o option\n" +"\t\tto change output format." +msgstr "" +"\n" +"\t\tVisualizza le annotazioni dell'ultima-configurazione-applicata per tipo/" +"nome o file.\n" +"\n" +"\t\tL'output predefinito verrà stampato su stdout nel formato YAML. Si può " +"usare l'opzione -o\n" +"\t\tPer cambiare il formato di output." + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" +"\n" +"\t # !!!Nota importante!!!\n" +"\t # Richiede che il binario 'tar' sia presente nel tuo contenitore\n" +"\t # immagine. Se 'tar' non è presente, 'kubectl cp' non riesce.\n" +"\n" +"\t # Copia /tmp/foo_dir directory locale in /tmp/bar_dir in un pod remoto " +"nello spazio dei nomi predefinito\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copia /tmp/foo file locale in /tmp/bar in un pod remoto in un " +"contenitore specifico\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copia /tmp/foo file locale in /tmp/bar in un pod remoto nello spazio " +"dei nomi \n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copia /tmp/foo da un pod remoto in /tmp/bar localmente\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" +"\n" +"\t # Crea un nuovo secret TLS denominato tls-secret con la coppia di dati " +"fornita:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # Crea un nuovo namespace denominato my-namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/" +"id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret --" +"from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Crea un nuovo secret denominato my-secret con i tasti per ogni file " +"nella barra delle cartelle\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Crea un nuovo secret denominato my-secret con le chiavi specificate " +"anziché i nomi sul disco\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/" +"id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Crea un nuovo secret denominato my-secret con key1 = supersecret e key2 " +"= topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret --" +"from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Crea un nuovo service account denominato my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Crea un nuovo servizio ExternalName denominato my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tCrea un servizio ExternalName con il nome specificato.\n" +"\n" +"\tIl servizio ExternalName fa riferimento a un indirizzo DNS esterno \n" +"\tsolo pod, che permetteranno agli autori delle applicazioni di utilizzare i " +"servizi di riferimento\n" +"\tche esistono fuori dalla piattaforma, su altri cluster, o localmente.." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp fornisce assistenza per qualsiasi comando nell'applicazione.\n" +"\tBasta digitare kubectl help [path to command] per i dettagli completi." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # Creare un nuovo servizio LoadBalancer denominato my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # Creare un nuovo servizio clusterIP denominato my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Creare un nuovo servizio clusterIP denominato my-cs (in modalità " +"headless)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # Crea una nuovo deployment chiamato my-dep che esegue l'immagine " +"busybox.\n" +" kubectl create deployment my-dep --image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # Creare un nuovo servizio nodeport denominato my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" +"\n" +" # Dump dello stato corrente del cluster verso stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump dello stato corrente del cluster verso /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump di tutti i namespaces verso stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump di un set di namespace verso /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" +"\n" +" # Aggiorna il pod 'foo' con annotazione 'description'e il valore 'my " +"frontend'.\n" +" # Se la stessa annotazione è impostata più volte, verrà applicato solo " +"l'ultimo valore\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Aggiorna un pod identificato per tipo e nome in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Aggiorna pod 'foo' con la annotazione 'description' e il valore 'my " +"frontend running nginx', sovrascrivendo qualsiasi valore esistente.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Aggiorna tutti i baccelli nel namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Aggiorna il pod 'foo' solo se la risorsa è invariata dalla versione 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Aggiorna il pod 'foo' rimuovendo un'annotazione denominata " +"'descrizione' se esiste.\n" +" # Non richiede flag -overwrite.\n" +" kubectl annotate pods foo description-" + +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" Crea un servizio LoadBalancer con il nome specificato." + +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" Crea un servizio clusterIP con il nome specificato." + +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" Creare un deployment con il nome specificato." + +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" Creare un servizio nodeport con il nome specificato." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" +"\n" +" Dump delle informazioni di cluster idonee per il debug e la diagnostica " +"di problemi di cluster. Per impostazione predefinita, tutto\n" +"    verso stdout. È possibile specificare opzionalmente una directory con --" +"output-directory. Se si specifica una directory, kubernetes \n" +" creearà un insieme di file in quella directory. Per impostazione " +"predefinita, dumps solo i dati del namespace \"kube-system\", ma è\n" +" possibile passare ad namespace diverso con il flag --namespaces o " +"specificare --all-namespaces per il dump di tutti i namespace.\n" +"\n" +"     Il comando esegue dump anche dei log di tutti i pod del cluster, questi " +"log vengono scaricati in directory differenti\n" +"     basati sul namespace e sul nome del pod." + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" +"\n" +" Visualizza gli indirizzi del master e dei servizi con label kubernetes.io/" +"cluster-service=true\n" +"  Per ulteriore debug e diagnosticare i problemi di cluster, utilizzare " +"'kubectl cluster-info dump'." + +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object tracked " +"by the quota." +msgstr "" +"Un insieme delimitato-da-virgole di quota scopes che devono corrispondere a " +"ciascun oggetto gestito dalla quota." + +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" +"Un insieme delimitato-da-virgola di coppie risorsa = quantità che definiscono " +"un hard limit." + +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" +"Un label selector da utilizzare per questo budget. Sono supportati solo i " +"selettori equality-based selector." + +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" +"Un selettore di label da utilizzare per questo servizio. Sono supportati solo " +"equality-based selector. Se vuota (default) dedurre il selettore dal " +"replication controller o replica set.)" + +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "Un calendario in formato Cron del lavoro che deve essere eseguito." + +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" +"Indirizzo IP esterno aggiuntivo (non gestito da Kubernetes) da accettare per " +"il servizio. Se questo IP viene indirizzato a un nodo, è possibile accedere " +"da questo IP in aggiunta al service IP generato." + +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it is " +"used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" +"Un override JSON inline per l'oggetto generato. Se questo non è vuoto, viene " +"utilizzato per ignorare l'oggetto generato. Richiede che l'oggetto fornisca " +"un campo valido apiVersion." + +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" +"Un override JSON inline per l'oggetto di servizio generato. Se questo non è " +"vuoto, viene utilizzato per ignorare l'oggetto generato. Richiede che " +"l'oggetto fornisca un campo valido apiVersion. Utilizzato solo se --expose è " +"true." + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "Applica una configurazione risorsa per nomefile o stdin" + +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "Approva una richiesta di firma del certificato" + +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" +"Assegnare il proprio ClusterIP o impostare su 'None' per un servizio " +"'headless' (nessun bilanciamento del carico)." + +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Collega a un container in esecuzione" + +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "Auto-scale a Deployment, ReplicaSet, o ReplicationController" + +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set " +"to 'None' to create a headless service." +msgstr "" +"ClusterIP da assegnare al servizio. Lasciare vuoto per allocare " +"automaticamente o impostare su 'None' per creare un servizio headless." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRole a cui questo ClusterRoleBinding fa riferimento" + +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "ClusterRole a cui questo RoleBinding fa riferimento" + +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --image " +"is specified, ignored otherwise. Required when using --image on a multi-" +"container pod" +msgstr "" +"Nome container che avrà la sua immagine aggiornata. Soltanto rilevante quando " +"--image è specificato, altrimenti ignorato. Necessario quando si utilizza --" +"image su un contenitore a più contenitori" + +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "Convertire i file di configurazione tra diverse versioni APIs" + +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "Copiare file e directory da e verso i container." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "Crea un ClusterRoleBinding per un ClusterRole particolare" + +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "Creare un servizio LoadBalancer." + +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "Crea un servizio NodePort." + +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "Crea un RoleBinding per un particolare Role o ClusterRole" + +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "Crea un secret TLS" + +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "Crea un servizio clusterIP." + +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "" +"Crea un configmap da un file locale, una directory o un valore letterale" + +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "Creare un deployment con il nome specificato." + +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "Crea un namespace con il nome specificato" + +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "Crea un pod disruption budget con il nome specificato." + +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "Crea una quota con il nome specificato." + +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "Crea una risorsa per nome file o stdin" + +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "Crea un secret da utilizzare con un registro Docker" + +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "Crea un secret da un file locale, una directory o un valore letterale" + +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "Crea un secret utilizzando un subcommand specificato" + +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "Creare un account di servizio con il nome specificato" + +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "Crea un servizio utilizzando il subcommand specificato." + +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Crea un servizio ExternalName." + +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "" +"Elimina risorse selezionate per nomi di file, stdin, risorse e nomi, o per " +"risorsa e selettore di label" + +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "Elimina il cluster specificato dal kubeconfig" + +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "Elimina il context specificato dal kubeconfig" + +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "Nega una richiesta di firma del certificato" + +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Deprecated: spegne correttamente una risorsa per nome o nome file" + +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "Descrive uno o più context" + +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Visualizza l'utilizzo di risorse (CPU/Memoria) per nodo" + +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Visualizza l'utilizzo di risorse (CPU/Memoria) per pod." + +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "Visualizza l'utilizzo di risorse (CPU/Memoria)." + +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "Visualizza informazioni sul cluster" + +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "Mostra i cluster definiti nel kubeconfig" + +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "" +"Visualizza le impostazioni merged di kubeconfig o un file kubeconfig " +"specificato" + +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "Visualizza una o più risorse" + +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "Visualizza il current-context" + +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "Documentazione delle risorse" + +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Drain node in preparazione alla manutenzione" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Dump di un sacco di informazioni pertinenti per il debug e la diagnosi" + +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "Modificare una risorsa sul server" + +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "Email per il registro Docker" + +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "Esegui un comando in un contenitore" + +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" +"Politica esplicita per il pull delle immagini container. Richiesto quando --" +"image è uguale all'immagine esistente, altrimenti ignorata." + +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Inoltra una o più porte locali a un pod" + +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Aiuto per qualsiasi comando" + +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" +"IP da assegnare al Load Balancer. Se vuota, un IP effimero verrà creato e " +"utilizzato (specifico per provider cloud)." + +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal values: " +"'None', 'ClientIP'" +msgstr "" +"Se non è vuoto, impostare l'affinità di sessione per il servizio; Valori " +"validi: 'None', 'ClientIP'" + +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" +"Se non è vuoto, l'aggiornamento delle annotazioni avrà successo solo se " +"questa è la resource-version corrente per l'oggetto. Valido solo quando si " +"specifica una singola risorsa." + +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" +"Se non vuoto, l'aggiornamento delle label avrà successo solo se questa è la " +"resource-version corrente per l'oggetto. Valido solo quando si specifica una " +"singola risorsa." + +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used with " +"--filename/-f" +msgstr "" +"Immagine da utilizzare per aggiornare il replication controller. Deve essere " +"diversa dall'immagine esistente (nuova immagine o nuovo tag immagine). Non " +"può essere utilizzata con --filename/-f" + +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "Gestisci un deployment rollout" + +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "Contrassegnare il nodo come programmabile" + +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "Contrassegnare il nodo come non programmabile" + +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "Imposta la risorsa indicata in pausa" + +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "Modificare le risorse del certificato." + +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "Modifica i file kubeconfig" + +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" +"Nome o numero di porta nel container verso il quale il servizio deve dirigere " +"il traffico. Opzionale." + +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" +"Restituisce solo i log dopo una data specificata (RFC3339). Predefinito tutti " +"i log. È possibile utilizzare solo uno tra data-inizio/a-partire-da." + +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "" +"Codice di completamento shell di output per la shell specificata (bash o zsh)" + +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: 'extensions/" +"v1beta1').)" +msgstr "" +"Output dell'oggetto formattato con la versione del gruppo fornito (per " +"esempio: 'extensions/v1beta1').)" + +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Password per l'autenticazione al registro di Docker" + +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Percorso certificato di chiave pubblica codificato PEM." + +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Percorso alla chiave privata associata a un certificato specificato." + +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "Eseguire un rolling update del ReplicationController specificato" + +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource version " +"match this value in order to scale." +msgstr "" +"Prerequisito per la versione delle risorse. Richiede che la versione corrente " +"delle risorse corrisponda a questo valore per scalare." + +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "Stampa per client e server le informazioni sulla versione" + +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "Stampa l'elenco flag ereditati da tutti i comandi" + +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "Stampa i log per container in un pod" + +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "Sostituire una risorsa per nomefile o stdin" + +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "Riprendere una risorsa in pausa" + +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "Ruolo di riferimento per RoleBinding" + +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "Esegui una particolare immagine nel cluster" + +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "Eseguire un proxy al server Kubernetes API" + +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "Posizione del server per il Registro Docker" + +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" +"Imposta una nuova dimensione per Deployment, ReplicaSet, Replication " +"Controller, o Job" + +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "Imposta caratteristiche specifiche sugli oggetti" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" +"Imposta l'annotazione dell'ultima-configurazione-applicata ad un oggetto live " +"per abbinare il contenuto di un file." + +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "Impostare il selettore di una risorsa" + +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "Imposta una voce cluster in kubeconfig" + +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "Imposta una voce context in kubeconfig" + +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "Imposta una voce utente in kubeconfig" + +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "Imposta un singolo valore in un file kubeconfig" + +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "Imposta il current-context in un file kubeconfig" + +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "Mostra i dettagli di una specifica risorsa o un gruppo di risorse" + +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "Mostra lo stato del rollout" + +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Sinonimo di --target-port" + +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" +"Prende un replication controller, service, deployment o un pod e lo espone " +"come nuovo servizio Kubernetes" + +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "L'immagine per il container da eseguire." + +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" +"La politica di pull dell'immagine per il container. Se lasciato vuoto, questo " +"valore non verrà specificato dal client e predefinito dal server" + +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" +"La chiave da utilizzare per distinguere tra due controller diversi, " +"predefinito \"deployment\". Rilevante soltanto quando --image è specificato, " +"altrimenti ignorato" + +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "The minimum number or percentage of available pods this budget requires." +msgstr "" +"Il numero minimo o la percentuale di pod disponibili che questo budget " +"richiede." + +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "Il nome dell'oggetto appena creato." + +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" +"Il nome dell'oggetto appena creato. Se non specificato, verrà utilizzato il " +"nome della risorsa di input." + +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" +"Il nome del generatore API da utilizzare, si veda http://kubernetes.io/docs/" +"user-guide/kubectl-conventions/#generators per un elenco." + +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" +"Il nome del generatore API da utilizzare. Attualmente c'è solo 1 generatore." + +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in v1 " +"is named 'default', while it is left unnamed in v2. Default is 'service/v2'." +msgstr "" +"Il nome del generatore API da utilizzare. Ci sono 2 generatori: 'service/v1' " +"e 'service/v2'. L'unica differenza tra loro è che la porta di servizio in v1 " +"è denominata \"predefinita\", mentre viene lasciata unnamed in v2. Il valore " +"predefinito è 'service/v2'." + +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" +"Il nome del generatore da utilizzare per la creazione di un servizio. " +"Utilizzato solo se --expose è true" + +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "" +"Il protocollo di rete per il servizio da creare. Il valore predefinito è " +"'TCP'." + +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" +"La porta che il servizio deve servire. Copiato dalla risorsa esposta, se non " +"specificata" + +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" +"La porta che questo contenitore espone. Se --expose è true, questa è anche la " +"porta utilizzata dal servizio creato." + +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" +"I limiti delle richieste di risorse per questo contenitore. Ad esempio, " +"'cpu=200m,memory=512Mi'. Si noti che i componenti lato server possono " +"assegnare i limiti a seconda della configurazione del server, ad esempio " +"intervalli di limiti." + +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" +"La risorsa necessita di richieste di requisiti per questo pod. Ad esempio, " +"'cpu = 100m, memoria = 256Mi'. Si noti che i componenti lato server possono " +"assegnare i requisiti a seconda della configurazione del server, ad esempio " +"intervalli di limiti." + +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" +"La politica di riavvio per questo Pod. Valori accettati [Always, OnFailure, " +"Never]. Se impostato su 'Always' viene creato un deployment, se impostato su " +"'OnFailure' viene creato un job, se impostato su 'Never', viene creato un " +"pod. Per questi ultimi due le - repliche devono essere 1. Predefinito " +"'Always', per CronJobs ` + "`" + `Never` + "`" + `." + +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "Tipo di segreto da creare" + +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" +"Digitare per questo servizio: ClusterIP, NodePort o LoadBalancer. " +"Ppredefinito è 'ClusterIP'." + +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "Annulla un precedente rollout" + +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "Annulla singolo valore in un file kubeconfig" + +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "Aggiornare campo/i risorsa utilizzando merge patch strategici" + +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "Aggiorna immagine di un pod template" + +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "Aggiorna richieste di risorse/limiti sugli oggetti con pod template" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "Aggiorna annotazioni di risorsa" + +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "Aggiorna label di una risorsa" + +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "Aggiorna i taints su uno o più nodi" + +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Nome utente per l'autenticazione nel registro Docker" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "" +"Visualizza ultime annotazioni dell'ultima configurazione applicata per " +"risorsa/oggetto" + +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "Visualizza la storia del rollout" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" +"Dove eseguire l'output dei file. Se vuota o '-' utilizza lo stdout, " +"altrimenti crea una gerarchia di directory in quella directory" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "flag di riavvio finto)" + +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "nome esterno del servizio" + +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "Kubectl controlla il gestore cluster di Kubernetes" +`) + +func translationsKubectlIt_itLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlIt_itLc_messagesK8sPo, nil +} + +func translationsKubectlIt_itLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlIt_itLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/it_IT/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlJa_jpLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xeb\x00\x00\x00\x1c\x00\x00\x00t\a\x00\x009\x01\x00\x00\xcc\x0e\x00\x00\x00\x00\x00\x00\xb0\x13\x00\x00\xdc\x00\x00\x00\xb1\x13\x00\x00\xb6\x00\x00\x00\x8e\x14\x00\x00\v\x02\x00\x00E\x15\x00\x00\x1f\x01\x00\x00Q\x17\x00\x00z\x00\x00\x00q\x18\x00\x00_\x02\x00\x00\xec\x18\x00\x00\u007f\x01\x00\x00L\x1b\x00\x00\x8f\x01\x00\x00\xcc\x1c\x00\x00k\x01\x00\x00\\\x1e\x00\x00k\x01\x00\x00\xc8\x1f\x00\x00>\x01\x00\x004!\x00\x00\x03\x02\x00\x00s\"\x00\x00o\x01\x00\x00w$\x00\x00H\x05\x00\x00\xe7%\x00\x00g\x02\x00\x000+\x00\x00\x1b\x02\x00\x00\x98-\x00\x00q\x01\x00\x00\xb4/\x00\x00\xa8\x01\x00\x00&1\x00\x00\xd4\x01\x00\x00\xcf2\x00\x00\x02\x02\x00\x00\xa44\x00\x00\xb4\x00\x00\x00\xa76\x00\x00\xb7\x02\x00\x00\\7\x00\x00\x92\x03\x00\x00\x14:\x00\x00\xbf\x01\x00\x00\xa7=\x00\x00=\x00\x00\x00g?\x00\x00;\x00\x00\x00\xa5?\x00\x00\xcd\x02\x00\x00\xe1?\x00\x00<\x00\x00\x00\xafB\x00\x00P\x00\x00\x00\xecB\x00\x00S\x00\x00\x00=C\x00\x00<\x00\x00\x00\x91C\x00\x00\xac\x01\x00\x00\xceC\x00\x00\x13\x03\x00\x00{E\x00\x00\xea\x01\x00\x00\x8fH\x00\x00\xfa\x01\x00\x00zJ\x00\x00\xda\x01\x00\x00uL\x00\x00c\x01\x00\x00PN\x00\x00T\x01\x00\x00\xb4O\x00\x00\xba\x06\x00\x00\tQ\x00\x00\xf9\x01\x00\x00\xc4W\x00\x00\xe0\x02\x00\x00\xbeY\x00\x00\x02\x03\x00\x00\x9f\\\x00\x00\xfb\x00\x00\x00\xa2_\x00\x00\xa5\x01\x00\x00\x9e`\x00\x00\xb4\x01\x00\x00Db\x00\x00\x18\x00\x00\x00\xf9c\x00\x00<\x00\x00\x00\x12d\x00\x00=\x00\x00\x00Od\x00\x00\xc6\x00\x00\x00\x8dd\x00\x00g\x02\x00\x00Te\x00\x00.\x00\x00\x00\xbcg\x00\x001\x03\x00\x00\xebg\x00\x00g\x00\x00\x00\x1dk\x00\x00Q\x00\x00\x00\x85k\x00\x00R\x00\x00\x00\xd7k\x00\x00\"\x00\x00\x00*l\x00\x00X\x02\x00\x00Ml\x00\x004\x00\x00\x00\xa6n\x00\x00}\x00\x00\x00\xdbn\x00\x00k\x01\x00\x00Yo\x00\x00\x81\a\x00\x00\xc5p\x00\x00f\x01\x00\x00Gx\x00\x00\x85\x00\x00\x00\xaey\x00\x00\xea\x00\x00\x004z\x00\x00\xd9\x00\x00\x00\x1f{\x00\x00\n\x05\x00\x00\xf9{\x00\x00\x10\x05\x00\x00\x04\x81\x00\x00\x1c\x00\x00\x00\x15\x86\x00\x00\x1e\x00\x00\x002\x86\x00\x00\x98\x02\x00\x00Q\x86\x00\x00\xbc\x01\x00\x00\xea\x88\x00\x00\x9c\x01\x00\x00\xa7\x8a\x00\x00q\x01\x00\x00D\x8c\x00\x00\x05\x01\x00\x00\xb6\x8d\x00\x00\xdf\x01\x00\x00\xbc\x8e\x00\x00\x1c\x01\x00\x00\x9c\x90\x00\x00\xc1\x01\x00\x00\xb9\x91\x00\x00\x1b\x02\x00\x00{\x93\x00\x00\xc0\x00\x00\x00\x97\x95\x00\x00\xd5\x02\x00\x00X\x96\x00\x00\x9d\x00\x00\x00.\x99\x00\x00X\x00\x00\x00\u0319\x00\x00%\x02\x00\x00%\x9a\x00\x00o\x00\x00\x00K\x9c\x00\x00u\x00\x00\x00\xbb\x9c\x00\x00\x01\x01\x00\x001\x9d\x00\x00v\x00\x00\x003\x9e\x00\x00t\x00\x00\x00\xaa\x9e\x00\x00\xef\x00\x00\x00\x1f\x9f\x00\x00}\x00\x00\x00\x0f\xa0\x00\x00j\x00\x00\x00\x8d\xa0\x00\x00\xc4\x01\x00\x00\xf8\xa0\x00\x00\xf7\x03\x00\x00\xbd\xa2\x00\x00;\x00\x00\x00\xb5\xa6\x00\x008\x00\x00\x00\xf1\xa6\x00\x001\x00\x00\x00*\xa7\x00\x007\x00\x00\x00\\\xa7\x00\x00u\x02\x00\x00\x94\xa7\x00\x00\xb0\x00\x00\x00\n\xaa\x00\x00[\x00\x00\x00\xbb\xaa\x00\x00J\x00\x00\x00\x17\xab\x00\x00a\x00\x00\x00b\xab\x00\x00\xbd\x00\x00\x00\u012b\x00\x009\x00\x00\x00\x82\xac\x00\x00\xc5\x00\x00\x00\xbc\xac\x00\x00\xae\x00\x00\x00\x82\xad\x00\x00\xd6\x00\x00\x001\xae\x00\x008\x00\x00\x00\b\xaf\x00\x00%\x00\x00\x00A\xaf\x00\x00W\x00\x00\x00g\xaf\x00\x00\x1d\x00\x00\x00\xbf\xaf\x00\x00=\x00\x00\x00\u076f\x00\x00u\x00\x00\x00\x1b\xb0\x00\x004\x00\x00\x00\x91\xb0\x00\x00-\x00\x00\x00\u01b0\x00\x00\xa3\x00\x00\x00\xf4\xb0\x00\x003\x00\x00\x00\x98\xb1\x00\x002\x00\x00\x00\u0331\x00\x008\x00\x00\x00\xff\xb1\x00\x00\x1e\x00\x00\x008\xb2\x00\x00\x1a\x00\x00\x00W\xb2\x00\x009\x00\x00\x00r\xb2\x00\x00\x13\x00\x00\x00\xac\xb2\x00\x00\x1b\x00\x00\x00\xc0\xb2\x00\x00@\x00\x00\x00\u0732\x00\x00,\x00\x00\x00\x1d\xb3\x00\x00*\x00\x00\x00J\xb3\x00\x007\x00\x00\x00u\xb3\x00\x00'\x00\x00\x00\xad\xb3\x00\x00&\x00\x00\x00\u0573\x00\x00.\x00\x00\x00\xfc\xb3\x00\x00=\x00\x00\x00+\xb4\x00\x00*\x00\x00\x00i\xb4\x00\x000\x00\x00\x00\x94\xb4\x00\x00,\x00\x00\x00\u0174\x00\x00\x1f\x00\x00\x00\xf2\xb4\x00\x00]\x00\x00\x00\x12\xb5\x00\x000\x00\x00\x00p\xb5\x00\x000\x00\x00\x00\xa1\xb5\x00\x00\"\x00\x00\x00\u04b5\x00\x00?\x00\x00\x00\xf5\xb5\x00\x00\x1d\x00\x00\x005\xb6\x00\x00,\x00\x00\x00S\xb6\x00\x00+\x00\x00\x00\x80\xb6\x00\x00$\x00\x00\x00\xac\xb6\x00\x00\x14\x00\x00\x00\u0476\x00\x00*\x00\x00\x00\xe6\xb6\x00\x00A\x00\x00\x00\x11\xb7\x00\x00\x1d\x00\x00\x00S\xb7\x00\x00\x1c\x00\x00\x00q\xb7\x00\x00\x1a\x00\x00\x00\x8e\xb7\x00\x00)\x00\x00\x00\xa9\xb7\x00\x006\x00\x00\x00\u04f7\x00\x00\x1d\x00\x00\x00\n\xb8\x00\x00\x19\x00\x00\x00(\xb8\x00\x00 \x00\x00\x00B\xb8\x00\x00v\x00\x00\x00c\xb8\x00\x00(\x00\x00\x00\u06b8\x00\x00\x16\x00\x00\x00\x03\xb9\x00\x00p\x00\x00\x00\x1a\xb9\x00\x00`\x00\x00\x00\x8b\xb9\x00\x00\x9b\x00\x00\x00\xec\xb9\x00\x00\x97\x00\x00\x00\x88\xba\x00\x00\xa8\x00\x00\x00 \xbb\x00\x00\x1b\x00\x00\x00\u027b\x00\x00\x18\x00\x00\x00\xe5\xbb\x00\x00\x1a\x00\x00\x00\xfe\xbb\x00\x00$\x00\x00\x00\x19\xbc\x00\x00\x1d\x00\x00\x00>\xbc\x00\x00\x17\x00\x00\x00\\\xbc\x00\x00a\x00\x00\x00t\xbc\x00\x00s\x00\x00\x00\u05bc\x00\x00B\x00\x00\x00J\xbd\x00\x00Y\x00\x00\x00\x8d\xbd\x00\x00+\x00\x00\x00\xe7\xbd\x00\x00+\x00\x00\x00\x13\xbe\x00\x006\x00\x00\x00?\xbe\x00\x00;\x00\x00\x00v\xbe\x00\x00q\x00\x00\x00\xb2\xbe\x00\x00/\x00\x00\x00$\xbf\x00\x001\x00\x00\x00T\xbf\x00\x00'\x00\x00\x00\x86\xbf\x00\x00'\x00\x00\x00\xae\xbf\x00\x00\x18\x00\x00\x00\u05bf\x00\x00&\x00\x00\x00\xef\xbf\x00\x00%\x00\x00\x00\x16\xc0\x00\x00(\x00\x00\x00<\xc0\x00\x00#\x00\x00\x00e\xc0\x00\x00K\x00\x00\x00\x89\xc0\x00\x00 \x00\x00\x00\xd5\xc0\x00\x00_\x00\x00\x00\xf6\xc0\x00\x00\x1e\x00\x00\x00V\xc1\x00\x00\"\x00\x00\x00u\xc1\x00\x00\"\x00\x00\x00\x98\xc1\x00\x00\x1f\x00\x00\x00\xbb\xc1\x00\x00-\x00\x00\x00\xdb\xc1\x00\x00-\x00\x00\x00\t\xc2\x00\x009\x00\x00\x007\xc2\x00\x00\x1e\x00\x00\x00q\xc2\x00\x00\x19\x00\x00\x00\x90\xc2\x00\x00c\x00\x00\x00\xaa\xc2\x00\x00#\x00\x00\x00\x0e\xc3\x00\x00\x82\x00\x00\x002\xc3\x00\x00\x94\x00\x00\x00\xb5\xc3\x00\x00H\x00\x00\x00J\xc4\x00\x00&\x00\x00\x00\x93\xc4\x00\x00e\x00\x00\x00\xba\xc4\x00\x00z\x00\x00\x00 \xc5\x00\x00J\x00\x00\x00\x9b\xc5\x00\x00\xe5\x00\x00\x00\xe6\xc5\x00\x00W\x00\x00\x00\xcc\xc6\x00\x00E\x00\x00\x00$\xc7\x00\x00a\x00\x00\x00j\xc7\x00\x00v\x00\x00\x00\xcc\xc7\x00\x00\xcb\x00\x00\x00C\xc8\x00\x00\xcf\x00\x00\x00\x0f\xc9\x00\x00\x1e\x01\x00\x00\xdf\xc9\x00\x00\x1c\x00\x00\x00\xfe\xca\x00\x00T\x00\x00\x00\x1b\xcb\x00\x00\x17\x00\x00\x00p\xcb\x00\x00/\x00\x00\x00\x88\xcb\x00\x009\x00\x00\x00\xb8\xcb\x00\x00\x1e\x00\x00\x00\xf2\xcb\x00\x00=\x00\x00\x00\x11\xcc\x00\x00$\x00\x00\x00O\xcc\x00\x00\x1f\x00\x00\x00t\xcc\x00\x00&\x00\x00\x00\x94\xcc\x00\x00+\x00\x00\x00\xbb\xcc\x00\x00G\x00\x00\x00\xe7\xcc\x00\x00\x14\x00\x00\x00/\xcd\x00\x00r\x00\x00\x00D\xcd\x00\x00\x13\x00\x00\x00\xb7\xcd\x00\x00\x18\x00\x00\x00\xcb\xcd\x00\x00/\x00\x00\x00\xe4\xcd\x00\x00\xaa\x01\x00\x00\x14\xce\x00\x00\xe0\x00\x00\x00\xbf\xcf\x00\x00\xba\x00\x00\x00\xa0\xd0\x00\x00\x10\x02\x00\x00[\xd1\x00\x00%\x01\x00\x00l\xd3\x00\x00z\x00\x00\x00\x92\xd4\x00\x00d\x02\x00\x00\r\xd5\x00\x00\x8b\x01\x00\x00r\xd7\x00\x00\x98\x01\x00\x00\xfe\xd8\x00\x00\x84\x01\x00\x00\x97\xda\x00\x00\x88\x01\x00\x00\x1c\xdc\x00\x00A\x01\x00\x00\xa5\xdd\x00\x00\a\x02\x00\x00\xe7\xde\x00\x00q\x01\x00\x00\xef\xe0\x00\x00\\\x05\x00\x00a\xe2\x00\x00s\x02\x00\x00\xbe\xe7\x00\x00#\x02\x00\x002\xea\x00\x00w\x01\x00\x00V\xec\x00\x00\xb9\x01\x00\x00\xce\xed\x00\x00\xe5\x01\x00\x00\x88\xef\x00\x00\n\x02\x00\x00n\xf1\x00\x00\xb4\x00\x00\x00y\xf3\x00\x00\xbf\x02\x00\x00.\xf4\x00\x00\x97\x03\x00\x00\xee\xf6\x00\x00\xbf\x01\x00\x00\x86\xfa\x00\x00A\x00\x00\x00F\xfc\x00\x00?\x00\x00\x00\x88\xfc\x00\x00,\x03\x00\x00\xc8\xfc\x00\x00<\x00\x00\x00\xf5\xff\x00\x00P\x00\x00\x002\x00\x01\x00S\x00\x00\x00\x83\x00\x01\x00<\x00\x00\x00\xd7\x00\x01\x00\xb3\x01\x00\x00\x14\x01\x01\x00\x15\x03\x00\x00\xc8\x02\x01\x00\xee\x01\x00\x00\xde\x05\x01\x00\x0e\x02\x00\x00\xcd\a\x01\x00\xdb\x01\x00\x00\xdc\t\x01\x00e\x01\x00\x00\xb8\v\x01\x00T\x01\x00\x00\x1e\r\x01\x00\xd4\x06\x00\x00s\x0e\x01\x00\x1d\x02\x00\x00H\x15\x01\x00\f\x03\x00\x00f\x17\x01\x00\x05\x03\x00\x00s\x1a\x01\x00\xfb\x00\x00\x00y\x1d\x01\x00\xb5\x01\x00\x00u\x1e\x01\x00\xb5\x01\x00\x00+ \x01\x00\x18\x00\x00\x00\xe1!\x01\x00<\x00\x00\x00\xfa!\x01\x00=\x00\x00\x007\"\x01\x00\xc6\x00\x00\x00u\"\x01\x00g\x02\x00\x00<#\x01\x00.\x00\x00\x00\xa4%\x01\x00>\x03\x00\x00\xd3%\x01\x00g\x00\x00\x00\x12)\x01\x00Q\x00\x00\x00z)\x01\x00R\x00\x00\x00\xcc)\x01\x00\"\x00\x00\x00\x1f*\x01\x00X\x02\x00\x00B*\x01\x004\x00\x00\x00\x9b,\x01\x00}\x00\x00\x00\xd0,\x01\x00k\x01\x00\x00N-\x01\x00\x83\a\x00\x00\xba.\x01\x00k\x01\x00\x00>6\x01\x00\x85\x00\x00\x00\xaa7\x01\x00\xee\x00\x00\x0008\x01\x00\xd9\x00\x00\x00\x1f9\x01\x00\x10\x05\x00\x00\xf99\x01\x00\x15\x05\x00\x00\n?\x01\x00\x1c\x00\x00\x00 D\x01\x00\x1e\x00\x00\x00=D\x01\x00\x99\x02\x00\x00\\D\x01\x00\xbc\x01\x00\x00\xf6F\x01\x00\x9c\x01\x00\x00\xb3H\x01\x00s\x01\x00\x00PJ\x01\x00\t\x01\x00\x00\xc4K\x01\x00\xec\x01\x00\x00\xceL\x01\x00\x1c\x01\x00\x00\xbbN\x01\x00\xc3\x01\x00\x00\xd8O\x01\x00\x1b\x02\x00\x00\x9cQ\x01\x00\xc0\x00\x00\x00\xb8S\x01\x00\xe1\x02\x00\x00yT\x01\x00\x9f\x00\x00\x00[W\x01\x00X\x00\x00\x00\xfbW\x01\x00*\x02\x00\x00TX\x01\x00o\x00\x00\x00\u007fZ\x01\x00v\x00\x00\x00\xefZ\x01\x00\x01\x01\x00\x00f[\x01\x00v\x00\x00\x00h\\\x01\x00u\x00\x00\x00\xdf\\\x01\x00\xf5\x00\x00\x00U]\x01\x00~\x00\x00\x00K^\x01\x00k\x00\x00\x00\xca^\x01\x00\xc8\x01\x00\x006_\x01\x00#\x04\x00\x00\xff`\x01\x00;\x00\x00\x00#e\x01\x008\x00\x00\x00_e\x01\x001\x00\x00\x00\x98e\x01\x007\x00\x00\x00\xcae\x01\x00|\x02\x00\x00\x02f\x01\x00\xb4\x00\x00\x00\u007fh\x01\x00[\x00\x00\x004i\x01\x00J\x00\x00\x00\x90i\x01\x00a\x00\x00\x00\xdbi\x01\x00\xbd\x00\x00\x00=j\x01\x009\x00\x00\x00\xfbj\x01\x00\xc5\x00\x00\x005k\x01\x00\xae\x00\x00\x00\xfbk\x01\x00\xd7\x00\x00\x00\xaal\x01\x00c\x00\x00\x00\x82m\x01\x00%\x00\x00\x00\xe6m\x01\x00_\x00\x00\x00\fn\x01\x00\x1d\x00\x00\x00ln\x01\x00=\x00\x00\x00\x8an\x01\x00y\x00\x00\x00\xc8n\x01\x004\x00\x00\x00Bo\x01\x00-\x00\x00\x00wo\x01\x00\xa5\x00\x00\x00\xa5o\x01\x003\x00\x00\x00Kp\x01\x002\x00\x00\x00\u007fp\x01\x008\x00\x00\x00\xb2p\x01\x00\x1e\x00\x00\x00\xebp\x01\x00\x1a\x00\x00\x00\nq\x01\x009\x00\x00\x00%q\x01\x00\x13\x00\x00\x00_q\x01\x00\x1b\x00\x00\x00sq\x01\x00@\x00\x00\x00\x8fq\x01\x00,\x00\x00\x00\xd0q\x01\x00*\x00\x00\x00\xfdq\x01\x007\x00\x00\x00(r\x01\x00'\x00\x00\x00`r\x01\x00Q\x00\x00\x00\x88r\x01\x00.\x00\x00\x00\xdar\x01\x00=\x00\x00\x00\ts\x01\x00*\x00\x00\x00Gs\x01\x000\x00\x00\x00rs\x01\x00,\x00\x00\x00\xa3s\x01\x00\x1f\x00\x00\x00\xd0s\x01\x00]\x00\x00\x00\xf0s\x01\x00:\x00\x00\x00Nt\x01\x00=\x00\x00\x00\x89t\x01\x00\"\x00\x00\x00\xc7t\x01\x00?\x00\x00\x00\xeat\x01\x007\x00\x00\x00*u\x01\x00,\x00\x00\x00bu\x01\x00+\x00\x00\x00\x8fu\x01\x00$\x00\x00\x00\xbbu\x01\x00'\x00\x00\x00\xe0u\x01\x00:\x00\x00\x00\bv\x01\x00b\x00\x00\x00Cv\x01\x001\x00\x00\x00\xa6v\x01\x00-\x00\x00\x00\xd8v\x01\x00$\x00\x00\x00\x06w\x01\x00)\x00\x00\x00+w\x01\x006\x00\x00\x00Uw\x01\x00\x1d\x00\x00\x00\x8cw\x01\x00\x19\x00\x00\x00\xaaw\x01\x00 \x00\x00\x00\xc4w\x01\x00w\x00\x00\x00\xe5w\x01\x00(\x00\x00\x00]x\x01\x00\x16\x00\x00\x00\x86x\x01\x00p\x00\x00\x00\x9dx\x01\x00h\x00\x00\x00\x0ey\x01\x00\x9b\x00\x00\x00wy\x01\x00\x97\x00\x00\x00\x13z\x01\x00\xa9\x00\x00\x00\xabz\x01\x00\x1b\x00\x00\x00U{\x01\x00\x18\x00\x00\x00q{\x01\x00\x1a\x00\x00\x00\x8a{\x01\x00$\x00\x00\x00\xa5{\x01\x00\x1d\x00\x00\x00\xca{\x01\x00%\x00\x00\x00\xe8{\x01\x00a\x00\x00\x00\x0e|\x01\x00s\x00\x00\x00p|\x01\x00B\x00\x00\x00\xe4|\x01\x00]\x00\x00\x00'}\x01\x00+\x00\x00\x00\x85}\x01\x00+\x00\x00\x00\xb1}\x01\x006\x00\x00\x00\xdd}\x01\x00;\x00\x00\x00\x14~\x01\x00q\x00\x00\x00P~\x01\x00/\x00\x00\x00\xc2~\x01\x001\x00\x00\x00\xf2~\x01\x00'\x00\x00\x00$\u007f\x01\x00'\x00\x00\x00L\u007f\x01\x00\x18\x00\x00\x00t\u007f\x01\x00&\x00\x00\x00\x8d\u007f\x01\x00%\x00\x00\x00\xb4\u007f\x01\x00(\x00\x00\x00\xda\u007f\x01\x00#\x00\x00\x00\x03\x80\x01\x00K\x00\x00\x00'\x80\x01\x00 \x00\x00\x00s\x80\x01\x00_\x00\x00\x00\x94\x80\x01\x00-\x00\x00\x00\xf4\x80\x01\x007\x00\x00\x00\"\x81\x01\x00:\x00\x00\x00Z\x81\x01\x004\x00\x00\x00\x95\x81\x01\x00:\x00\x00\x00\u0281\x01\x00:\x00\x00\x00\x05\x82\x01\x009\x00\x00\x00@\x82\x01\x00\x1e\x00\x00\x00z\x82\x01\x00\x1a\x00\x00\x00\x99\x82\x01\x00c\x00\x00\x00\xb4\x82\x01\x00#\x00\x00\x00\x18\x83\x01\x00\x82\x00\x00\x00<\x83\x01\x00\x99\x00\x00\x00\xbf\x83\x01\x00H\x00\x00\x00Y\x84\x01\x00&\x00\x00\x00\xa2\x84\x01\x00e\x00\x00\x00\u0244\x01\x00z\x00\x00\x00/\x85\x01\x00J\x00\x00\x00\xaa\x85\x01\x00\xf5\x00\x00\x00\xf5\x85\x01\x00X\x00\x00\x00\xeb\x86\x01\x00I\x00\x00\x00D\x87\x01\x00a\x00\x00\x00\x8e\x87\x01\x00w\x00\x00\x00\xf0\x87\x01\x00\xcf\x00\x00\x00h\x88\x01\x00\xd3\x00\x00\x008\x89\x01\x00/\x01\x00\x00\f\x8a\x01\x00\x1c\x00\x00\x00<\x8b\x01\x00X\x00\x00\x00Y\x8b\x01\x00*\x00\x00\x00\xb2\x8b\x01\x00:\x00\x00\x00\u074b\x01\x009\x00\x00\x00\x18\x8c\x01\x00\x1e\x00\x00\x00R\x8c\x01\x00=\x00\x00\x00q\x8c\x01\x003\x00\x00\x00\xaf\x8c\x01\x00'\x00\x00\x00\xe3\x8c\x01\x00&\x00\x00\x00\v\x8d\x01\x00+\x00\x00\x002\x8d\x01\x00G\x00\x00\x00^\x8d\x01\x00*\x00\x00\x00\xa6\x8d\x01\x00v\x00\x00\x00\u044d\x01\x00\x13\x00\x00\x00H\x8e\x01\x00\x18\x00\x00\x00\\\x8e\x01\x00/\x00\x00\x00u\x8e\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00^\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00F\x00\x00\x00\xc4\x00\x00\x00\x0f\x00\x00\x00\xc3\x00\x00\x00\x00\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00\x86\x00\x00\x00\xeb\x00\x00\x00c\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00o\x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00J\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x98\x00\x00\x00U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdb\x00\x00\x00\x17\x00\x00\x00u\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\xb7\x00\x00\x00\xd7\x00\x00\x00*\x00\x00\x00\x99\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x84\x00\x00\x00\x9c\x00\x00\x00\xe6\x00\x00\x00\x9d\x00\x00\x00\xc5\x00\x00\x00\xd9\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\xcd\x00\x00\x00\xcb\x00\x00\x00y\x00\x00\x00\x97\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00C\x00\x00\x00\x93\x00\x00\x00\xad\x00\x00\x00\xe1\x00\x00\x00\xa6\x00\x00\x00\xd0\x00\x00\x00r\x00\x00\x00+\x00\x00\x006\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00h\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xd1\x00\x00\x00\xde\x00\x00\x00;\x00\x00\x00\x00\x00\x00\x00\xe9\x00\x00\x00\xe7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\x00\x00\x00/\x00\x00\x00V\x00\x00\x00\x8d\x00\x00\x00\xe3\x00\x00\x00!\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd3\x00\x00\x00\x88\x00\x00\x00l\x00\x00\x00s\x00\x00\x00g\x00\x00\x00\x05\x00\x00\x00\xc6\x00\x00\x00#\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00\x00\x00\x00\x00\xc2\x00\x00\x00\x13\x00\x00\x00S\x00\x00\x00G\x00\x00\x00$\x00\x00\x00\xc1\x00\x00\x00\xb5\x00\x00\x00X\x00\x00\x00m\x00\x00\x00\t\x00\x00\x00x\x00\x00\x00\xb8\x00\x00\x00\xbd\x00\x00\x00k\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00E\x00\x00\x00\xbf\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x00\x00:\x00\x00\x00\x82\x00\x00\x00\x81\x00\x00\x00&\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00[\x00\x00\x00I\x00\x00\x00e\x00\x00\x00\x04\x00\x00\x00>\x00\x00\x00\b\x00\x00\x00\x94\x00\x00\x00\x8f\x00\x00\x00\xce\x00\x00\x00?\x00\x00\x00Y\x00\x00\x00\xda\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x004\x00\x00\x00\xcc\x00\x00\x00\f\x00\x00\x005\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\xe5\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00 \x00\x00\x00)\x00\x00\x00\xcf\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00Z\x00\x00\x00\"\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00]\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x00\x00\x00j\x00\x00\x008\x00\x00\x00\xa3\x00\x00\x00q\x00\x00\x00t\x00\x00\x00_\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00@\x00\x00\x00\xd2\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x92\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x95\x00\x00\x00\x06\x00\x00\x00\xa8\x00\x00\x00\xae\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x91\x00\x00\x00\x0e\x00\x00\x00{\x00\x00\x00\xa7\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd5\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00w\x00\x00\x00\x12\x00\x00\x00=\x00\x00\x00\xaf\x00\x00\x00\a\x00\x00\x00\xdf\x00\x00\x00\xc0\x00\x00\x00N\x00\x00\x00%\x00\x00\x009\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\x00\x00\x00\x00\x00\x00\x00\u007f\x00\x00\x00\xbe\x00\x00\x00\xe2\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\xb3\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00D\x00\x00\x00B\x00\x00\x00n\x00\x00\x00\x00\x00\x00\x00\xd6\x00\x00\x00\x83\x00\x00\x00\n\x00\x00\x00W\x00\x00\x00\x14\x00\x00\x00Q\x00\x00\x00\xd4\x00\x00\x00d\x00\x00\x00\xac\x00\x00\x00\x16\x00\x00\x00\x96\x00\x00\x00K\x00\x00\x002\x00\x00\x00\x1a\x00\x00\x00\xb4\x00\x00\x00f\x00\x00\x00\xa2\x00\x00\x00\xe8\x00\x00\x00\x02\x00\x00\x00A\x00\x00\x00\xe4\x00\x00\x00\x8c\x00\x00\x00\x9a\x00\x00\x00`\x00\x00\x00\xab\x00\x00\x00M\x00\x00\x007\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9b\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\xdd\x00\x00\x00\x8e\x00\x00\x00\xca\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x003\x00\x00\x00T\x00\x00\x00\x87\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\xaa\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x00\xc7\x00\x00\x00\x8b\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods\n\n\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: EMAIL\nPOT-Creation-Date: 2017-03-14 21:32-0700\nPO-Revision-Date: 2019-02-14 10:33+0900\nLast-Translator: Giri Kuncoro \nLanguage-Team: \nLanguage: ja\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.1.1\nX-Poedit-SourceCharset: UTF-8\nPlural-Forms: nplurals=2; plural=(n > 1);\n\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin \u2014clusterrole=cluster-admin \u2014user=user1 \u2014user=user2 \u2014group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin \u2014clusterrole=admin \u2014user=user1 \u2014user=user2 \u2014group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config \u2014from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config \u2014from-file=key1=/path/to/bar/file1.txt \u2014from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config \u2014from-literal=key1=config1 \u2014from-literal=key2=config2\x00\n\t\t # If you don\u2019t already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret \u2014docker-server=DOCKER_REGISTRY_SERVER \u2014docker-username=DOCKER_USER \u2014docker-password=DOCKER_PASSWORD \u2014docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: \u2014prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply \u2014prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply \u2014prune -f manifest.yaml \u2014all \u2014prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \u201cfoo\u201d, with the number of pods between 2 and 10, no target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo \u2014min=2 \u2014max=10\n\n\t\t# Auto scale a replication controller \u201cfoo\u201d, with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo \u2014max=5 \u2014cpu-percent=80\x00\n\t\t# Convert \u2018pod.yaml\u2019 to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by \u2018pod.yaml\u2019 to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml \u2014local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \u201cpod-reader\u201d that allows user to perform \u201cget\u201d, \u201cwatch\u201d and \u201clist\u201d on pods\n\t\tkubectl create clusterrole pod-reader \u2014verb=get,list,watch \u2014resource=pods\n\n\t\t# Create a ClusterRole named \u201cpod-reader\u201d with ResourceName specified\n\t\tkubectl create clusterrole pod-reader \u2014verb=get,list,watch \u2014resource=pods \u2014resource-name=readablepod\x00\n\t\t# Create a Role named \u201cpod-reader\u201d that allows user to perform \u201cget\u201d, \u201cwatch\u201d and \u201clist\u201d on pods\n\t\tkubectl create role pod-reader \u2014verb=get \u2014verb=list \u2014verb=watch \u2014resource=pods\n\n\t\t# Create a Role named \u201cpod-reader\u201d with ResourceName specified\n\t\tkubectl create role pod-reader \u2014verb=get \u2014verg=list \u2014verb=watch \u2014resource=pods \u2014resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota \u2014hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort \u2014hard=pods=100 \u2014scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb \u2014selector=app=rails \u2014min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb \u2014selector=app=nginx \u2014min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml \u2014edit \u2014output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod \u2014port=444 \u2014name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \u201cnginx-https\u201d\n\t\tkubectl expose service nginx \u2014port=443 \u2014target-port=8443 \u2014name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named \u2018video-stream\u2019.\n\t\tkubectl expose rc streamer \u2014port=4100 \u2014protocol=udp \u2014name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx \u2014port=80 \u2014target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx \u2014port=80 \u2014target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \u201cbaz\u201d and \u201cfoo\u201d\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo \u2014now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo \u2014grace-period=0 \u2014force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods \u2014all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \u201cpod.json\u201d\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the \u2018frontend\u2019 replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \u201cfoo\u201d, even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo \u2014force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo \u2014grace-period=900\x00\n\t\t# Edit the service named \u2018docker-registry\u2019:\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\u201cnano\u201d kubectl edit svc/docker-registry\n\n\t\t# Edit the job \u2018myjob\u2019 in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment \u2018mydeployment\u2019 in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml \u2014save-config\x00\n\t\t# Get output from running \u2018date\u2019 from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running \u2018date\u2019 in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to \u2018bash\u2019 in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from \u2018bash\u2019 back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t \u2014 bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to \u2018bash\u2019 in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from \u2018bash\u2019 back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \u201c\n# Kubectl shell completion\nsource \u2018$HOME/.kube/completion.bash.inc\u2019\n\u201c >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \u201cpod.yaml\u201d in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 \u2014template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \u201cfoo\u201d as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \u201cfoo\u201d as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p \u2018{\u201cspec\u201d:{\u201cunschedulable\u201d:true}}\u2019\n\n\t\t# Partially update a node identified by the type and name specified in \u201cnode.json\u201d using strategic merge patch\n\t\tkubectl patch -f node.json -p \u2018{\u201cspec\u201d:{\u201cunschedulable\u201d:true}}\u2019\n\n\t\t# Update a container\u2019s image; spec.containers[*].name is required because it\u2019s a merge key\n\t\tkubectl patch pod valid-pod -p \u2018{\u201cspec\u201d:{\u201ccontainers\u201d:[{\u201cname\u201d:\u201dkubernetes-serve-hostname\u201d,\u201dimage\u201d:\u201dnew image\u201d}]}}\u2019\n\n\t\t# Update a container\u2019s image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod \u2014type=\u2018json\u2019 -p=\u2018[{\u201cop\u201d: \u201creplace\u201d, \u201cpath\u201d: \u201c/spec/containers/0/image\u201d, \u201cvalue\u201d:\u201dnew image\u201d}]\u2019\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod\u2019s image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed \u2019s/\\(image: myimage\\):.*$/\x01:v4/\u2018 | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace \u2014force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs \u2014tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs \u2014since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy \u2014port=8011 \u2014www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy \u2014port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy \u2014api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named \u2018foo\u2019 to 3.\n\t\tkubectl scale \u2014replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \u201cfoo.yaml\u201d to 3.\n\t\tkubectl scale \u2014replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql\u2019s current size is 2, scale mysql to 3.\n\t\tkubectl scale \u2014current-replicas=2 \u2014replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale \u2014replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named \u2018cron\u2019 to 3.\n\t\tkubectl scale \u2014replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml \u2014create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod \u2014namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME \u2014containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox \u2014image=busybox \u2014restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx \u2014image=nginx \u2014 \u2026 \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx \u2014image=nginx \u2014command \u2014 \u2026 \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi \u2014image=perl \u2014restart=OnFailure \u2014 perl -Mbignum=bpi -wle \u2018print bpi(2000)\u2019\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi \u2014schedule=\u201c0/5 * * * ?\u201d \u2014image=perl \u2014restart=OnFailure \u2014 perl -Mbignum=bpi -wle \u2018print bpi(2000)\u2019\x00\n\t\t# Update node \u2018foo\u2019 with a taint with key \u2018dedicated\u2019 and value \u2018special-user\u2019 and effect \u2018NoSchedule\u2019.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node \u2018foo\u2019 the taint with key \u2018dedicated\u2019 and effect \u2018NoSchedule\u2019 if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node \u2018foo\u2019 all the taints with key \u2018dedicated\u2019\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod \u2018foo\u2019 with the label \u2018unhealthy\u2019 and the value \u2018true\u2019.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod \u2018foo\u2019 with the label \u2018status\u2019 and the value \u2018unhealthy\u2019, overwriting any existing value.\n\t\tkubectl label \u2014overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods \u2014all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \u201cpod.json\u201d\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod \u2018foo\u2019 only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy \u2014resource-version=1\n\n\t\t# Update pod \u2018foo\u2019 by removing a label named \u2018bar\u2019 if it exists.\n\t\t# Does not require the \u2014overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 \u2014image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend \u2014image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 \u2014rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn\u2019t exist yet.\n\t\tTo use \u2018apply\u2019, always create the resource initially with either \u2018apply\u2019 or \u2018create \u2014save-config\u2019.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the \u2014prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by \u2014output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER \u2014username=DOCKER_USER \u2014password=DOCKER_PASSWORD \u2014email=DOCKER_EMAIL\u2019.\n\n That produces a ~/.dockercfg file that is used by subsequent \u2018docker push\u2019 and \u2018docker pull\u2019 commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod\u2019s processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee \u2018kubectl delete \u2014help\u2019 for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe \u2018top pod\u2019 command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse \u2014force. \u2014force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t\u2019drain\u2019 waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \u201c-o json\u201d.\n\n\t\tThe flag \u2014windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew \u2014prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf \u2014current-replicas or \u2014resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though \u2018kubectl apply -f \u2019 was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy \u2014api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy \u2014www=/my/files \u2014www-prefix=/static/ \u2014api-prefix=/api/\n\n\t\tThe above lets you \u2018curl localhost:8001/api/v1/pods\u2019.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy \u2014api-prefix=/custom/\n\n\t\tThe above lets you \u2018curl localhost:8001/custom/api/v1/pods\u2019\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If \u2014overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If \u2014resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the \u2018tar\u2019 binary is present in your container\n\t # image. If \u2018tar\u2019 is not present, \u2018kubectl cp\u2019 will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret \u2014cert=path/to/tls.cert \u2014key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret \u2014from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret \u2014from-file=ssh-privatekey=~/.ssh/id_rsa \u2014from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret \u2014from-literal=key1=supersecret \u2014from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns \u2014external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs \u2014tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs \u2014tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs \u2014clusterip=\u201cNone\u201d\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep \u2014image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns \u2014tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump \u2014output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump \u2014all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump \u2014namespaces default,kube-system \u2014output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description=\u2018my frontend\u2019\n\n # Update pod \u2018foo\u2019 with the annotation \u2018description\u2019 and the value \u2018my frontend running nginx\u2019, overwriting any existing value.\n kubectl annotate \u2014overwrite pods foo description=\u2018my frontend running nginx\u2019\n\n # Update all pods in the namespace\n kubectl annotate pods \u2014all description=\u2018my frontend running nginx\u2019\n\n # Update pod \u2018foo\u2019 only if the resource is unchanged from version 1.\n kubectl annotate pods foo description=\u2018my frontend running nginx\u2019 \u2014resource-version=1\n\n # Update pod \u2018foo\u2019 by removing an annotation named \u2018description\u2019 if it exists.\n # Does not require the \u2014overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with \u2014output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the \u2018kube-system\u2019 namespace, but you can\n switch to a different namespace with the \u2014namespaces flag, or specify \u2014all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use \u2018kubectl cluster-info dump\u2019.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if \u2014expose is true.\x00\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u6307\u5b9a\u307e\u305f\u306f\u6a19\u6e96\u5165\u529b\u7d4c\u7531\u3067\u30ea\u30bd\u30fc\u30b9\u306b\u30b3\u30f3\u30d5\u30a3\u30b0\u3092\u9069\u7528\u3059\u308b\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to \u2018None\u2019 for a \u2018headless\u2019 service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to \u2018None\u2019 to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when \u2014image is specified, ignored otherwise. Required when using \u2014image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u6307\u5b9a\u307e\u305f\u306f\u6a19\u6e96\u5165\u529b\u7d4c\u7531\u3067\u30ea\u30bd\u30fc\u30b9\u3092\u4f5c\u6210\u3059\u308b\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00kubeconfig\u304b\u3089\u6307\u5b9a\u3057\u305f\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u524a\u9664\u3059\u308b\x00kubeconfig\u304b\u3089\u6307\u5b9a\u3057\u305f\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u524a\u9664\u3059\u308b\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x001\u3064\u307e\u305f\u306f\u8907\u6570\u306e\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u8a18\u8ff0\u3059\u308b\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u60c5\u5831\u3092\u8868\u793a\u3059\u308b\x00kubeconfig\u3067\u5b9a\u7fa9\u3055\u308c\u305f\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8868\u793a\u3059\u308b\x00\u30de\u30fc\u30b8\u3055\u308c\u305fkubeconfig\u306e\u8a2d\u5b9a\u307e\u305f\u306f\u6307\u5b9a\u3055\u308c\u305fkubeconfig\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a\u3059\u308b\x001\u3064\u307e\u305f\u306f\u8907\u6570\u306e\u30ea\u30bd\u30fc\u30b9\u3092\u8868\u793a\u3059\u308b\x00\u30ab\u30ec\u30f3\u30c8\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u8868\u793a\u3059\u308b\x00\u30ea\u30bd\u30fc\u30b9\u306e\u8aac\u660e\u3092\u8868\u793a\u3059\u308b\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when \u2014image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: \u2018None\u2019, \u2018ClientIP\u2019\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with \u2014filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00kubeconfig\u30d5\u30a1\u30a4\u30eb\u3092\u5909\u66f4\u3059\u308b\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: \u2018extensions/v1beta1\u2019).)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00\u30ea\u30bd\u30fc\u30b9\u306e\u30bb\u30ec\u30af\u30bf\u30fc\u3092\u8a2d\u5b9a\u3059\u308b\x00kubeconfig\u306b\u30af\u30e9\u30b9\u30bf\u30fc\u30a8\u30f3\u30c8\u30ea\u3092\u8a2d\u5b9a\u3059\u308b\x00kubeconfig\u306b\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u30a8\u30f3\u30c8\u30ea\u3092\u8a2d\u5b9a\u3059\u308b\x00kubeconfig\u306b\u30e6\u30fc\u30b6\u30fc\u30a8\u30f3\u30c8\u30ea\u3092\u8a2d\u5b9a\u3059\u308b\x00kubeconfig\u30d5\u30a1\u30a4\u30eb\u5185\u306e\u5909\u6570\u3092\u500b\u5225\u306b\u8a2d\u5b9a\u3059\u308b\x00kubeconfig\u306b\u30ab\u30ec\u30f3\u30c8\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3092\u8a2d\u5b9a\u3059\u308b\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for \u2014target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default \u2018deployment\u2019. Only relevant when \u2014image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: \u2018service/v1\u2019 and \u2018service/v2\u2019. The only difference between them is that service port in v1 is named \u2018default\u2019, while it is left unnamed in v2. Default is \u2018service/v2\u2019.\x00The name of the generator to use for creating a service. Only used if \u2014expose is true\x00The network protocol for the service to be created. Default is \u2018TCP\u2019.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If \u2014expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, \u2018cpu=200m,memory=512Mi\u2019. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The resource requirement requests for this container. For example, \u2018cpu=100m,memory=256Mi\u2019. Note that server side components may assign requests depending on the server configuration, such as limit ranges.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to \u2018Always\u2019 a deployment is created, if set to \u2018OnFailure\u2019 a job is created, if set to \u2018Never\u2019, a regular pod is created. For the latter two \u2014replicas must be 1. Default \u2018Always\u2019, for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is \u2018ClusterIP\u2019.\x00\u73fe\u5728\u306e\u30ed\u30fc\u30eb\u30a2\u30a6\u30c8\u3092\u53d6\u308a\u6d88\u3059\x00kubeconfig\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u5909\u6570\u3092\u500b\u5225\u306b\u524a\u9664\u3059\u308b\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00\u30ea\u30bd\u30fc\u30b9\u306e\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u66f4\u65b0\u3059\u308b\x00\u30ea\u30bd\u30fc\u30b9\u306e\u30e9\u30d9\u30eb\u3092\u66f4\u65b0\u3059\u308b\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00\u30ed\u30fc\u30eb\u30a2\u30a6\u30c8\u306e\u5c65\u6b74\u3092\u8868\u793a\u3059\u308b\x00Where to output the files. If empty or \u2018-\u2018 uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00") + +func translationsKubectlJa_jpLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlJa_jpLc_messagesK8sMo, nil +} + +func translationsKubectlJa_jpLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlJa_jpLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ja_JP/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlJa_jpLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR girikuncoro@gmail.com, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-03-14 21:32-0700\n" +"PO-Revision-Date: 2019-02-14 10:33+0900\n" +"Last-Translator: Giri Kuncoro \n" +"Language-Team: \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.1.1\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin —clusterrole=cluster-" +"admin —user=user1 —user=user2 —group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin —clusterrole=admin —user=user1 —" +"user=user2 —group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config —from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config —from-file=key1=/path/to/bar/file1." +"txt —from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config —from-literal=key1=config1 —from-" +"literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # If you don’t already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret —docker-" +"server=DOCKER_REGISTRY_SERVER —docker-username=DOCKER_USER —docker-" +"password=DOCKER_PASSWORD —docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: —prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply —prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply —prune -f manifest.yaml —all —prune-whitelist=core/v1/" +"ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# Auto scale a deployment “foo”, with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo —min=2 —max=10\n" +"\n" +"\t\t# Auto scale a replication controller “foo”, with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo —max=5 —cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# Convert ‘pod.yaml’ to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by ‘pod.yaml’ to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml —local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a ClusterRole named “pod-reader” that allows user to perform " +"“get”, “watch” and “list” on pods\n" +"\t\tkubectl create clusterrole pod-reader —verb=get,list,watch —" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named “pod-reader” with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader —verb=get,list,watch —" +"resource=pods —resource-name=readablepod" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# Create a Role named “pod-reader” that allows user to perform “get”, " +"“watch” and “list” on pods\n" +"\t\tkubectl create role pod-reader —verb=get —verb=list —verb=watch —" +"resource=pods\n" +"\n" +"\t\t# Create a Role named “pod-reader” with ResourceName specified\n" +"\t\tkubectl create role pod-reader —verb=get —verg=list —verb=watch —" +"resource=pods —resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota —hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort —hard=pods=100 —scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb —selector=app=rails —min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb —selector=app=nginx —min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml —edit —output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod —port=444 —name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name “nginx-https”\n" +"\t\tkubectl expose service nginx —port=443 —target-port=8443 —name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named ‘video-stream’.\n" +"\t\tkubectl expose rc streamer —port=4100 —protocol=udp —name=video-stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx —port=80 —target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx —port=80 —target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names “baz” and “foo”\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo —now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo —grace-period=0 —force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods —all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in “pod.json”\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the ‘frontend’ replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# Drain node “foo”, even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo —force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo —grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# Edit the service named ‘docker-registry’:\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=“nano” kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job ‘myjob’ in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment ‘mydeployment’ in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml —save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# Get output from running ‘date’ from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running ‘date’ in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to ‘bash’ in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from ‘bash’ back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t — bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to ‘bash’ in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from ‘bash’ back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf “\n" +"# Kubectl shell completion\n" +"source ‘$HOME/.kube/completion.bash.inc’\n" +"“ >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in “pod.yaml” in JSON " +"output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 —template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# Mark node “foo” as schedulable.\n" +"\t\t$ kubectl uncordon foo" + +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# Mark node “foo” as unschedulable.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p ‘{“spec”:{“unschedulable”:true}}’\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"“node.json” using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p ‘{“spec”:{“unschedulable”:true}}’\n" +"\n" +"\t\t# Update a container’s image; spec.containers[*].name is required " +"because it’s a merge key\n" +"\t\tkubectl patch pod valid-pod -p ‘{“spec”:{“containers”:" +"[{“name”:”kubernetes-serve-hostname”,”image”:”new image”}]}}’\n" +"\n" +"\t\t# Update a container’s image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod —type=‘json’ -p=‘[{“op”: “replace”, “path”: " +"“/spec/containers/0/image”, “value”:”new image”}]’" + +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" + +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod’s image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed ’s/\\(image: myimage\\):.*$/:v4/‘ | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace —force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs —tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs —since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy —port=8011 —www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy —port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy —api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Scale a replicaset named ‘foo’ to 3.\n" +"\t\tkubectl scale —replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in “foo.yaml” " +"to 3.\n" +"\t\tkubectl scale —replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql’s current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale —current-replicas=2 —replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale —replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named ‘cron’ to 3.\n" +"\t\tkubectl scale —replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml —create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod —namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME —containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox —image=busybox —restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx —image=nginx — \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx —image=nginx —command — \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi —image=perl —restart=OnFailure — perl -Mbignum=bpi -wle " +"‘print bpi(2000)’\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi —schedule=“0/5 * * * ?” —image=perl —restart=OnFailure — " +"perl -Mbignum=bpi -wle ‘print bpi(2000)’" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Update node ‘foo’ with a taint with key ‘dedicated’ and value ‘special-" +"user’ and effect ‘NoSchedule’.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node ‘foo’ the taint with key ‘dedicated’ and effect " +"‘NoSchedule’ if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node ‘foo’ all the taints with key ‘dedicated’\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Update pod ‘foo’ with the label ‘unhealthy’ and the value ‘true’.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod ‘foo’ with the label ‘status’ and the value ‘unhealthy’, " +"overwriting any existing value.\n" +"\t\tkubectl label —overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods —all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in “pod.json”\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod ‘foo’ only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy —resource-version=1\n" +"\n" +"\t\t# Update pod ‘foo’ by removing a label named ‘bar’ if it exists.\n" +"\t\t# Does not require the —overwrite flag.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 —image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend —image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 —rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." +msgstr "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn’t exist yet.\n" +"\t\tTo use ‘apply’, always create the resource initially with either ‘apply’ " +"or ‘create —save-config’.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the —prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by —output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." + +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRole." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." + +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\tCreate a namespace with the specified name." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER —username=DOCKER_USER —" +"password=DOCKER_PASSWORD —email=DOCKER_EMAIL’.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent ‘docker " +"push’ and ‘docker pull’ commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." + +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" + +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." + +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" + +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\tCreate a role with single rule." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\tCreate a service account with the specified name." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod’s processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee ‘kubectl delete —help’ for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe ‘top pod’ command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse —force. —force will also allow deletion to proceed if the managing " +"resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t’drain’ waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify “-o json”.\n" +"\n" +"\t\tThe flag —windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." + +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\tMark node as schedulable." + +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\tMark node as unschedulable." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" +msgstr "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew —prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf —current-replicas or —resource-version is specified, it is validated " +"before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"‘kubectl apply -f ’ was run,\n" +"\t\twithout updating any other parts of the object." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy —api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy —www=/my/files —www-prefix=/static/ —api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you ‘curl localhost:8001/api/v1/pods’.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy —api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you ‘curl localhost:8001/custom/api/v1/pods’" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." +msgstr "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If —overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If —resource-version is specified, then updates will use this resource " +"version, otherwise the existing resource-version will be used." + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." +msgstr "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the ‘tar’ binary is present in your container\n" +"\t # image. If ‘tar’ is not present, ‘kubectl cp’ will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret —cert=path/to/tls.cert —key=path/to/" +"tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret —from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret —from-file=ssh-privatekey=~/.ssh/" +"id_rsa —from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret —from-literal=key1=supersecret —" +"from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns —external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs —tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs —tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs —clusterip=“None”" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep —image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns —tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump —output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump —all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump —namespaces default,kube-system —output-" +"directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description=‘my frontend’\n" +"\n" +" # Update pod ‘foo’ with the annotation ‘description’ and the value ‘my " +"frontend running nginx’, overwriting any existing value.\n" +" kubectl annotate —overwrite pods foo description=‘my frontend running " +"nginx’\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods —all description=‘my frontend running nginx’\n" +"\n" +" # Update pod ‘foo’ only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description=‘my frontend running nginx’ —" +"resource-version=1\n" +"\n" +" # Update pod ‘foo’ by removing an annotation named ‘description’ if it " +"exists.\n" +" # Does not require the —overwrite flag.\n" +" kubectl annotate pods foo description-" + +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" Create a LoadBalancer service with the specified name." + +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" Create a clusterIP service with the specified name." + +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" Create a deployment with the specified name." + +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" Create a nodeport service with the specified name." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with —output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the ‘kube-system’ namespace, but you can\n" +" switch to a different namespace with the —namespaces flag, or specify —" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use ‘kubectl cluster-info " +"dump’." + +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." +msgstr "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." + +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." + +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." + +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" + +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "A schedule in the Cron format the job should be run with." + +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." + +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." + +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if —expose is true." + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "ファイル名を指定または標準入力経由でリソースにコンフィグを適用する" + +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "Approve a certificate signing request" + +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" +"Assign your own ClusterIP or set to ‘None’ for a ‘headless’ service (no " +"loadbalancing)." + +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Attach to a running container" + +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "Auto-scale a Deployment, ReplicaSet, or ReplicationController" + +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." +msgstr "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to ‘None’ to create a headless service." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRole this ClusterRoleBinding should reference" + +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "ClusterRole this RoleBinding should reference" + +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" +msgstr "" +"Container name which will have its image upgraded. Only relevant when —image " +"is specified, ignored otherwise. Required when using —image on a multi-" +"container pod" + +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "Convert config files between different API versions" + +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "Copy files and directories to and from containers." + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "Create a ClusterRoleBinding for a particular ClusterRole" + +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "Create a LoadBalancer service." + +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "Create a NodePort service." + +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "Create a RoleBinding for a particular Role or ClusterRole" + +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "Create a TLS secret" + +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "Create a clusterIP service." + +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "Create a configmap from a local file, directory or literal value" + +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "Create a deployment with the specified name." + +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "Create a namespace with the specified name" + +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "Create a pod disruption budget with the specified name." + +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "Create a quota with the specified name." + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "ファイル名を指定または標準入力経由でリソースを作成する" + +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "Create a secret for use with a Docker registry" + +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "Create a secret from a local file, directory or literal value" + +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "Create a secret using specified subcommand" + +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "Create a service account with the specified name" + +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "Create a service using specified subcommand." + +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Create an ExternalName service." + +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "kubeconfigから指定したクラスターを削除する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "kubeconfigから指定したコンテキストを削除する" + +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "Deny a certificate signing request" + +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Deprecated: Gracefully shut down a resource by name or filename" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "1つまたは複数のコンテキストを記述する" + +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" + +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" + +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +#: pkg/kubectl/cmd/clusterinfo.go:51 +#| msgid "Display clusters defined in the kubeconfig" +msgid "Display cluster info" +msgstr "クラスターの情報を表示する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "kubeconfigで定義されたクラスターを表示する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "" +"マージされたkubeconfigの設定または指定されたkubeconfigファイルを表示する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "1つまたは複数のリソースを表示する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "カレントコンテキストを表示する" + +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "リソースの説明を表示する" + +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Drain node in preparation for maintenance" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Dump lots of relevant info for debugging and diagnosis" + +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "Edit a resource on the server" + +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "Email for Docker registry" + +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "Execute a command in a container" + +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" +"Explicit policy for when to pull container images. Required when —image is " +"same as existing image, ignored otherwise." + +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Forward one or more local ports to a pod" + +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Help about any command" + +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." + +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" +msgstr "" +"If non-empty, set the session affinity for the service to this; legal " +"values: ‘None’, ‘ClientIP’" + +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" +"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." + +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" +"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." + +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" +msgstr "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with —filename/-f" + +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "Manage a deployment rollout" + +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "Mark node as schedulable" + +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "Mark node as unschedulable" + +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "Mark the provided resource as paused" + +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "Modify certificate resources." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "kubeconfigファイルを変更する" + +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." + +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." + +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "Output shell completion code for the specified shell (bash or zsh)" + +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" +msgstr "" +"Output the formatted object with the given group version (for ex: " +"‘extensions/v1beta1’).)" + +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Password for Docker registry authentication" + +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Path to PEM encoded public key certificate." + +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Path to private key associated with given certificate." + +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "Perform a rolling update of the given ReplicationController" + +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." +msgstr "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." + +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "Print the client and server version information" + +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "Print the list of flags inherited by all commands" + +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "Print the logs for a container in a pod" + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "Replace a resource by filename or stdin" + +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "Resume a paused resource" + +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "Role this RoleBinding should reference" + +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "Run a particular image on the cluster" + +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "Run a proxy to the Kubernetes API server" + +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "Server location for Docker registry" + +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" + +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "Set specific features on objects" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." + +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "リソースのセレクターを設定する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "kubeconfigにクラスターエントリを設定する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "kubeconfigにコンテキストエントリを設定する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "kubeconfigにユーザーエントリを設定する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "kubeconfigファイル内の変数を個別に設定する" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "kubeconfigにカレントコンテキストを設定する" + +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "Show details of a specific resource or group of resources" + +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "Show the status of the rollout" + +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Synonym for —target-port" + +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" + +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "The image for the container to run." + +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" + +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" +"The key to use to differentiate between two different controllers, default " +"‘deployment’. Only relevant when —image is specified, ignored otherwise" + +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "" +"The minimum number or percentage of available pods this budget requires." +msgstr "" +"The minimum number or percentage of available pods this budget requires." + +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "The name for the newly created object." + +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." + +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." + +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" +"The name of the API generator to use. Currently there is only 1 generator." + +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." +msgstr "" +"The name of the API generator to use. There are 2 generators: ‘service/v1’ " +"and ‘service/v2’. The only difference between them is that service port in " +"v1 is named ‘default’, while it is left unnamed in v2. Default is ‘service/" +"v2’." + +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" +"The name of the generator to use for creating a service. Only used if —" +"expose is true" + +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "The network protocol for the service to be created. Default is ‘TCP’." + +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" + +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" +"The port that this container exposes. If —expose is true, this is also the " +"port used by the service that is created." + +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" +"The resource requirement limits for this container. For example, ‘cpu=200m," +"memory=512Mi’. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." + +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" +"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." + +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to ‘Always’ a deployment is created, if set to ‘OnFailure’ a job is " +"created, if set to ‘Never’, a regular pod is created. For the latter two —" +"replicas must be 1. Default ‘Always’, for CronJobs ` + "`" + `Never` + "`" + `." + +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "The type of secret to create" + +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"‘ClusterIP’." + +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "現在のロールアウトを取り消す" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "kubeconfigファイルから変数を個別に削除する" + +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "Update field(s) of a resource using strategic merge patch" + +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "Update image of a pod template" + +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "Update resource requests/limits on objects with pod templates" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "リソースのアノテーションを更新する" + +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "リソースのラベルを更新する" + +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "Update the taints on one or more nodes" + +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Username for Docker registry authentication" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "" +"View latest last-applied-configuration annotations of a resource/object" + +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "ロールアウトの履歴を表示する" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" +"Where to output the files. If empty or ‘-‘ uses stdout, otherwise creates a " +"directory hierarchy in that directory" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "dummy restart flag)" + +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "external name of service" + +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "kubectl controls the Kubernetes cluster manager" + +#~ msgid "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgid_plural "" +#~ "watch is only supported on individual resources and resource collections " +#~ "- %d resources were found" +#~ msgstr[0] "" +#~ "watchは単一リソース及びリソースコレクションのみサポートしています - %d個の" +#~ "リソースが見つかりました" +#~ msgstr[1] "" +#~ "watchは単一リソース及びリソースコレクションのみサポートしています - %d個の" +#~ "リソースが見つかりました" +`) + +func translationsKubectlJa_jpLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlJa_jpLc_messagesK8sPo, nil +} + +func translationsKubectlJa_jpLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlJa_jpLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ja_JP/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlKo_krLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x11\x00\x00\x00\x1c\x00\x00\x00\xa4\x00\x00\x00\x17\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00\x88\x01\x00\x008\x00\x00\x00\x89\x01\x00\x000\x00\x00\x00\xc2\x01\x00\x000\x00\x00\x00\xf3\x01\x00\x00\x1d\x00\x00\x00$\x02\x00\x00*\x00\x00\x00B\x02\x00\x00A\x00\x00\x00m\x02\x00\x00\x1c\x00\x00\x00\xaf\x02\x00\x00\x17\x00\x00\x00\xcc\x02\x00\x00\"\x00\x00\x00\xe4\x02\x00\x00\"\x00\x00\x00\a\x03\x00\x00\x1f\x00\x00\x00*\x03\x00\x00-\x00\x00\x00J\x03\x00\x00-\x00\x00\x00x\x03\x00\x00/\x00\x00\x00\xa6\x03\x00\x00$\x00\x00\x00\xd6\x03\x00\x00\xc5\x00\x00\x00\xfb\x03\x00\x00\x9f\x01\x00\x00\xc1\x04\x00\x00H\x00\x00\x00a\x06\x00\x00:\x00\x00\x00\xaa\x06\x00\x00:\x00\x00\x00\xe5\x06\x00\x004\x00\x00\x00 \a\x00\x007\x00\x00\x00U\a\x00\x00Q\x00\x00\x00\x8d\a\x00\x00&\x00\x00\x00\xdf\a\x00\x00$\x00\x00\x00\x06\b\x00\x007\x00\x00\x00+\b\x00\x007\x00\x00\x00c\b\x00\x004\x00\x00\x00\x9b\b\x00\x004\x00\x00\x00\xd0\b\x00\x00>\x00\x00\x00\x05\t\x00\x00;\x00\x00\x00D\t\x00\x000\x00\x00\x00\x80\t\x00\x00l\x00\x00\x00\xb1\t\x00\x00\x01\x00\x00\x00\n\x00\x00\x00\v\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\f\x00\x00\x00\x05\x00\x00\x00\r\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00Apply a configuration to a resource by filename or stdin\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Describe one or many contexts\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Displays the current-context\x00Modify kubeconfig files\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Unsets an individual value in a kubeconfig file\x00Update the annotations on a resource\x00watch is only supported on individual resources and resource collections - %d resources were found\x00watch is only supported on individual resources and resource collections - %d resources were found\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2018-04-03 06:05+0900\nLast-Translator: Ian Y. Choi \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.0.6\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=1; plural=0;\nLanguage: ko_KR\n\x00\uad6c\uc131\uc744 \ud30c\uc77c \uc774\ub984 \ub610\ub294 stdin\uc5d0 \uc758\ud55c \uc790\uc6d0\uc5d0 \uc801\uc6a9\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc9c0\uc815\ub41c \ud074\ub7ec\uc2a4\ud130\ub97c \uc0ad\uc81c\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc9c0\uc815\ub41c \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc0ad\uc81c\ud569\ub2c8\ub2e4\x00\ud558\ub098 \ub610\ub294 \uc5ec\ub7ec \ucee8\ud14d\uc2a4\ud2b8\ub97c \uc124\uba85\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0 \uc815\uc758\ub41c \ud074\ub7ec\uc2a4\ud130\ub97c \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00\ubcd1\ud569\ub41c kubeconfig \uc124\uc815 \ub610\ub294 \uc9c0\uc815\ub41c kubeconfig \ud30c\uc77c\uc744 \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00\ud604\uc7ac-\ucee8\ud14d\uc2a4\ud2b8\ub97c \ud45c\uc2dc\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc744 \uc218\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \ud074\ub7ec\uc2a4\ud130 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \ucee8\ud14d\uc2a4\ud2b8 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig\uc5d0\uc11c \uc0ac\uc6a9\uc790 \ud56d\ubaa9\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ub2e8\uc77c\uac12\uc744 \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ud604\uc7ac-\ucee8\ud14d\uc2a4\ud2b8\ub97c \uc124\uc815\ud569\ub2c8\ub2e4\x00kubeconfig \ud30c\uc77c\uc5d0\uc11c \ub2e8\uc77c\uac12 \uc124\uc815\uc744 \ud574\uc81c\ud569\ub2c8\ub2e4\x00\uc790\uc6d0\uc5d0 \ub300\ud55c \uc8fc\uc11d\uc744 \uc5c5\ub370\uc774\ud2b8\ud569\ub2c8\ub2e4\x00watch\ub294 \ub2e8\uc77c \ub9ac\uc18c\uc2a4\uc640 \ub9ac\uc18c\uc2a4 \ubaa8\uc74c\ub9cc\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4 - %d \uac1c \uc790\uc6d0\uc744 \ubc1c\uacac\ud558\uc600\uc2b5\ub2c8\ub2e4\x00") + +func translationsKubectlKo_krLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlKo_krLc_messagesK8sMo, nil +} + +func translationsKubectlKo_krLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlKo_krLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlKo_krLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR ianyrchoi@gmail.com, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2018-04-03 06:05+0900\n" +"Last-Translator: Ian Y. Choi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ko_KR\n" + +# https://github.com/kubernetes/kubernetes/blob/masterpkg/kubectl/cmd/apply.go#L98 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "구성을 파일 이름 또는 stdin에 의한 자원에 적용합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "kubeconfig에서 지정된 클러스터를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +msgid "Delete the specified context from the kubeconfig" +msgstr "kubeconfig에서 지정된 컨텍스트를 삭제합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +msgid "Describe one or many contexts" +msgstr "하나 또는 여러 컨텍스트를 설명합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +msgid "Display clusters defined in the kubeconfig" +msgstr "kubeconfig에 정의된 클러스터를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "병합된 kubeconfig 설정 또는 지정된 kubeconfig 파일을 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +msgid "Displays the current-context" +msgstr "현재-컨텍스트를 표시합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +msgid "Modify kubeconfig files" +msgstr "kubeconfig 파일을 수정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +msgid "Sets a cluster entry in kubeconfig" +msgstr "kubeconfig에서 클러스터 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +msgid "Sets a context entry in kubeconfig" +msgstr "kubeconfig에서 컨텍스트 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +msgid "Sets a user entry in kubeconfig" +msgstr "kubeconfig에서 사용자 항목을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +msgid "Sets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값을 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +msgid "Sets the current-context in a kubeconfig file" +msgstr "kubeconfig 파일에서 현재-컨텍스트를 설정합니다" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "kubeconfig 파일에서 단일값 설정을 해제합니다" + +msgid "Update the annotations on a resource" +msgstr "자원에 대한 주석을 업데이트합니다" + +msgid "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgid_plural "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgstr[0] "" +"watch는 단일 리소스와 리소스 모음만을 지원합니다 - %d 개 자원을 발견하였습" +"니다" +`) + +func translationsKubectlKo_krLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlKo_krLc_messagesK8sPo, nil +} + +func translationsKubectlKo_krLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlKo_krLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/ko_KR/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlTemplatePot = []byte(`# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: EMAIL\n" +"POT-Creation-Date: 2017-03-14 21:32-0700\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the " +"cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-" +"admin --user=user1 --user=user2 --group=group1" +msgstr "" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin " +"ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --" +"user=user2 --group=group1" +msgstr "" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead " +"of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1." +"txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and " +"key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-" +"literal=key2=config2" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a " +"dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-" +"server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-" +"password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx " +"and delete all the other resources that are not in the file and match label " +"app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other " +"configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/" +"ConfigMap" +msgstr "" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and " +"10, no target CPU utilization specified so a default autoscaling policy will " +"be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods " +"between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the " +"latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create " +"them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" + +#: pkg/kubectl/cmd/create_clusterrole.go:34 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform " +"\"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --" +"resource=pods --resource-name=readablepod" +msgstr "" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a Role named \"pod-reader\" that allows user to perform \"get" +"\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create role pod-reader --verb=get --verb=list --verb=watch --" +"resource=pods\n" +"\n" +"\t\t# Create a Role named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create role pod-reader --verb=get --verg=list --verb=watch --" +"resource=pods --resource-name=readablepod" +msgstr "" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3," +"replicationcontrollers=2,resourcequotas=1,secrets=5," +"persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in " +"time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-" +"available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods " +"with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any " +"point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format " +"then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and " +"name specified in \"nginx-controller.yaml\", which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with " +"the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the " +"container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-" +"https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 " +"balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-" +"stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which " +"serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and " +"connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into " +"stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-" +"created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a " +"ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet, and use a " +"grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified " +"config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first " +"container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by " +"default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container " +"from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node " +"name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output " +"format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in " +"JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output " +"format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports " +"5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in " +"\"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required " +"because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":" +"\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", " +"\"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" + +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" + +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | " +"kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod " +"web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named " +"nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static " +"content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-" +"api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/" +"pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" " +"to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a " +"directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents " +"of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port " +"5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables " +"\"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --" +"env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the " +"deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", " +"\"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it " +"if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom " +"arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom " +"arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it " +"out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -" +"wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every " +"5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --" +"restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-" +"user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is " +"replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect " +"'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', " +"overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in " +"frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the " +"image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping " +"the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to " +"frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' " +"or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not " +"use unless you are aware of what the current state is. See https://issues." +"k8s.io/34274." +msgstr "" + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it " +"into format\n" +"\t\tof version specified by --output-version flag. If target version is not " +"specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change to output destination." +msgstr "" + +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" + +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key " +"certificate must be .PEM encoded and match the given private key." +msgstr "" + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal " +"value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename " +"is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" + +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate " +"to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --" +"password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker " +"push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires " +"authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. " +"You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and " +"desired minimum available pods" +msgstr "" + +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" + +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional " +"scopes" +msgstr "" + +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the " +"basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may " +"specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is " +"a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files " +"are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" + +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of " +"pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and " +"creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods " +"deployed within the system as needed." +msgstr "" + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by " +"resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may " +"be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources " +"define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may " +"override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. " +"Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged " +"immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may " +"take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace" +"\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the " +"pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node " +"detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or " +"talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting " +"those pods may result in\n" +"\t\tmultiple processes running on different machines using the same " +"identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are " +"sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the " +"same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those " +"nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted " +"immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if " +"someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their " +"update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by " +"delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful " +"termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of " +"pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few " +"minutes\n" +"\t\tsince pod creation." +msgstr "" + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or " +"pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on " +"the server. " +msgstr "" + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from " +"arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use " +"normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot " +"be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not " +"proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced " +"by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there " +"are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete " +"any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the " +"managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the " +"machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl " +"uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can " +"retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, " +"or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for " +"Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a " +"time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files " +"you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, " +"version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line " +"endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be " +"created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when " +"updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, " +"you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update " +"your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" + +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" + +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not " +"installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by " +"adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions " +"of zsh >= 5.2" +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication " +"controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace " +"as the\n" +"\t\texisting replication controller and overwrite at least one (common) " +"label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, " +"the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or " +"Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the " +"scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is " +"validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds " +"true when the\n" +"\t\tscale is sent to the server." +msgstr "" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to " +"match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though " +"'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/" +"api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tPlease refer to the models in https://htmlpreview.github.io/?https://" +"github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions." +"html to find if a field is mutable." +msgstr "" + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, " +"otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this " +"resource version, otherwise the existing resource-version will be used." +msgstr "" + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it " +"is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, " +"numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or " +"file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use " +"-o option\n" +"\t\tto change output format." +msgstr "" + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in " +"the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific " +"container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace " +"\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/" +"to/tls.key" +msgstr "" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder " +"bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of " +"names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/." +"ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and " +"key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret " +"--from-literal=key2=topsecret" +msgstr "" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-" +"directory=/path/to/cluster-state" +msgstr "" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend'.\n" +" # If the same annotation is set multiple times, only the last value will " +"be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my " +"frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running " +"nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --" +"resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it " +"exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster " +"problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. " +"If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in " +"the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --" +"all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these " +"logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/" +"cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info " +"dump'." +msgstr "" + +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "" +"A comma-delimited set of quota scopes that must all match each object " +"tracked by the quota." +msgstr "" + +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "" +"A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "" +"A label selector to use for this budget. Only equality-based selector " +"requirements are supported." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:104 +msgid "" +"A label selector to use for this service. Only equality-based selector " +"requirements are supported. If empty (the default) infer the selector from " +"the replication controller or replica set.)" +msgstr "" + +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:109 +msgid "" +"Additional external IP address (not managed by Kubernetes) to accept for the " +"service. If this IP is routed to a node, the service can be accessed by this " +"IP in addition to its generated service IP." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "" +"An inline JSON override for the generated object. If this is non-empty, it " +"is used to override the generated object. Requires that the object supply a " +"valid apiVersion field." +msgstr "" + +#: pkg/kubectl/cmd/run.go:137 +msgid "" +"An inline JSON override for the generated service object. If this is non-" +"empty, it is used to override the generated object. Requires that the object " +"supply a valid apiVersion field. Only used if --expose is true." +msgstr "" + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "" + +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:82 +msgid "" +"Assign your own ClusterIP or set to 'None' for a 'headless' service (no " +"loadbalancing)." +msgstr "" + +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "" + +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:113 +msgid "" +"ClusterIP to be assigned to the service. Leave empty to auto-allocate, or " +"set to 'None' to create a headless service." +msgstr "" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "" + +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "" +"Container name which will have its image upgraded. Only relevant when --" +"image is specified, ignored otherwise. Required when using --image on a " +"multi-container pod" +msgstr "" + +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "" + +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "" + +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "" + +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "" + +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "" + +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "" + +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "" + +#: pkg/kubectl/cmd/delete.go:132 +msgid "" +"Delete resources by filenames, stdin, resources and names, or by resources " +"and label selector" +msgstr "" + +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "" + +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "" + +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "" + +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "" + +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "" + +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "" + +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "" + +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "" + +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "" + +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "" + +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "" + +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "" +"Explicit policy for when to pull container images. Required when --image is " +"same as existing image, ignored otherwise." +msgstr "" + +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "" + +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:103 +msgid "" +"IP to assign to the Load Balancer. If empty, an ephemeral IP will be created " +"and used (cloud-provider specific)." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:112 +msgid "" +"If non-empty, set the session affinity for the service to this; legal " +"values: 'None', 'ClientIP'" +msgstr "" + +#: pkg/kubectl/cmd/annotate.go:136 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/label.go:134 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "" +"Image to use for upgrading the replication controller. Must be distinct from " +"the existing image (either new image or new image tag). Can not be used " +"with --filename/-f" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "" + +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "" + +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "" + +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:108 +msgid "" +"Name or number for the port on the container that the service should direct " +"traffic to. Optional." +msgstr "" + +#: pkg/kubectl/cmd/logs.go:113 +msgid "" +"Only return logs after a specific date (RFC3339). Defaults to all logs. Only " +"one of since-time / since may be used." +msgstr "" + +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "" + +#: pkg/kubectl/cmd/convert.go:85 +msgid "" +"Output the formatted object with the given group version (for ex: " +"'extensions/v1beta1').)" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "" + +#: pkg/kubectl/cmd/scale.go:83 +msgid "" +"Precondition for resource version. Requires that the current resource " +"version match this value in order to scale." +msgstr "" + +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "" + +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "" + +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "" + +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "" + +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "" + +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "" + +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "" + +#: pkg/kubectl/cmd/scale.go:71 +msgid "" +"Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "" + +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "" +"Set the last-applied-configuration annotation on a live object to match the " +"contents of a file." +msgstr "" + +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "" + +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "" + +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "" + +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "" + +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:88 +msgid "" +"Take a replication controller, service, deployment or pod and expose it as a " +"new Kubernetes Service" +msgstr "" + +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "" + +#: pkg/kubectl/cmd/run.go:119 +msgid "" +"The image pull policy for the container. If left empty, this value will not " +"be specified by the client and defaulted by the server" +msgstr "" + +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "" +"The key to use to differentiate between two different controllers, default " +"'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "" + +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "" +"The minimum number or percentage of available pods this budget requires." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "" + +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "" +"The name for the newly created object. If not specified, the name of the " +"input resource will be used." +msgstr "" + +#: pkg/kubectl/cmd/run.go:116 +msgid "" +"The name of the API generator to use, see http://kubernetes.io/docs/user-" +"guide/kubectl-conventions/#generators for a list." +msgstr "" + +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "" +"The name of the API generator to use. Currently there is only 1 generator." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:99 +msgid "" +"The name of the API generator to use. There are 2 generators: 'service/v1' " +"and 'service/v2'. The only difference between them is that service port in " +"v1 is named 'default', while it is left unnamed in v2. Default is 'service/" +"v2'." +msgstr "" + +#: pkg/kubectl/cmd/run.go:136 +msgid "" +"The name of the generator to use for creating a service. Only used if --" +"expose is true" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "" + +#: pkg/kubectl/cmd/expose.go:101 +msgid "" +"The port that the service should serve on. Copied from the resource being " +"exposed, if unspecified" +msgstr "" + +#: pkg/kubectl/cmd/run.go:124 +msgid "" +"The port that this container exposes. If --expose is true, this is also the " +"port used by the service that is created." +msgstr "" + +#: pkg/kubectl/cmd/run.go:134 +msgid "" +"The resource requirement limits for this container. For example, 'cpu=200m," +"memory=512Mi'. Note that server side components may assign limits depending " +"on the server configuration, such as limit ranges." +msgstr "" + +#: pkg/kubectl/cmd/run.go:133 +msgid "" +"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." +msgstr "" + +#: pkg/kubectl/cmd/run.go:131 +msgid "" +"The restart policy for this Pod. Legal values [Always, OnFailure, Never]. " +"If set to 'Always' a deployment is created, if set to 'OnFailure' a job is " +"created, if set to 'Never', a regular pod is created. For the latter two --" +"replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "" + +#: pkg/kubectl/cmd/expose.go:102 +msgid "" +"Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is " +"'ClusterIP'." +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "" + +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "" + +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "" + +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "" + +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "" + +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "" + +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "" + +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "" + +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "" +"Where to output the files. If empty or '-' uses stdout, otherwise creates a " +"directory hierarchy in that directory" +msgstr "" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "" + +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "" + +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "" +`) + +func translationsKubectlTemplatePotBytes() ([]byte, error) { + return _translationsKubectlTemplatePot, nil +} + +func translationsKubectlTemplatePot() (*asset, error) { + bytes, err := translationsKubectlTemplatePotBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/template.pot", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlZh_cnLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\xea\x00\x00\x00\x1c\x00\x00\x00l\a\x00\x009\x01\x00\x00\xbc\x0e\x00\x00\x00\x00\x00\x00\xa0\x13\x00\x00\xdc\x00\x00\x00\xa1\x13\x00\x00\xb6\x00\x00\x00~\x14\x00\x00\v\x02\x00\x005\x15\x00\x00\x1f\x01\x00\x00A\x17\x00\x00z\x00\x00\x00a\x18\x00\x00_\x02\x00\x00\xdc\x18\x00\x00|\x01\x00\x00<\x1b\x00\x00\x8f\x01\x00\x00\xb9\x1c\x00\x00k\x01\x00\x00I\x1e\x00\x00>\x01\x00\x00\xb5\x1f\x00\x00\x03\x02\x00\x00\xf4 \x00\x00o\x01\x00\x00\xf8\"\x00\x00H\x05\x00\x00h$\x00\x00g\x02\x00\x00\xb1)\x00\x00\x1b\x02\x00\x00\x19,\x00\x00u\x01\x00\x005.\x00\x00\xa8\x01\x00\x00\xab/\x00\x00\xd4\x01\x00\x00T1\x00\x00\x02\x02\x00\x00)3\x00\x00\xb4\x00\x00\x00,5\x00\x00\xb7\x02\x00\x00\xe15\x00\x00\x92\x03\x00\x00\x998\x00\x00\xbf\x01\x00\x00,<\x00\x00=\x00\x00\x00\xec=\x00\x00;\x00\x00\x00*>\x00\x00\xcd\x02\x00\x00f>\x00\x00<\x00\x00\x004A\x00\x00P\x00\x00\x00qA\x00\x00S\x00\x00\x00\xc2A\x00\x00<\x00\x00\x00\x16B\x00\x00\xac\x01\x00\x00SB\x00\x00\x13\x03\x00\x00\x00D\x00\x00\xea\x01\x00\x00\x14G\x00\x00\xfa\x01\x00\x00\xffH\x00\x00\xda\x01\x00\x00\xfaJ\x00\x00c\x01\x00\x00\xd5L\x00\x00T\x01\x00\x009N\x00\x00\xba\x06\x00\x00\x8eO\x00\x00\xf9\x01\x00\x00IV\x00\x00\xe0\x02\x00\x00CX\x00\x00\x02\x03\x00\x00$[\x00\x00\xfb\x00\x00\x00'^\x00\x00\xa5\x01\x00\x00#_\x00\x00\xb4\x01\x00\x00\xc9`\x00\x00\x18\x00\x00\x00~b\x00\x00<\x00\x00\x00\x97b\x00\x00=\x00\x00\x00\xd4b\x00\x00\xc6\x00\x00\x00\x12c\x00\x00g\x02\x00\x00\xd9c\x00\x00.\x00\x00\x00Af\x00\x001\x03\x00\x00pf\x00\x00g\x00\x00\x00\xa2i\x00\x00Q\x00\x00\x00\nj\x00\x00R\x00\x00\x00\\j\x00\x00\"\x00\x00\x00\xafj\x00\x00X\x02\x00\x00\xd2j\x00\x004\x00\x00\x00+m\x00\x00}\x00\x00\x00`m\x00\x00k\x01\x00\x00\xdem\x00\x00\x81\a\x00\x00Jo\x00\x00f\x01\x00\x00\xccv\x00\x00\x85\x00\x00\x003x\x00\x00\xea\x00\x00\x00\xb9x\x00\x00\xd9\x00\x00\x00\xa4y\x00\x00\n\x05\x00\x00~z\x00\x00\x10\x05\x00\x00\x89\u007f\x00\x00\x1c\x00\x00\x00\x9a\x84\x00\x00\x1e\x00\x00\x00\xb7\x84\x00\x00\x98\x02\x00\x00\u0584\x00\x00\xbc\x01\x00\x00o\x87\x00\x00\x9c\x01\x00\x00,\x89\x00\x00q\x01\x00\x00\u024a\x00\x00\x05\x01\x00\x00;\x8c\x00\x00\xdf\x01\x00\x00A\x8d\x00\x00\x1c\x01\x00\x00!\x8f\x00\x00\xc1\x01\x00\x00>\x90\x00\x00\x1b\x02\x00\x00\x00\x92\x00\x00\xc0\x00\x00\x00\x1c\x94\x00\x00\xd5\x02\x00\x00\u0754\x00\x00\x9d\x00\x00\x00\xb3\x97\x00\x00X\x00\x00\x00Q\x98\x00\x00%\x02\x00\x00\xaa\x98\x00\x00o\x00\x00\x00\u041a\x00\x00u\x00\x00\x00@\x9b\x00\x00\x01\x01\x00\x00\xb6\x9b\x00\x00v\x00\x00\x00\xb8\x9c\x00\x00t\x00\x00\x00/\x9d\x00\x00\xef\x00\x00\x00\xa4\x9d\x00\x00}\x00\x00\x00\x94\x9e\x00\x00j\x00\x00\x00\x12\x9f\x00\x00\xc4\x01\x00\x00}\x9f\x00\x00\xf7\x03\x00\x00B\xa1\x00\x00;\x00\x00\x00:\xa5\x00\x008\x00\x00\x00v\xa5\x00\x001\x00\x00\x00\xaf\xa5\x00\x007\x00\x00\x00\xe1\xa5\x00\x00u\x02\x00\x00\x19\xa6\x00\x00\xb0\x00\x00\x00\x8f\xa8\x00\x00[\x00\x00\x00@\xa9\x00\x00J\x00\x00\x00\x9c\xa9\x00\x00a\x00\x00\x00\xe7\xa9\x00\x00\xbd\x00\x00\x00I\xaa\x00\x009\x00\x00\x00\a\xab\x00\x00\xc5\x00\x00\x00A\xab\x00\x00\xae\x00\x00\x00\a\xac\x00\x00\xd6\x00\x00\x00\xb6\xac\x00\x008\x00\x00\x00\x8d\xad\x00\x00%\x00\x00\x00\u01ad\x00\x00W\x00\x00\x00\xec\xad\x00\x00\x1d\x00\x00\x00D\xae\x00\x00=\x00\x00\x00b\xae\x00\x00u\x00\x00\x00\xa0\xae\x00\x004\x00\x00\x00\x16\xaf\x00\x00-\x00\x00\x00K\xaf\x00\x00\xa3\x00\x00\x00y\xaf\x00\x003\x00\x00\x00\x1d\xb0\x00\x002\x00\x00\x00Q\xb0\x00\x008\x00\x00\x00\x84\xb0\x00\x00\x1e\x00\x00\x00\xbd\xb0\x00\x00\x1a\x00\x00\x00\u0730\x00\x009\x00\x00\x00\xf7\xb0\x00\x00\x13\x00\x00\x001\xb1\x00\x00\x1b\x00\x00\x00E\xb1\x00\x00@\x00\x00\x00a\xb1\x00\x00,\x00\x00\x00\xa2\xb1\x00\x00*\x00\x00\x00\u03f1\x00\x007\x00\x00\x00\xfa\xb1\x00\x00'\x00\x00\x002\xb2\x00\x00&\x00\x00\x00Z\xb2\x00\x00.\x00\x00\x00\x81\xb2\x00\x00=\x00\x00\x00\xb0\xb2\x00\x00*\x00\x00\x00\xee\xb2\x00\x000\x00\x00\x00\x19\xb3\x00\x00,\x00\x00\x00J\xb3\x00\x00\x1f\x00\x00\x00w\xb3\x00\x00]\x00\x00\x00\x97\xb3\x00\x000\x00\x00\x00\xf5\xb3\x00\x000\x00\x00\x00&\xb4\x00\x00\"\x00\x00\x00W\xb4\x00\x00?\x00\x00\x00z\xb4\x00\x00\x1d\x00\x00\x00\xba\xb4\x00\x00,\x00\x00\x00\u0634\x00\x00+\x00\x00\x00\x05\xb5\x00\x00$\x00\x00\x001\xb5\x00\x00\x14\x00\x00\x00V\xb5\x00\x00*\x00\x00\x00k\xb5\x00\x00A\x00\x00\x00\x96\xb5\x00\x00\x1d\x00\x00\x00\u0635\x00\x00\x1c\x00\x00\x00\xf6\xb5\x00\x00\x1a\x00\x00\x00\x13\xb6\x00\x00)\x00\x00\x00.\xb6\x00\x006\x00\x00\x00X\xb6\x00\x00\x1d\x00\x00\x00\x8f\xb6\x00\x00\x19\x00\x00\x00\xad\xb6\x00\x00 \x00\x00\x00\u01f6\x00\x00v\x00\x00\x00\xe8\xb6\x00\x00(\x00\x00\x00_\xb7\x00\x00\x16\x00\x00\x00\x88\xb7\x00\x00p\x00\x00\x00\x9f\xb7\x00\x00`\x00\x00\x00\x10\xb8\x00\x00\x9b\x00\x00\x00q\xb8\x00\x00\x97\x00\x00\x00\r\xb9\x00\x00\xa8\x00\x00\x00\xa5\xb9\x00\x00\x1b\x00\x00\x00N\xba\x00\x00\x18\x00\x00\x00j\xba\x00\x00\x1a\x00\x00\x00\x83\xba\x00\x00$\x00\x00\x00\x9e\xba\x00\x00\x1d\x00\x00\x00\u00fa\x00\x00\x17\x00\x00\x00\xe1\xba\x00\x00a\x00\x00\x00\xf9\xba\x00\x00s\x00\x00\x00[\xbb\x00\x00B\x00\x00\x00\u03fb\x00\x00Y\x00\x00\x00\x12\xbc\x00\x00+\x00\x00\x00l\xbc\x00\x00+\x00\x00\x00\x98\xbc\x00\x006\x00\x00\x00\u013c\x00\x00;\x00\x00\x00\xfb\xbc\x00\x00q\x00\x00\x007\xbd\x00\x00/\x00\x00\x00\xa9\xbd\x00\x001\x00\x00\x00\u067d\x00\x00'\x00\x00\x00\v\xbe\x00\x00'\x00\x00\x003\xbe\x00\x00\x18\x00\x00\x00[\xbe\x00\x00&\x00\x00\x00t\xbe\x00\x00%\x00\x00\x00\x9b\xbe\x00\x00(\x00\x00\x00\xc1\xbe\x00\x00#\x00\x00\x00\xea\xbe\x00\x00K\x00\x00\x00\x0e\xbf\x00\x00 \x00\x00\x00Z\xbf\x00\x00_\x00\x00\x00{\xbf\x00\x00\x1e\x00\x00\x00\u06ff\x00\x00\"\x00\x00\x00\xfa\xbf\x00\x00\"\x00\x00\x00\x1d\xc0\x00\x00\x1f\x00\x00\x00@\xc0\x00\x00-\x00\x00\x00`\xc0\x00\x00-\x00\x00\x00\x8e\xc0\x00\x009\x00\x00\x00\xbc\xc0\x00\x00\x1e\x00\x00\x00\xf6\xc0\x00\x00\x19\x00\x00\x00\x15\xc1\x00\x00c\x00\x00\x00/\xc1\x00\x00#\x00\x00\x00\x93\xc1\x00\x00\x82\x00\x00\x00\xb7\xc1\x00\x00\x94\x00\x00\x00:\xc2\x00\x00H\x00\x00\x00\xcf\xc2\x00\x00&\x00\x00\x00\x18\xc3\x00\x00e\x00\x00\x00?\xc3\x00\x00z\x00\x00\x00\xa5\xc3\x00\x00J\x00\x00\x00 \xc4\x00\x00\xe5\x00\x00\x00k\xc4\x00\x00W\x00\x00\x00Q\xc5\x00\x00E\x00\x00\x00\xa9\xc5\x00\x00a\x00\x00\x00\xef\xc5\x00\x00v\x00\x00\x00Q\xc6\x00\x00\xcb\x00\x00\x00\xc8\xc6\x00\x00\xcf\x00\x00\x00\x94\xc7\x00\x00\x1e\x01\x00\x00d\xc8\x00\x00\x1c\x00\x00\x00\x83\xc9\x00\x00T\x00\x00\x00\xa0\xc9\x00\x00\x17\x00\x00\x00\xf5\xc9\x00\x00/\x00\x00\x00\r\xca\x00\x009\x00\x00\x00=\xca\x00\x00\x1e\x00\x00\x00w\xca\x00\x00=\x00\x00\x00\x96\xca\x00\x00$\x00\x00\x00\xd4\xca\x00\x00\x1f\x00\x00\x00\xf9\xca\x00\x00&\x00\x00\x00\x19\xcb\x00\x00+\x00\x00\x00@\xcb\x00\x00G\x00\x00\x00l\xcb\x00\x00\x14\x00\x00\x00\xb4\xcb\x00\x00r\x00\x00\x00\xc9\xcb\x00\x00\x13\x00\x00\x00<\xcc\x00\x00\x18\x00\x00\x00P\xcc\x00\x00/\x00\x00\x00i\xcc\x00\x00\xa6\x01\x00\x00\x99\xcc\x00\x00\xdd\x00\x00\x00@\xce\x00\x00\xb7\x00\x00\x00\x1e\xcf\x00\x00#\x02\x00\x00\xd6\xcf\x00\x00\"\x01\x00\x00\xfa\xd1\x00\x00\x80\x00\x00\x00\x1d\xd3\x00\x000\x02\x00\x00\x9e\xd3\x00\x00Z\x01\x00\x00\xcf\xd5\x00\x00u\x01\x00\x00*\xd7\x00\x00w\x01\x00\x00\xa0\xd8\x00\x00F\x01\x00\x00\x18\xda\x00\x00\xe6\x01\x00\x00_\xdb\x00\x00u\x01\x00\x00F\xdd\x00\x009\x05\x00\x00\xbc\xde\x00\x00W\x02\x00\x00\xf6\xe3\x00\x00#\x02\x00\x00N\xe6\x00\x00r\x01\x00\x00r\xe8\x00\x00\xc2\x01\x00\x00\xe5\xe9\x00\x00\xdf\x01\x00\x00\xa8\xeb\x00\x00 \x02\x00\x00\x88\xed\x00\x00\x8b\x00\x00\x00\xa9\xef\x00\x00\x95\x02\x00\x005\xf0\x00\x00{\x03\x00\x00\xcb\xf2\x00\x00\xd0\x01\x00\x00G\xf6\x00\x00@\x00\x00\x00\x18\xf8\x00\x00>\x00\x00\x00Y\xf8\x00\x00\xd4\x02\x00\x00\x98\xf8\x00\x008\x00\x00\x00m\xfb\x00\x00H\x00\x00\x00\xa6\xfb\x00\x00<\x00\x00\x00\xef\xfb\x00\x006\x00\x00\x00,\xfc\x00\x00\xbe\x01\x00\x00c\xfc\x00\x00\x13\x03\x00\x00\"\xfe\x00\x00\x02\x02\x00\x006\x01\x01\x00?\x02\x00\x009\x03\x01\x00\xcd\x01\x00\x00y\x05\x01\x00e\x01\x00\x00G\a\x01\x00T\x01\x00\x00\xad\b\x01\x00\xba\x06\x00\x00\x02\n\x01\x00\xf9\x01\x00\x00\xbd\x10\x01\x00\xe0\x02\x00\x00\xb7\x12\x01\x00\x02\x03\x00\x00\x98\x15\x01\x00\xfb\x00\x00\x00\x9b\x18\x01\x00\xaa\x01\x00\x00\x97\x19\x01\x00\x83\x01\x00\x00B\x1b\x01\x00\x1c\x00\x00\x00\xc6\x1c\x01\x00=\x00\x00\x00\xe3\x1c\x01\x00A\x00\x00\x00!\x1d\x01\x00\xc4\x00\x00\x00c\x1d\x01\x00g\x02\x00\x00(\x1e\x01\x00*\x00\x00\x00\x90 \x01\x001\x03\x00\x00\xbb \x01\x00g\x00\x00\x00\xed#\x01\x00h\x00\x00\x00U$\x01\x00R\x00\x00\x00\xbe$\x01\x00\x1e\x00\x00\x00\x11%\x01\x00X\x02\x00\x000%\x01\x00/\x00\x00\x00\x89'\x01\x00}\x00\x00\x00\xb9'\x01\x00k\x01\x00\x007(\x01\x00\x81\a\x00\x00\xa3)\x01\x00f\x01\x00\x00%1\x01\x00\x80\x00\x00\x00\x8c2\x01\x00\xe3\x00\x00\x00\r3\x01\x00\xd4\x00\x00\x00\xf13\x01\x00\x05\x05\x00\x00\xc64\x01\x00\x86\x04\x00\x00\xcc9\x01\x00\x1f\x00\x00\x00S>\x01\x00!\x00\x00\x00s>\x01\x00\x98\x02\x00\x00\x95>\x01\x00\xb6\x01\x00\x00.A\x01\x00\x9c\x01\x00\x00\xe5B\x01\x00q\x01\x00\x00\x82D\x01\x00\x05\x01\x00\x00\xf4E\x01\x00\xdf\x01\x00\x00\xfaF\x01\x00\x1c\x01\x00\x00\xdaH\x01\x00\xc1\x01\x00\x00\xf7I\x01\x00 \x02\x00\x00\xb9K\x01\x00\xc0\x00\x00\x00\xdaM\x01\x00\xe8\x02\x00\x00\x9bN\x01\x00\x94\x00\x00\x00\x84Q\x01\x00_\x00\x00\x00\x19R\x01\x00%\x02\x00\x00yR\x01\x00o\x00\x00\x00\x9fT\x01\x00u\x00\x00\x00\x0fU\x01\x00\x01\x01\x00\x00\x85U\x01\x00v\x00\x00\x00\x87V\x01\x00{\x00\x00\x00\xfeV\x01\x00\x00\x01\x00\x00zW\x01\x00\x80\x00\x00\x00{X\x01\x00q\x00\x00\x00\xfcX\x01\x00\xc2\x01\x00\x00nY\x01\x00\t\x04\x00\x001[\x01\x00B\x00\x00\x00;_\x01\x00?\x00\x00\x00~_\x01\x008\x00\x00\x00\xbe_\x01\x00>\x00\x00\x00\xf7_\x01\x00u\x02\x00\x006`\x01\x00\xb0\x00\x00\x00\xacb\x01\x00[\x00\x00\x00]c\x01\x00J\x00\x00\x00\xb9c\x01\x00a\x00\x00\x00\x04d\x01\x00\xbd\x00\x00\x00fd\x01\x009\x00\x00\x00$e\x01\x00\xc5\x00\x00\x00^e\x01\x00\xae\x00\x00\x00$f\x01\x00\xd6\x00\x00\x00\xd3f\x01\x00=\x00\x00\x00\xaag\x01\x00\x1e\x00\x00\x00\xe8g\x01\x00W\x00\x00\x00\ah\x01\x00&\x00\x00\x00_h\x01\x00W\x00\x00\x00\x86h\x01\x00u\x00\x00\x00\xdeh\x01\x00+\x00\x00\x00Ti\x01\x00$\x00\x00\x00\x80i\x01\x00\xa3\x00\x00\x00\xa5i\x01\x00,\x00\x00\x00Ij\x01\x00X\x00\x00\x00vj\x01\x00>\x00\x00\x00\xcfj\x01\x00\"\x00\x00\x00\x0ek\x01\x00\x1e\x00\x00\x001k\x01\x00B\x00\x00\x00Pk\x01\x00\x17\x00\x00\x00\x93k\x01\x00\x1f\x00\x00\x00\xabk\x01\x00E\x00\x00\x00\xcbk\x01\x00'\x00\x00\x00\x11l\x01\x00%\x00\x00\x009l\x01\x002\x00\x00\x00_l\x01\x00\"\x00\x00\x00\x92l\x01\x00=\x00\x00\x00\xb5l\x01\x000\x00\x00\x00\xf3l\x01\x00B\x00\x00\x00$m\x01\x00.\x00\x00\x00gm\x01\x00+\x00\x00\x00\x96m\x01\x000\x00\x00\x00\xc2m\x01\x00\x1f\x00\x00\x00\xf3m\x01\x00]\x00\x00\x00\x13n\x01\x00*\x00\x00\x00qn\x01\x00,\x00\x00\x00\x9cn\x01\x00\x1e\x00\x00\x00\xc9n\x01\x00?\x00\x00\x00\xe8n\x01\x00\x1e\x00\x00\x00(o\x01\x00-\x00\x00\x00Go\x01\x00,\x00\x00\x00uo\x01\x00$\x00\x00\x00\xa2o\x01\x00\x12\x00\x00\x00\xc7o\x01\x00*\x00\x00\x00\xdao\x01\x00E\x00\x00\x00\x05p\x01\x00\x1f\x00\x00\x00Kp\x01\x00\x16\x00\x00\x00kp\x01\x00\x15\x00\x00\x00\x82p\x01\x00)\x00\x00\x00\x98p\x01\x006\x00\x00\x00\xc2p\x01\x00!\x00\x00\x00\xf9p\x01\x00\x19\x00\x00\x00\x1bq\x01\x00)\x00\x00\x005q\x01\x00v\x00\x00\x00_q\x01\x00(\x00\x00\x00\xd6q\x01\x00\x16\x00\x00\x00\xffq\x01\x00p\x00\x00\x00\x16r\x01\x00`\x00\x00\x00\x87r\x01\x00\x9b\x00\x00\x00\xe8r\x01\x00\x97\x00\x00\x00\x84s\x01\x00\xa8\x00\x00\x00\x1ct\x01\x00#\x00\x00\x00\xc5t\x01\x00\x1b\x00\x00\x00\xe9t\x01\x00\x1d\x00\x00\x00\x05u\x01\x00(\x00\x00\x00#u\x01\x00\x1a\x00\x00\x00Lu\x01\x00\x18\x00\x00\x00gu\x01\x00a\x00\x00\x00\x80u\x01\x00s\x00\x00\x00\xe2u\x01\x00B\x00\x00\x00Vv\x01\x00Y\x00\x00\x00\x99v\x01\x00+\x00\x00\x00\xf3v\x01\x00+\x00\x00\x00\x1fw\x01\x006\x00\x00\x00Kw\x01\x005\x00\x00\x00\x82w\x01\x00q\x00\x00\x00\xb8w\x01\x00(\x00\x00\x00*x\x01\x00!\x00\x00\x00Sx\x01\x00 \x00\x00\x00ux\x01\x00.\x00\x00\x00\x96x\x01\x00\x1e\x00\x00\x00\xc5x\x01\x00$\x00\x00\x00\xe4x\x01\x00'\x00\x00\x00\ty\x01\x00,\x00\x00\x001y\x01\x00#\x00\x00\x00^y\x01\x00\\\x00\x00\x00\x82y\x01\x00'\x00\x00\x00\xdfy\x01\x00_\x00\x00\x00\az\x01\x00\x1c\x00\x00\x00gz\x01\x000\x00\x00\x00\x84z\x01\x003\x00\x00\x00\xb5z\x01\x000\x00\x00\x00\xe9z\x01\x00-\x00\x00\x00\x1a{\x01\x00-\x00\x00\x00H{\x01\x00=\x00\x00\x00v{\x01\x00\x18\x00\x00\x00\xb4{\x01\x00\x19\x00\x00\x00\xcd{\x01\x00p\x00\x00\x00\xe7{\x01\x00\x1f\x00\x00\x00X|\x01\x00o\x00\x00\x00x|\x01\x00x\x00\x00\x00\xe8|\x01\x009\x00\x00\x00a}\x01\x00\x1f\x00\x00\x00\x9b}\x01\x00Z\x00\x00\x00\xbb}\x01\x00v\x00\x00\x00\x16~\x01\x00=\x00\x00\x00\x8d~\x01\x00\xe1\x00\x00\x00\xcb~\x01\x00[\x00\x00\x00\xad\u007f\x01\x00N\x00\x00\x00\t\x80\x01\x00R\x00\x00\x00X\x80\x01\x00v\x00\x00\x00\xab\x80\x01\x00\xcb\x00\x00\x00\"\x81\x01\x00\xaa\x00\x00\x00\xee\x81\x01\x00G\x01\x00\x00\x99\x82\x01\x00\x1a\x00\x00\x00\xe1\x83\x01\x00Y\x00\x00\x00\xfc\x83\x01\x00\x1a\x00\x00\x00V\x84\x01\x003\x00\x00\x00q\x84\x01\x00;\x00\x00\x00\xa5\x84\x01\x00#\x00\x00\x00\xe1\x84\x01\x00=\x00\x00\x00\x05\x85\x01\x00\x1b\x00\x00\x00C\x85\x01\x00\"\x00\x00\x00_\x85\x01\x00+\x00\x00\x00\x82\x85\x01\x00+\x00\x00\x00\xae\x85\x01\x00J\x00\x00\x00\u0685\x01\x00\x15\x00\x00\x00%\x86\x01\x00f\x00\x00\x00;\x86\x01\x00\x13\x00\x00\x00\xa2\x86\x01\x00\x15\x00\x00\x00\xb6\x86\x01\x00(\x00\x00\x00\u0306\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00]\x00\x00\x00[\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00E\x00\x00\x00\xc3\x00\x00\x00\x0e\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\xea\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00n\x00\x00\x00|\x00\x00\x00\x00\x00\x00\x00I\x00\x00\x00\x00\x00\x00\x00\xd7\x00\x00\x00\x97\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x16\x00\x00\x00t\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\xb6\x00\x00\x00\xd6\x00\x00\x00)\x00\x00\x00\x98\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x83\x00\x00\x00\x9b\x00\x00\x00\xe5\x00\x00\x00\x9c\x00\x00\x00\xc4\x00\x00\x00\xd8\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\xcc\x00\x00\x00\xca\x00\x00\x00x\x00\x00\x00\x96\x00\x00\x00\xb9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00B\x00\x00\x00\x92\x00\x00\x00\xac\x00\x00\x00\xe0\x00\x00\x00\xa5\x00\x00\x00\xcf\x00\x00\x00q\x00\x00\x00*\x00\x00\x005\x00\x00\x00\x00\x00\x00\x00\xa4\x00\x00\x00\u007f\x00\x00\x00\x00\x00\x00\x00g\x00\x00\x00\x9f\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00\xdd\x00\x00\x00:\x00\x00\x00\x00\x00\x00\x00\xe8\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x00\x00\x00.\x00\x00\x00U\x00\x00\x00_\x00\x00\x00\xe2\x00\x00\x00 \x00\x00\x00}\x00\x00\x00\x00\x00\x00\x00\xe1\x00\x00\x00\xd2\x00\x00\x00\x87\x00\x00\x00k\x00\x00\x00r\x00\x00\x00f\x00\x00\x00\x05\x00\x00\x00\xc5\x00\x00\x00\"\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00\xc1\x00\x00\x00\x12\x00\x00\x00R\x00\x00\x00F\x00\x00\x00#\x00\x00\x00\xc0\x00\x00\x00\xb4\x00\x00\x00W\x00\x00\x00l\x00\x00\x00\t\x00\x00\x00w\x00\x00\x00\xb7\x00\x00\x00\xbc\x00\x00\x00j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x00\x00\x00D\x00\x00\x00\xbe\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x009\x00\x00\x00\x81\x00\x00\x00\x80\x00\x00\x00%\x00\x00\x00\xdf\x00\x00\x00\x00\x00\x00\x00Z\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x04\x00\x00\x00=\x00\x00\x00H\x00\x00\x00\x93\x00\x00\x00\x8e\x00\x00\x00\xcd\x00\x00\x00>\x00\x00\x00X\x00\x00\x00\xd9\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00&\x00\x00\x003\x00\x00\x00\xcb\x00\x00\x00\v\x00\x00\x004\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\xba\x00\x00\x00\x00\x00\x00\x00\xa8\x00\x00\x00\x9d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x1f\x00\x00\x00(\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00Y\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x00u\x00\x00\x00\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00i\x00\x00\x007\x00\x00\x00\xa2\x00\x00\x00p\x00\x00\x00s\x00\x00\x00^\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x89\x00\x00\x00?\x00\x00\x00\xd1\x00\x00\x00+\x00\x00\x00\x00\x00\x00\x00\x84\x00\x00\x00\x00\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x00\x00\xc7\x00\x00\x00\x94\x00\x00\x00\x06\x00\x00\x00\xa7\x00\x00\x00\xad\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\r\x00\x00\x00z\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x00\x00\xb5\x00\x00\x00h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x00\x00\x00K\x00\x00\x00\x00\x00\x00\x00\xe9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00v\x00\x00\x00\x91\x00\x00\x00<\x00\x00\x00\xae\x00\x00\x00\a\x00\x00\x00\xde\x00\x00\x00\xbf\x00\x00\x00M\x00\x00\x00$\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xda\x00\x00\x00-\x00\x00\x00\x00\x00\x00\x00~\x00\x00\x00\xbd\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\xb2\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Q\x00\x00\x00C\x00\x00\x00A\x00\x00\x00m\x00\x00\x00\x00\x00\x00\x00\xd5\x00\x00\x00\x82\x00\x00\x00\n\x00\x00\x00V\x00\x00\x00\x13\x00\x00\x00P\x00\x00\x00\xd3\x00\x00\x00c\x00\x00\x00\xab\x00\x00\x00\x15\x00\x00\x00\x95\x00\x00\x00J\x00\x00\x001\x00\x00\x00\x19\x00\x00\x00\xb3\x00\x00\x00e\x00\x00\x00\xa1\x00\x00\x00\xe7\x00\x00\x00\x02\x00\x00\x00@\x00\x00\x00\xe3\x00\x00\x00\x8b\x00\x00\x00\x99\x00\x00\x00\b\x00\x00\x00\xaa\x00\x00\x00L\x00\x00\x006\x00\x00\x00/\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x8d\x00\x00\x00\xc9\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\xb1\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\xaf\x00\x00\x00\x00\x00\x00\x00{\x00\x00\x002\x00\x00\x00S\x00\x00\x00\x86\x00\x00\x00a\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\xa9\x00\x00\x00\xa3\x00\x00\x00\x00\x00\x00\x00o\x00\x00\x00\xc6\x00\x00\x00\x8a\x00\x00\x00\x00\n\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # Create a new configmap named my-config based on folder bar\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # Show metrics for all nodes\n\t\t kubectl top node\n\n\t\t # Show metrics for a given node\n\t\t kubectl top node NODE_NAME\x00\n\t\t# Apply the configuration in pod.json to a pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# Apply the JSON passed into stdin to a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune is still in Alpha\n\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, target CPU utilization specified so a default autoscaling policy will be used:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n\t\t# and print to stdout in json format.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# Convert all files under current directory to latest version and create them all.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# Create a new resourcequota named my-quota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# Create a new resourcequota named best-effort\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n\t\t# and require at least one of them being available at any point in time.\n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n\t\t# and require at least half of the pods selected to be available at any point in time.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# Create a pod using the data in pod.json.\n\t\tkubectl create -f ./pod.json\n\n\t\t# Create a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# Delete a pod using the type and name specified in pod.json.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n\t\tkubectl delete pod,service baz foo\n\n\t\t# Delete pods and services with label name=myLabel.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# Delete a pod with minimal delay\n\t\tkubectl delete pod foo --now\n\n\t\t# Force delete a pod on a dead node\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# Delete all pods\n\t\tkubectl delete pods --all\x00\n\t\t# Describe a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# Describe a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# Describe a pod identified by type and name in \"pod.json\"\n\t\tkubectl describe -f pod.json\n\n\t\t# Describe all pods\n\t\tkubectl describe pods\n\n\t\t# Describe pods by label name=myLabel\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n\t\t# get the name of the rc as a prefix in the pod the name).\n\t\tkubectl describe pods frontend\x00\n\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n\t\t$ kubectl drain foo --force\n\n\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet \u6216\u8005 StatefulSet, and use a grace period of 15 minutes.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# Edit the service named 'docker-registry':\n\t\tkubectl edit svc/docker-registry\n\n\t\t# Use an alternative editor\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n\t\tkubectl exec 123456-7890 date\n\n\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# Get output from running pod 123456-7890, using the first container by default\n\t\tkubectl attach 123456-7890\n\n\t\t# Get output from ruby-container from pod 123456-7890\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n\t\t# and sends stdout/stderr from 'bash' back to the client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# Get output from the first pod of a ReplicaSet named nginx\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# Get the documentation of the resource and its fields\n\t\tkubectl explain pods\n\n\t\t# Get the documentation of a specific field of a resource\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# Install bash completion on a Mac using homebrew\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for bash into the current shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# Write bash completion code to a file and source if from .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell completion\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# Load the kubectl completion code for zsh[1] into the current shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# List all pods in ps output format.\n\t\tkubectl get pods\n\n\t\t# List all pods in ps output format with more information (such as node name).\n\t\tkubectl get pods -o wide\n\n\t\t# List a single replication controller with specified NAME in ps output format.\n\t\tkubectl get replicationcontroller web\n\n\t\t# List a single pod in JSON output format.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# Return only the phase value of the specified pod.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# List all replication controllers and services together in ps output format.\n\t\tkubectl get rc,services\n\n\t\t# List one or more resources by their type and names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# List all resources with different types.\n\t\tkubectl get all\x00\n\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod :5000\n\n\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# Mark node \"foo\" as schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# Mark node \"foo\" as unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# Partially update a node using strategic merge patch\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# Update a container's image using a json patch with positional arrays\n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# Print flags inherited by all commands\n\t\tkubectl options\x00\n\t\t# Print the address of the master and cluster services\n\t\tkubectl cluster-info\x00\n\t\t# Print the client and server versions for the current context\n\t\tkubectl version\x00\n\t\t# Print the supported API versions\n\t\tkubectl api-versions\x00\n\t\t# Replace a pod using the data in pod.json.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# Replace a pod based on the JSON passed into stdin.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# Update a single-container pod's image version (tag) to v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# Force replace, delete and then re-create the resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# Return snapshot logs from pod nginx with only one container\n\t\tkubectl logs nginx\n\n\t\t# Return snapshot logs for the pods defined by label app=nginx\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n\t\t# The chosen port for the server will be output to stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale a replicaset named 'foo' to 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale multiple replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale job named 'cron' to 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# Show metrics for all pods in the default namespace\n\t\tkubectl top pod\n\n\t\t# Show metrics for all pods in the given namespace\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# Show metrics for a given pod and its containers\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# Show metrics for the pods defined by label name=myLabel\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\tApply a configuration to a resource by filename or stdin.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\tConvert config files between different API versions. Both YAML\n\t\tand JSON formats are accepted.\n\n\t\tThe command takes filename, directory, or URL as input, and convert it into format\n\t\tof version specified by --output-version flag. If target version is not specified or\n\t\tnot supported, convert to latest version.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change to output destination.\x00\n\t\tCreate a ClusterRole.\x00\n\t\tCreate a ClusterRoleBinding for a particular ClusterRole.\x00\n\t\tCreate a RoleBinding for a particular Role or ClusterRole.\x00\n\t\tCreate a TLS secret from the given public/private key pair.\n\n\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a namespace with the specified name.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\tCreate a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\tCreate a role with single rule.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\tCreate a service account with the specified name.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\tDisplay Resource (CPU/Memory/Storage) usage.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\tDrain node in preparation for maintenance.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\tEdit a resource from the default editor.\n\n\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n\t\taccepts filenames as well as command line arguments, although the files you point to must\n\t\tbe previously saved versions of resources.\n\n\t\tEditing is done with the API version used to fetch the resource.\n\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n\n\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n\n\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n\t\totherwise the default for your operating system will be used.\n\n\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n\t\tthat contains your unapplied changes. The most common error when updating a resource\n\t\tis another editor changing the resource on the server. When this occurs, you will have\n\t\tto apply your changes to the newer version of the resource, or update your temporary\n\t\tsaved copy to include the latest resource version.\x00\n\t\tMark node as schedulable.\x00\n\t\tMark node as unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\tPerform a rolling update of the given ReplicationController.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\tUpdate the taints on one or more nodes.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!Important Note!!!\n\t # Requires that the 'tar' binary is present in your container\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # Create a new TLS secret named tls-secret with the given key pair:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # Create a new namespace named my-namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # Create a new LoadBalancer service named my-lbs\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # Create a new clusterIP service named my-cs\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # Create a new clusterIP service named my-cs (in headless mode)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # Create a new deployment named my-dep that runs the busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # Create a new nodeport service named my-ns\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # Dump current cluster state to stdout\n kubectl cluster-info dump\n\n # Dump current cluster state to /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # Dump all namespaces to stdout\n kubectl cluster-info dump --all-namespaces\n\n # Dump a set of namespaces to /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # Update pod 'foo' by removing an annotation named 'description' if it exists.\n # Does not require the --overwrite flag.\n kubectl annotate pods foo description-\x00\n Create a LoadBalancer service with the specified name.\x00\n Create a clusterIP service with the specified name.\x00\n Create a deployment with the specified name.\x00\n Create a nodeport service with the specified name.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00Apply a configuration to a resource by filename or stdin\x00Approve a certificate signing request\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach to a running container\x00Auto-scale a Deployment, ReplicaSet, or ReplicationController\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRole this ClusterRoleBinding should reference\x00ClusterRole this RoleBinding should reference\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00Convert config files between different API versions\x00Copy files and directories to and from containers.\x00Create a ClusterRoleBinding for a particular ClusterRole\x00Create a LoadBalancer service.\x00Create a NodePort service.\x00Create a RoleBinding for a particular Role or ClusterRole\x00Create a TLS secret\x00Create a clusterIP service.\x00Create a configmap from a local file, directory or literal value\x00Create a deployment with the specified name.\x00Create a namespace with the specified name\x00Create a pod disruption budget with the specified name.\x00Create a quota with the specified name.\x00Create a resource by filename or stdin\x00Create a secret for use with a Docker registry\x00Create a secret from a local file, directory or literal value\x00Create a secret using specified subcommand\x00Create a service account with the specified name\x00Create a service using specified subcommand.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Deny a certificate signing request\x00Deprecated: Gracefully shut down a resource by name or filename\x00Describe one or many contexts\x00Display Resource (CPU/Memory) usage of nodes\x00Display Resource (CPU/Memory) usage of pods\x00Display Resource (CPU/Memory) usage.\x00Display cluster info\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Display one or many resources\x00Displays the current-context\x00Documentation of resources\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00Edit a resource on the server\x00Email for Docker registry\x00Execute a command in a container\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00Manage a deployment rollout\x00Mark node as schedulable\x00Mark node as unschedulable\x00Mark the provided resource as paused\x00Modify certificate resources.\x00Modify kubeconfig files\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00Perform a rolling update of the given ReplicationController\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00Print the client and server version information\x00Print the list of flags inherited by all commands\x00Print the logs for a container in a pod\x00Replace a resource by filename or stdin\x00Resume a paused resource\x00Role this RoleBinding should reference\x00Run a particular image on the cluster\x00Run a proxy to the Kubernetes API server\x00Server location for Docker registry\x00Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job\x00Set specific features on objects\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00Set the selector on a resource\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Show details of a specific resource or group of resources\x00Show the status of the rollout\x00Synonym for --target-port\x00Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service\x00The image for the container to run.\x00The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server\x00The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise\x00The minimum number or percentage of available pods this budget requires.\x00The name for the newly created object.\x00The name for the newly created object. If not specified, the name of the input resource will be used.\x00The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list.\x00The name of the API generator to use. Currently there is only 1 generator.\x00The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.\x00The name of the generator to use for creating a service. Only used if --expose is true\x00The network protocol for the service to be created. Default is 'TCP'.\x00The port that the service should serve on. Copied from the resource being exposed, if unspecified\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00The 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.\x00The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs `Never`.\x00The type of secret to create\x00Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.\x00Undo a previous rollout\x00Unsets an individual value in a kubeconfig file\x00Update field(s) of a resource using strategic merge patch\x00Update image of a pod template\x00Update resource requests/limits on objects with pod templates\x00Update the annotations on a resource\x00Update the labels on a resource\x00Update the taints on one or more nodes\x00Username for Docker registry authentication\x00View latest last-applied-configuration annotations of a resource/object\x00View rollout history\x00Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory\x00dummy restart flag)\x00external name of service\x00kubectl controls the Kubernetes cluster manager\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2017-11-11 19:01+0800\nLast-Translator: zhengjiajin \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.0.4\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=2; plural=(n > 1);\nLanguage: zh\n\x00\n\t\t # \u4f7f\u7528 cluster-admin ClusterRole \u4e3a user1, user2, and group1 \u521b\u5efa\u4e00\u4e2a ClusterRoleBinding\n\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1\x00\n\t\t # \u4f7f\u7528 admin ClusterRole \u4e3a user1, user2, and group1 \u521b\u5efa\u4e00\u4e2a RoleBinding\n\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1\x00\n\t\t # \u901a\u8fc7\u6587\u4ef6\u5939 bar \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-config \u7684 configmap\n\t\t kubectl create configmap my-config --from-file=path/to/bar\n\n\t\t # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-config \u7684 configmap \u5e76\u6307\u5b9a keys \u800c\u4e0d\u662f\u4f7f\u7528\u78c1\u76d8\u4e0a\u6240\u5728\u7684\u6587\u4ef6\u540d\n\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n\n\t\t # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-config \u7684 configmap \u4e14 key1=config1 \u548c key2=config2\n\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2\x00\n\t\t # \u5982\u679c\u4f60\u8fd8\u6ca1\u6709\u4e00\u4e2a .dockercfg \u6587\u4ef6, \u4f60\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a dockercfg \u7684 secret \u76f4\u63a5\u4f7f\u7528:\n\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL\x00\n\t\t # \u663e\u793a\u6240\u6709 nodes \u4e0a\u7684\u6307\u6807\n\t\t kubectl top node\n\n\t\t # \u663e\u793a\u6307\u5b9a node \u4e0a\u7684\u6307\u6807\n\t\t kubectl top node NODE_NAME\x00\n\t\t# \u5c06 pod.json \u4e0a\u7684\u914d\u7f6e\u5e94\u7528\u4e8e pod.\n\t\tkubectl apply -f ./pod.json\n\n\t\t# \u5c06\u4f20\u5165 stdin \u7684 JSON \u5e94\u7528\u5230\u4e00\u4e2a pod.\n\t\tcat pod.json | kubectl apply -f -\n\n\t\t# Note: --prune \u4ecd\u7136\u5728 Alpha\n\t\t# \u5e94\u7528\u5728 manifest.yaml \u4e2d\u5339\u914d\u6807\u7b7e app=nginx \u7684\u8d44\u6e90\u914d\u7f6e\u5e76\u5220\u9664\u6240\u6709\u4e0d\u5728\u8fd9\u4e2a\u6587\u4ef6\u4e2d\u5e76\u5339\u914d\u6807\u7b7eapp=nginx \u7684\u8d44\u6e90\n\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n\n\t\t# \u5e94\u7528 manifest.yaml \u7684\u914d\u7f6e\u5e76\u5220\u9664\u6240\u6709\u4e0d\u5728\u8fd9\u4e2a\u6587\u4ef6\u4e2d\u7684 configmaps.\n\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap\x00\n\t\t# \u81ea\u52a8\u5f39\u6027\u4f38\u7f29 deployment \"foo\", pods \u7684\u6570\u91cf\u5728 2 \u548c 10 \u4e4b\u95f4, \u76ee\u6807 CPU \u6307\u5b9a\u4e3a\u9ed8\u8ba4\u7684\u5f39\u6027\u4f38\u7f29\u7b56\u7565:\n\t\tkubectl autoscale deployment foo --min=2 --max=10\n\n\t\t# \u81ea\u52a8\u5f39\u6027\u4f38\u7f29 replication controller \"foo\", pods \u7684\u6570\u91cf\u5728 1 \u548c 5 \u4e4b\u95f4, \u76ee\u6807 CPU \u5229\u7528\u7387\u4e3a 80%:\n\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80\x00\n\t\t# \u5c06\u2019pod.yaml' \u8f6c\u6362\u4e3a\u6700\u65b0\u7248\u672c\u5e76\u6253\u5370\u5230 stdout.\n\t\tkubectl convert -f pod.yaml\n\n\t\t# \u5c06 \u2018pod.yaml' \u6307\u5b9a\u7684\u8d44\u6e90\u7684\u5b9e\u65f6\u72b6\u6001\u8f6c\u6362\u4e3a\u6700\u65b0\u7248\u672c\n\t\t# \u5e76\u4ee5 json \u683c\u5f0f\u6253\u5370\u5230 stdout.\n\t\tkubectl convert -f pod.yaml --local -o json\n\n\t\t# \u5c06\u5f53\u524d\u76ee\u5f55\u4e0b\u7684\u6240\u4ee5\u6587\u4ef6\u8f6c\u6362\u4e3a\u6700\u65b0\u7248\u672c\u5e76\u521b\u5efa\u5b83\u4eec.\n\t\tkubectl convert -f . | kubectl create -f -\x00\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u4e3a \"pod-reader\" \u7684 ClusterRole, \u5141\u8bb8\u7528\u6237\u5728 pods \u4e0a\u6267\u884c \u201cget\", \"watch\" \u548c \"list\"\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u4e3a \"pod-reader\" ClusterRole, \u5176\u4e2d\u6307\u5b9a\u4e86 ResourceName\n\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod\x00\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u4e3a my-quota \u7684 resourcequota\n\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u4e3a best-effort \u7684 resourcequota\n\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort\x00\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-pdb \u7684 pod disruption budget \u5e76\u5c06\u4f1a\u9009\u62e9\u6240\u6709 app=rails \u6807\u7b7e\u7684 pods\n\t\t# \u5e76\u8981\u6c42\u4ed6\u4eec\u5728\u540c\u4e00\u65f6\u95f4\u4e2d\u6700\u5c11\u6709\u4e00\u4e2a\u53ef\u7528. \n\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n\n\t\t# \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-pdb \u7684 pod disruption budget \u5e76\u5c06\u4f1a\u9009\u62e9\u6240\u6709 app=rails \u6807\u7b7e\u7684 pods\n\t\t# \u5e76\u8981\u6c42\u4ed6\u4eec\u5728\u540c\u4e00\u65f6\u95f4\u4e2d\u6700\u5c11\u6709\u4e00\u534a\u53ef\u7528.\n\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%\x00\n\t\t# \u4f7f\u7528\u5728 pod.json \u7684 \u6570\u636e\u521b\u5efa\u4e00\u4e2a pod.\n\t\tkubectl create -f ./pod.json\n\n\t\t# \u6839\u636e\u4f20\u5165 stdin \u7684 JSON \u521b\u5efa\u4e00\u4e2a pod.\n\t\tcat pod.json | kubectl create -f -\n\n\t\t# \u4f7f\u7528 v1 API \u683c\u5f0f\u5728 JSON \u4e2d\u7f16\u8f91\u5728 docker-registry.yaml \u4e2d\u7684\u6570\u636e\u7136\u540e\u4f7f\u7528\u88ab\u7f16\u8f91\u540e\u7684\u6570\u636e\u521b\u5efa\u8d44\u6e90.\n\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json\x00\n\t\t# \u4e3a\u4e00\u4e2a replicated nginx \u521b\u5efa\u4e00\u4e2a service, \u670d\u52a1\u5728\u7aef\u53e3 80 \u5e76\u8fde\u63a5\u5230 containers \u76848000\u7aef\u53e3.\n\t\tkubectl expose rc nginx --port=80 --target-port=8000\n\n\t\t# \u4f7f\u7528\u5728 \"nginx-controller.yaml\\ \u4e2d\u6307\u5b9a\u7684 type \u548c name \u4e3a\u4e00\u4e2areplication controller \u521b\u5efa\u4e00\u4e2a service, \u670d\u52a1\u5728\u7aef\u53e3 80 \u5e76\u8fde\u63a5\u5230 containers \u76848000\u7aef\u53e3.\n\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n\n\t\t# \u4e3a\u540d\u4e3a valid-pod \u7684 pod \u521b\u5efa\u4e00\u4e2a service, \u670d\u52a1\u5728\u7aef\u53e3 444 \u5e76\u547d\u540d\u4e3a \"frontend\" \n\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n\n\t\t# \u57fa\u4e8e\u4e0a\u9762\u7684 service \u521b\u5efa\u7b2c\u4e8c\u4e2a service, \u66b4\u9732\u5bb9\u5668\u7aef\u53e3 8443 \u5e76\u547d\u540d\u4e3a \"nginx-https\" \u7aef\u53e3\u4e3a 443 \n\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n\n\t\t# \u4e3a\u4e00\u4e2a\u540d\u79f0\u4e3a streaming \u7684\u5e94\u7528\u521b\u5efa\u4e00\u4e2a service \u66b4\u9732\u7aef\u53e3 4100, \u534f\u8bae\u4e3a UDP \u540d\u79f0\u4e3a 'video-stream'.\n\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n\n\t\t# \u4e3a\u4e00\u4e2a\u540d\u79f0\u4e3a nginx \u7684 replica set \u521b\u5efa\u4e00\u4e2a service, \u670d\u52a1\u5728 \u7aef\u53e3 80 \u4e14\u8fde\u63a5\u5230\u5bb9\u5668\u7aef\u53e3 8000.\n\t\tkubectl expose rs nginx --port=80 --target-port=8000\n\n\t\t# \u4e3a\u4e00\u4e2a\u540d\u79f0\u4e3a nginx \u7684 deployment \u521b\u5efa\u4e00\u4e2a service, \u670d\u52a1\u5728\u7aef\u53e3 80 \u4e14 \u8fde\u63a5\u5230 containers \u7684 8000 \u7aef\u53e3.\n\t\tkubectl expose deployment nginx --port=80 --target-port=8000\x00\n\t\t# \u4f7f\u7528 pod.json \u4e2d\u7684\u7c7b\u578b\u548c\u540d\u79f0\u5220\u9664\u4e00\u4e2a pod.\n\t\tkubectl delete -f ./pod.json\n\n\t\t# \u57fa\u4e8e\u91cd\u5b9a\u5411\u5230 stdin \u4e2d\u7684 JSON \u7684\u7c7b\u578b\u548c\u540d\u79f0\u5220\u9664\u4e00\u4e2a pod.\n\t\tcat pod.json | kubectl delete -f -\n\n\t\t# \u5220\u9664\u540d\u4e3a \"baz\" \u548c \"foo\" \u7684 pod \u548c service\n\t\tkubectl delete pod,service baz foo\n\n\t\t# \u5220\u9664\u6807\u7b7e\u4e3a name=myLabel \u7684 pods \u548c services.\n\t\tkubectl delete pods,services -l name=myLabel\n\n\t\t# \u5220\u9664\u6700\u5c0f\u5ef6\u8fdf\u7684 pod\n\t\tkubectl delete pod foo --now\n\n\t\t# \u5f3a\u5236\u5220\u9664\u540d\u4e3a foo \u7684 pod\n\t\tkubectl delete pod foo --grace-period=0 --force\n\n\t\t# \u5220\u9664\u6240\u6709 pods\n\t\tkubectl delete pods --all\x00\n\t\t# \u63cf\u8ff0\u4e00\u4e2a node\n\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n\n\t\t# \u63cf\u8ff0\u4e00\u4e2a pod\n\t\tkubectl describe pods/nginx\n\n\t\t# \u63cf\u8ff0\u4e00\u4e2a\u88ab \"pod.json\" \u4e2d\u7684\u7c7b\u578b\u548c\u540d\u79f0\u6807\u8bc6\u7684 pod\n\t\tkubectl describe -f pod.json\n\n\t\t# \u63cf\u8ff0\u6240\u6709 pods\n\t\tkubectl describe pods\n\n\t\t# \u63cf\u8ff0\u6807\u7b7e\u4e3a name=myLabel \u7684 pods\n\t\tkubectl describe po -l name=myLabel\n\n\t\t# \u63cf\u8ff0\u6240\u6709\u88ab\u540d\u79f0\u4e3a 'frontend' \u7684 replication controller \u7ba1\u7406\u7684 pods(rc-\u521b\u5efa pods\n\t\t# \u5e76\u4f7f\u7528 rc \u7684\u540d\u79f0\u4f5c\u4e3a pod \u7684\u524d\u7f00).\n\t\tkubectl describe pods frontend\x00\n\t\t# \u9a71\u9010\u8282\u70b9 \"foo\", \u5373\u4f7f\u5f88\u591a pods \u6ca1\u6709\u88ab\u4e00\u4e2a\u5728 node \u4e0a\u7684 ReplicationController, ReplicaSet, Job, DaemonSet \u6216\u8005 StatefulSet \u7ba1\u7406.\n\t\t$ kubectl drain foo --force\n\n\t\t# \u540c\u4e0a, \u5982\u679c\u5b58\u5728 pods \u6ca1\u6709\u88ab\u4e00\u4e2a ReplicationController, ReplicaSet, Job, DaemonSet \u6216\u8005 StatefulSet \u7ba1\u7406\u8d85\u8fc7 15 \u5206\u949f\u5219\u9000\u51fa.\n\t\t$ kubectl drain foo --grace-period=900\x00\n\t\t# \u7f16\u8f91\u540d\u4e3a 'docker-registry' \u7684 service:\n\t\tkubectl edit svc/docker-registry\n\n\t\t# \u4f7f\u7528\u4e00\u4e2a\u53ef\u9009\u62e9\u7684\u7f16\u8f91\u5668\n\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n\n\t\t# \u4f7f\u7528 v1 API \u683c\u5f0f\u7684 JSON \u7f16\u8f91\u540d\u4e3a 'myjob' \u7684 job:\n\t\tkubectl edit job.v1.batch/myjob -o json\n\n\t\t# \u5728 YAML \u4e2d\u7f16\u8f91\u540d\u4e3a 'mydeployment' \u7684 deployment \u5e76\u5728\u5b83\u7684\u6ce8\u89e3\u4e2d\u4fdd\u5b58\u4fee\u6539\u540e\u7684\u914d\u7f6e:\n\t\tkubectl edit deployment/mydeployment -o yaml --save-config\x00\n\t\t# \u4ece\u8fd0\u884c\u4e2dpod 123456-7890 \u83b7\u53d6\u6267\u884c 'date' \u7684\u8f93\u51fa, \u9ed8\u8ba4\u4f7f\u7528\u7b2c\u4e00\u4e2a\u5bb9\u5668\n\t\tkubectl exec 123456-7890 date\n\n\t\t# \u4ece pod 123456-7890 \u7684\u5bb9\u5668 ruby-container \u83b7\u53d6\u6267\u884c 'date' \u7684\u8f93\u51fa\n\t\tkubectl exec 123456-7890 -c ruby-container date\n\n\t\t# \u5207\u6362\u5230 terminal \u6a21\u5f0f, \u53d1\u9001 stdin \u5230\u8fd0\u884c\u5728 pod 123456-7890 \u7684\u5bb9\u5668 ruby-container 'bash' \n\t\t# \u5e76\u4ece 'bash' \u53d1\u9001 stdout/stderr \u8fd4\u56de\u5230 client\n\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il\x00\n\t\t# \u4ece\u8fd0\u884c\u4e2dpod 123456-7890 \u83b7\u53d6\u6267\u884c 'date' \u7684\u8f93\u51fa, \u9ed8\u8ba4\u4f7f\u7528\u7b2c\u4e00\u4e2a\u5bb9\u5668\n\t\tkubectl attach 123456-7890\n\n\t\t# \u4ece pod 123456-7890 \u7684\u5bb9\u5668 ruby-container \u83b7\u53d6\u8f93\u51fa\n\t\tkubectl attach 123456-7890 -c ruby-container\n\n\t\t# \u5207\u6362\u5230 terminal \u6a21\u5f0f, \u53d1\u9001 stdin \u5230\u8fd0\u884c\u5728 pod 123456-7890 \u7684\u5bb9\u5668 ruby-container 'bash' \n\t\t# \u5e76\u4ece 'bash' \u53d1\u9001 stdout/stderr \u8fd4\u56de\u5230 client\n\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n\n\t\t# \u4ece\u540d\u79f0\u4e3a nginx \u7684 ReplicaSet \u83b7\u53d6\u7b2c\u4e00\u4e2a pod \u7684\u8f93\u51fa\n\t\tkubectl attach rs/nginx\n\t\t\x00\n\t\t# \u83b7\u53d6\u8d44\u6e90\u53ca\u5176\u5b57\u6bb5\u7684\u6587\u6863\n\t\tkubectl explain pods\n\n\t\t# \u83b7\u53d6\u8d44\u6e90\u6307\u5b9a\u5b57\u6bb5\u7684\u6587\u6863\n\t\tkubectl explain pods.spec.containers\x00\n\t\t# \u5728\u4e00\u4e2a Mac \u4e2d\u4f7f\u7528 homebrew \u5b89\u88c5 bash \u8865\u5168\n\t\tbrew install bash-completion\n\t\tprintf \"\n# Bash \u8865\u5168\u652f\u6301\nsource $(brew --prefix)/etc/bash_completion\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# \u5bfc\u5165 kubectl \u8865\u5168\u4ee3\u7801\u5230\u5f53\u524d shell\n\t\tsource <(kubectl completion bash)\n\n\t\t# \u5199\u5165 bash \u8865\u5168\u4ee3\u7801\u5230\u4e00\u4e2a\u6587\u4ef6\u5e76 source \u5982\u679c\u5b83\u662f .bash_profile\n\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n\t\tprintf \"\n# Kubectl shell \u8865\u5168\nsource '$HOME/.kube/completion.bash.inc'\n\" >> $HOME/.bash_profile\n\t\tsource $HOME/.bash_profile\n\n\t\t# \u4e3a zsh[1] \u5bfc\u5165 kubectl \u8865\u5168\u4ee3\u7801\u5230\u5f53\u524d shell\n\t\tsource <(kubectl completion zsh)\x00\n\t\t# \u4ee5 ps \u8f93\u51fa\u683c\u5f0f\u5217\u51fa\u6240\u6709 pod.\n\t\tkubectl get pods\n\n\t\t# \u4ee5 ps \u8f93\u51fa\u683c\u5f0f\u5217\u51fa\u6240\u6709 pod(\u5982\u8282\u70b9\u540d\u79f0).\n\t\tkubectl get pods -o wide\n\n\t\t# \u83b7\u53d6\u540d\u79f0\u4e3a web \u7684 replicationcontroller.\n\t\tkubectl get replicationcontroller web\n\n\t\t# \u4f7f\u7528 JSON \u683c\u5f0f\u5316\u8f93\u51fa\u663e\u793a\u4e00\u4e2a\u5355\u72ec\u7684 pod.\n\t\tkubectl get -o json pod web-pod-13je7\n\n\t\t# \u663e\u793a\u4e00\u4e2a\u88ab \"pod.yaml\" \u4e2d\u7684 type \u548c name \u6807\u8bc6\u7684 pod \u5e76\u4f7f\u7528 JSON \u683c\u5f0f\u5316\u8f93\u51fa.\n\t\tkubectl get -f pod.yaml -o json\n\n\t\t# \u53ea\u8fd4\u56de\u88ab\u6307\u5b9a pod \u4e2d phase \u7684\u503c.\n\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n\n\t\t# \u663e\u793a\u6240\u6709\u7684 replication controllers \u548c services \u5e76\u683c\u5f0f\u5316\u8f93\u51fa.\n\t\tkubectl get rc,services\n\n\t\t# \u663e\u793a\u4e00\u4e2a\u6216\u8005\u66f4\u591a resources \u901a\u8fc7\u5b83\u4eec\u7684 type \u548c names.\n\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n\n\t\t# \u4f7f\u7528\u4e0d\u540c\u7684 types \u663e\u793a\u6240\u6709 resources.\n\t\tkubectl get all\x00\n\t\t# \u5728\u672c\u5730\u76d1\u542c\u7aef\u53e3 5000 \u548c 6000 , forwarding \u6570\u636e to/from \u5728 pod 5000 \u548c 6000 \u7aef\u53e3\n\t\tkubectl port-forward mypod 5000 6000\n\n\t\t# \u5728\u672c\u5730\u76d1\u542c\u7aef\u53e3 8888 , forwarding \u5230 pod \u7684 5000\u7aef\u53e3\n\t\tkubectl port-forward mypod 8888:5000\n\n\t\t# \u5728\u672c\u5730\u968f\u673a\u76d1\u542c\u4e00\u4e2a\u7aef\u53e3 , forwarding \u5230 pod \u7684 5000\u7aef\u53e3\n\t\tkubectl port-forward mypod :5000\n\n\t\t# \u5728\u672c\u5730\u968f\u673a\u76d1\u542c\u4e00\u4e2a\u7aef\u53e3 , forwarding \u5230 pod \u7684 5000\u7aef\u53e3\n\t\tkubectl port-forward mypod 0:5000\x00\n\t\t# \u6807\u8bb0 node \"foo\" \u4e3a schedulable.\n\t\t$ kubectl uncordon foo\x00\n\t\t# \u6807\u8bb0 node \"foo\" \u4e3a unschedulable.\n\t\tkubectl cordon foo\x00\n\t\t# \u4f7f\u7528 strategic merge patch \u90e8\u5206\u66f4\u65b0\u4e00\u4e2a node\n\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# \u4f7f\u7528 strategic merge patch \u90e8\u5206\u66f4\u65b0\u4e00\u4e2a\u88ab \"node.json\" \u7684 type \u548c name \u6807\u793a \u7684 node.\n\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n\n\t\t# \u66f4\u65b0\u4e00\u4e2a container \u7684 image; spec.containers[*].name \u662f\u5fc5\u987b\u7684 \u56e0\u4e3a\u5b83\u662f\u4e00\u4e2a merge key\n\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n\n\t\t# \u4f7f\u7528\u4e00\u4e2a json patch \u66f4\u65b0\u4e00\u4e2a\u6307\u5b9a\u5750\u6807\u7684 container \u7684 image \n\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'\x00\n\t\t# \u8f93\u51fa\u6240\u6709\u547d\u4ee4\u7ee7\u627f\u7684 flags\n\t\tkubectl options\x00\n\t\t# \u8f93\u51fa master \u548c cluster services \u7684\u5730\u5740\n\t\tkubectl cluster-info\x00\n\t\t# \u8f93\u51fa\u5f53\u524d client \u548c server \u7248\u672c\n\t\tkubectl version\x00\n\t\t# \u8f93\u51fa\u652f\u6301\u7684 API \u7248\u672c\n\t\tkubectl api-versions\x00\n\t\t# \u4f7f\u7528\u5728 pod.json \u4e2d\u7684\u6570\u636e\u66ff\u6362\u4e00\u4e2a pod.\n\t\tkubectl replace -f ./pod.json\n\n\t\t# \u57fa\u4e8e\u88ab\u91cd\u5b9a\u5411\u5230 stdin \u4e2d\u7684 JSON \u66ff\u6362\u4e00\u4e2a pod.\n\t\tcat pod.json | kubectl replace -f -\n\n\t\t# \u66f4\u65b0\u4e00\u4e2a\u5355\u72ec\u5bb9\u5668\u7684 pod \u7684 image \u7248\u672c (tag) \u5230 v4\n\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/\x01:v4/' | kubectl replace -f -\n\n\t\t# \u5f3a\u5236\u66ff\u6362, \u5220\u9664\u7136\u540e\u91cd\u65b0\u521b\u5efa\u8fd9\u4e2a resource\n\t\tkubectl replace --force -f ./pod.json\x00\n\t\t# \u8fd4\u56de\u4ec5\u6709\u4e00\u4e2a\u5bb9\u5668 pod \u540d\u79f0\u4e3a nginx \u7684 snapshot \u65e5\u5fd7\n\t\tkubectl logs nginx\n\n\t\t# \u8fd4\u56de label \u4e3a app=nginx \u7684 pods \u7684 snapshot \u65e5\u5fd7\n\t\tkubectl logs -lapp=nginx\n\n\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n\t\tkubectl logs -p -c ruby web-1\n\n\t\t# Begin streaming the logs of the ruby container in pod web-1\n\t\tkubectl logs -f -c ruby web-1\n\n\t\t# Display only the most recent 20 lines of output in pod nginx\n\t\tkubectl logs --tail=20 nginx\n\n\t\t# Show all logs from pod nginx written in the last hour\n\t\tkubectl logs --since=1h nginx\n\n\t\t# Return snapshot logs from first container of a job named hello\n\t\tkubectl logs job/hello\n\n\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n\t\tkubectl logs deployment/nginx -c nginx-1\x00\n\t\t# \u8fd0\u884c proxy \u5230 kubernetes apiserver \u7684 8011 \u7aef\u53e3\u4e0a, \u670d\u52a1\u9759\u6001\u5185\u5bb9\u8def\u5f84\u4e3a ./local/www/\n\t\tkubectl proxy --port=8011 --www=./local/www/\n\n\t\t# \u5728\u4efb\u610f\u7684\u672c\u5730\u7aef\u53e3\u4e0a\u8fd0\u884c\u4e00\u4e2a proxy \u5230 kubernetes apiserver.\n\t\t# \u4e3a\u8fd9\u4e2a server \u6311\u9009\u7684\u7aef\u53e3\u5c06\u4f1a\u88ab\u8f93\u51fa\u5230 stdout.\n\t\tkubectl proxy --port=0\n\n\t\t# \u8fd0\u884c\u4e00\u4e2a proxy \u5230 kubernetes apiserver, \u4fee\u6539 api prefix \u4e3a k8s-api\n\t\t# \u8fd9\u4f1a\u4f7f e.g. \u8fd9\u4e2a pods \u7684\u6709\u6548 api \u4e3a localhost:8001/k8s-api/v1/pods/\n\t\tkubectl proxy --api-prefix=/k8s-api\x00\n\t\t# Scale \u4e00\u4e2a\u540d\u79f0\u4e3a \u2018foo\u2019 \u7684 replicaset \u670d\u672c\u6570\u4e3a 3.\n\t\tkubectl scale --replicas=3 rs/foo\n\n\t\t# Scale \u6307\u5b9a\u7684 \"foo.yaml\" \u7684 type \u548c name \u6807\u8bc6\u7684 resource \u526f\u672c\u6570\u91cf\u4e3a 3.\n\t\tkubectl scale --replicas=3 -f foo.yaml\n\n\t\t# \u5982\u679c\u540d\u79f0\u4e3a mysql \u7684 deployment \u5f53\u524d\u526f\u672c\u6570\u91cf\u4e3a 2, scale mysql \u5230 3.\n\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n\n\t\t# Scale \u591a\u4e2a replication controllers.\n\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n\n\t\t# Scale \u540d\u79f0\u4e3a \u2019cron\u2019 \u7684 job \u526f\u672c\u6570\u91cf\u4e3a 3.\n\t\tkubectl scale --replicas=3 job/cron\x00\n\t\t# \u8bbe\u7f6e\u4e00\u4e2a\u8d44\u6e90\u7684 last-applied-configuration \u53bb\u5339\u914d\u4e00\u4e2a\u6587\u4ef6\u7684\u5185\u5bb9.\n\t\tkubectl apply set-last-applied -f deploy.yaml\n\n\t\t# Execute set-last-applied against each configuration file in a directory.\n\t\tkubectl apply set-last-applied -f path/\n\n\t\t# \u8bbe\u7f6e\u4e00\u4e2a\u8d44\u6e90\u7684 last-applied-configuration \u53bb\u5339\u914d\u4e00\u4e2a\u6587\u4ef6\u7684\u5185\u5bb9, \u5982\u679c\u4e0d\u5b58\u5728\u5c06\u4f1a\u521b\u5efa\u4e00\u4e2a annotation.\n\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n\t\t\x00\n\t\t# \u663e\u793a default namespace \u4e0b\u6240\u6709 pods \u4e0b\u7684 metrics\n\t\tkubectl top pod\n\n\t\t# \u663e\u793a\u6307\u5b9a namespace \u4e0b\u6240\u6709 pods \u7684 metrics\n\t\tkubectl top pod --namespace=NAMESPACE\n\n\t\t# \u663e\u793a\u6307\u5b9a pod \u548c\u5b83\u7684\u5bb9\u5668\u7684 metrics\n\t\tkubectl top pod POD_NAME --containers\n\n\t\t# \u663e\u793a\u6307\u5b9a label \u4e3a name=myLabel \u7684 pods \u7684 metrics\n\t\tkubectl top pod -l name=myLabel\x00\n\t\t# Shut down foo.\n\t\tkubectl stop replicationcontroller foo\n\n\t\t# Stop pods and services with label name=myLabel.\n\t\tkubectl stop pods,services -l name=myLabel\n\n\t\t# Shut down the service defined in service.json\n\t\tkubectl stop -f service.json\n\n\t\t# Shut down all resources in the path/to/resources directory\n\t\tkubectl stop -f path/to/resources\x00\n\t\t# Start a single instance of nginx.\n\t\tkubectl run nginx --image=nginx\n\n\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n\t\tkubectl run hazelcast --image=hazelcast --port=5701\n\n\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n\n\t\t# Start a replicated instance of nginx.\n\t\tkubectl run nginx --image=nginx --replicas=5\n\n\t\t# Dry run. Print the corresponding API objects without creating them.\n\t\tkubectl run nginx --image=nginx --dry-run\n\n\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n\n\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n\n\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n\t\tkubectl run nginx --image=nginx -- ... \n\n\t\t# Start the nginx container using a different command and custom arguments.\n\t\tkubectl run nginx --image=nginx --command -- ... \n\n\t\t# Start the perl container to compute \u03c0 to 2000 places and print it out.\n\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n\n\t\t# Start the cron job to compute \u03c0 to 2000 places and print it out every 5 minutes.\n\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\x00\n\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n\n\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n\t\tkubectl taint nodes foo dedicated:NoSchedule-\n\n\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n\t\tkubectl taint nodes foo dedicated-\x00\n\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n\t\tkubectl label pods foo unhealthy=true\n\n\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n\t\tkubectl label --overwrite pods foo status=unhealthy\n\n\t\t# Update all pods in the namespace\n\t\tkubectl label pods --all status=unhealthy\n\n\t\t# Update a pod identified by the type and name in \"pod.json\"\n\t\tkubectl label -f pod.json status=unhealthy\n\n\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n\t\tkubectl label pods foo status=unhealthy --resource-version=1\n\n\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n\t\t# Does not require the --overwrite flag.\n\t\tkubectl label pods foo bar-\x00\n\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n\n\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n\n\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n\t\t# name of the replication controller.\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n\n\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n\t\tkubectl rolling-update frontend --image=image:v2\n\n\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback\x00\n\t\t# View the last-applied-configuration annotations by type/name in YAML.\n\t\tkubectl apply view-last-applied deployment/nginx\n\n\t\t# View the last-applied-configuration annotations by file in JSON\n\t\tkubectl apply view-last-applied -f deploy.yaml -o json\x00\n\t\t\u901a\u8fc7\u6587\u4ef6\u540d\u6216\u6807\u51c6\u8f93\u5165\u6d41(stdin)\u5bf9\u8d44\u6e90\u8fdb\u884c\u914d\u7f6e.\n\t\tThis resource will be created if it doesn't exist yet.\n\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274.\x00\n\t\t\u5728\u4e0d\u540c\u7684 API versions \u8f6c\u6362\u914d\u7f6e\u6587\u4ef6. \u63a5\u53d7 YAML\n\t\t\u548c JSON \u683c\u5f0f.\n\n\t\t\u8fd9\u4e2a\u547d\u4ee4\u4ee5 filename, directory, \u6216\u8005 URL \u4f5c\u4e3a\u8f93\u5165, \u5e76\u901a\u8fc7 \u2014output-version flag\n\t\t \u8f6c\u6362\u5230\u6307\u5b9a\u7248\u672c\u7684\u683c\u5f0f. \u5982\u679c\u76ee\u6807\u7248\u672c\u6ca1\u6709\u88ab\u6307\u5b9a\u6216\u8005\n\t\t\u4e0d\u652f\u6301, \u8f6c\u6362\u5230\u6700\u540e\u7684\u7248\u672c.\n\n\t\t\u9ed8\u8ba4\u4ee5 YAML \u683c\u5f0f\u8f93\u51fa\u5230 stdout. \u53ef\u4ee5\u4f7f\u7528 -o option\n\t\t\u4fee\u6539\u76ee\u6807\u8f93\u51fa\u7684\u683c\u5f0f.\x00\n\t\t\u521b\u5efa\u4e00\u4e2a ClusterRole.\x00\n\t\t \u4e3a\u6307\u5b9a\u7684 ClusterRole \u521b\u5efa\u4e00\u4e2a ClusterRoleBinding.\x00\n\t\t\u4e3a\u6307\u5b9a\u7684 Role \u6216\u8005 ClusterRole \u521b\u5efa\u4e00\u4e2a RoleBinding.\x00\n\t\t\u4e3a\u6307\u5b9a\u7684 public/private key pair \u521b\u5efa\u4e00\u4e2a TLS secret.\n\n\t\tpublic/private key pair \u5fc5\u987b\u5728\u4f20\u9012\u524d\u5b58\u5728. public key certificate \u5fc5\u987b\u4ee5 .PEM \u88ab\u7f16\u7801\u4e14\u5339\u914d\u6307\u5b9a\u7684 private key.\x00\n\t\tCreate a configmap based on a file, directory, or specified literal value.\n\n\t\tA single configmap may package one or more key/value pairs.\n\n\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\t\u521b\u5efa\u4e00\u4e2a namespace \u5e76\u6307\u5b9a\u540d\u79f0.\x00\n\t\tCreate a new secret for use with Docker registries.\n\n\t\tDockercfg secrets are used to authenticate against Docker registries.\n\n\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n\n\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n\n That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n\t\tauthenticate to the registry. The email address is optional.\n\n\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n\t\tby creating a dockercfg secret and attaching it to your service account.\x00\n\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods\x00\n\t\t\u901a\u8fc7\u6587\u4ef6\u540d\u6216\u8005\u6807\u51c6\u8f93\u5165\u6d41(stdin)\u521b\u5efa\u4e00\u4e2a\u8d44\u6e90.\n\n\t\tJSON and YAML formats are accepted.\x00\n\t\tCreate a resourcequota with the specified name, hard limits and optional scopes\x00\n\t\t\u521b\u5efa\u5355\u4e00 rule \u7684 role.\x00\n\t\tCreate a secret based on a file, directory, or specified literal value.\n\n\t\tA single secret may package one or more key/value pairs.\n\n\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n\n\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n\t\tsymlinks, devices, pipes, etc).\x00\n\t\t\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 service account.\x00\n\t\tCreate and run a particular image, possibly replicated.\n\n\t\tCreates a deployment or job to manage the created container(s).\x00\n\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n\n\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed.\x00\n\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n\n\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n\t\tresources and names, or resources and label selector.\n\n\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n\t\tthe --force flag.\n\n\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n\t\tterminated, which can leave those processes running until the node detects the deletion and\n\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n\t\tmultiple processes running on different machines using the same identification which may lead\n\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n\t\thas released those resources and causing those pods to be evicted immediately.\n\n\t\tNote that the delete command does NOT do resource version checks, so if someone\n\t\tsubmits an update to a resource right when you submit a delete, their update\n\t\twill be lost along with the rest of the resource.\x00\n\t\tDeprecated: Gracefully shut down a resource by name or filename.\n\n\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n\t\tSee 'kubectl delete --help' for more details.\n\n\t\tAttempts to shut down and delete a resource that supports graceful termination.\n\t\tIf the resource is scalable it will be scaled to 0 before deletion.\x00\n\t\t\u663e\u793a node \u7684\u8d44\u6e90(CPU/Memory/Storage)\u4f7f\u7528.\n\n\t\tThe top-node command allows you to see the resource consumption of nodes.\x00\n\t\t\u663e\u793a pods \u8d44\u6e90(CPU/Memory/Storage)\u4f7f\u7528.\n\n\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n\n\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n\t\tsince pod creation.\x00\n\t\t\u663e\u793a\u8d44\u6e90(CPU/Memory/Storage)\u4f7f\u7528.\n\n\t\tThe top command allows you to see the resource consumption for nodes or pods.\n\n\t\tThis command requires Heapster to be correctly configured and working on the server. \x00\n\t\t\u6e05\u7406\u8282\u70b9\u4e3a\u8282\u70b9\u7ef4\u62a4\u505a\u51c6\u5907.\n\n\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n\t\t'drain' evicts the pods if the APIServer supports eviction\n\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n\t\tto delete the pods.\n\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n\t\twithout --ignore-daemonsets, and regardless it will not delete any\n\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n\t\tpods that are neither mirror pods nor managed by ReplicationController,\n\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n\t\tor more pods is missing.\n\n\t\t'drain' waits for graceful termination. You should not operate on the machine until\n\t\tthe command completes.\n\n\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n\t\twill make the node schedulable again.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)\x00\n\t\t\u4f7f\u7528\u9ed8\u8ba4\u7684\u7f16\u8f91\u5668\u4fee\u6539\u8d44\u6e90.\n\n\t\tedit \u547d\u4ee4\u5141\u8bb8\u4f60\u901a\u8fc7\u547d\u4ee4\u884c\u76f4\u63a5\u4fee\u6539 API \u8d44\u6e90.\n\t\t\u5b83\u4f1a\u6253\u5f00\u4f60\u5728 KUBE_EDITOR \u6216\u8005EDITOR \u73af\u5883\u53d8\u91cf\u4e2d\u5b9a\u4e49\u7684\u7f16\u8f91\u5668\n\t\t\u6216\u8005\u56de\u6eda\u5230 Linux vi \u7f16\u8f91\u5668\u6216\u8005 Windows notepad.\n\t\t\u4f60\u53ef\u4ee5\u4fee\u6539\u591a\u4e2a\u5bf9\u8c61, \u867d\u7136\u6bcf\u6b21\u53ea\u80fd\u4fee\u6539\u4e00\u6b21. \u8fd9\u4e2a\u547d\u4ee4\n\t\t\u540c\u65f6\u4e5f\u63a5\u53d7\u6587\u4ef6\u540d\u4f5c\u4e3a\u547d\u4ee4\u884c\u53c2\u6570, \u5c3d\u7ba1\u8fd9\u4e9b\u6587\u4ef6\u4f60\u6307\u51fa\u5fc5\u987b\u662f\n\t\t\u4f60\u4e4b\u524d\u4fdd\u5b58\u7684\u8d44\u6e90\u7248\u672c.\n\n\t\tEditing \u662f\u901a\u8fc7\u7528\u4e8e\u83b7\u53d6\u8d44\u6e90\u7684API\u7248\u672c\u5b8c\u6210\u7684.\n\t\t\u4e3a\u4e86\u80fd\u901a\u8fc7\u6307\u5b9a\u7684 API \u7248\u672c\u4fee\u6539, \u8bf7\u5b8c\u5168\u9650\u5b9a resource, version \u548c group.\n\n\t\t\u9ed8\u8ba4\u662f YAML \u683c\u5f0f. \u60f3\u5728 JSON \u4e2d\u4fee\u6539, \u6307\u5b9a \"-o json\".\n\n\t\t--windows-line-endings \u547d\u4ee4\u884c\u53c2\u6570\u53ef\u4ee5\u7528\u6765\u5f3a\u5236\u4f7f\u7528 Windows line endings,\n\t\t\u5426\u5219\u4f1a\u4f7f\u7528\u4f60\u64cd\u4f5c\u7cfb\u7edf\u7684\u9ed8\u8ba4\u503c.\n\n\t\t\u5982\u679c\u66f4\u65b0\u65f6\u53d1\u751f\u9519\u8bef\uff0c\u5c06\u5728\u78c1\u76d8\u4e0a\u521b\u5efa\u4e00\u4e2a\u4e34\u65f6\u6587\u4ef6\n\t\t\u91cc\u9762\u5305\u542b\u60a8\u672a\u5e94\u7528\u7684\u66f4\u6539. \u66f4\u65b0\u8d44\u6e90\u65f6\u6700\u5e38\u89c1\u7684\u9519\u8bef\n\t\t\u662f\u53e6\u4e00\u4e2a\u7f16\u8f91\u5668\u4e5f\u5728\u670d\u52a1\u5668\u4e2d\u4fee\u6539\u8fd9\u4e2a\u8d44\u6e90. \u5f53\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6, \u4f60\u5c06\n\t\t\u9700\u8981\u5e94\u7528\u4f60\u7684\u4fee\u6539\u5230\u8d44\u6e90\u7684\u6700\u65b0\u7248\u672c, \u6216\u8005\u66f4\u65b0\u4f60\u88ab\u4fdd\u5b58\u7684\u4e34\u65f6\u6587\u4ef6\n\t\t\u590d\u5236\u5b83\u5e76\u4f7f\u7528\u6700\u65b0\u7684\u7248\u672c.\x00\n\t\t\u6807\u8bb0 node \u4e3a schedulable.\x00\n\t\t\u6807\u8bb0 node \u4e3a unschedulable.\x00\n\t\tOutput shell completion code for the specified shell (bash or zsh).\n\t\tThe shell code must be evaluated to provide interactive\n\t\tcompletion of kubectl commands. This can be done by sourcing it from\n\t\tthe .bash_profile.\n\n\t\tNote: this requires the bash-completion framework, which is not installed\n\t\tby default on Mac. This can be installed by using homebrew:\n\n\t\t $ brew install bash-completion\n\n\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n\t\tfollowing line to the .bash_profile\n\n\t\t $ source $(brew --prefix)/etc/bash_completion\n\n\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2\x00\n\t\t\u5b8c\u6210\u6307\u5b9a\u7684 ReplicationController \u7684\u6eda\u52a8\u5347\u7ea7.\n\n\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n\n\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)\x00\n\t\tReplace a resource by filename or stdin.\n\n\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n\t\tcomplete resource spec must be provided. This can be obtained by\n\n\t\t $ kubectl get TYPE NAME -o yaml\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n\n\t\tScale also allows users to specify one or more preconditions for the scale action.\n\n\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n\t\tscale is sent to the server.\x00\n\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n\t\twithout updating any other parts of the object.\x00\n\t\tTo proxy all of the kubernetes api and nothing else, use:\n\n\t\t $ kubectl proxy --api-prefix=/\n\n\t\tTo proxy only part of the kubernetes api and also some static files:\n\n\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n\n\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n\n\t\tTo proxy the entire kubernetes api at a different root, use:\n\n\t\t $ kubectl proxy --api-prefix=/custom/\n\n\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'\x00\n\t\tUpdate field(s) of a resource using strategic merge patch\n\n\t\tJSON and YAML formats are accepted.\n\n\t\tPlease refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.\x00\n\t\tUpdate the labels on a resource.\n\n\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.\x00\n\t\t\u66f4\u65b0\u4e00\u4e2a\u6216\u8005\u591a\u4e2a node \u4e0a\u7684 taints.\n\n\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n\t\t* Currently taint can only apply to node.\x00\n\t\tView the latest last-applied-configuration annotations by type/name or file.\n\n\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n\t\tto change output format.\x00\n\t # !!!\u6ce8\u610f!!!\n\t # \u8981\u6c42\u5bb9\u5668\u4e2d\u6709 'tar' \u547d\u4ee4\n\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n\n\t # \u590d\u5236\u672c\u5730\u76ee\u5f55 /tmp/foo_dir \u5230 default namespace \u4e0b\u7684\u8fdc\u7a0b pod \u7684 /tmp/bar_dir \u8def\u5f84 \n\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n\n # \u590d\u5236 /tmp/foo local \u672c\u5730\u6587\u4ef6\u5230\u6307\u5b9a\u8fdc\u7a0b pod \u7684\u6307\u5b9a\u5bb9\u5668\u7684 /tmp/bar \u8def\u5f84\n\t\tkubectl cp /tmp/foo :/tmp/bar -c \n\n\t\t# \u590d\u5236 /tmp/foo \u672c\u5730\u6587\u4ef6\u5230\u5728 namespace \u4e0b\u7684\u67d0\u4e2a pod \u7684 /tmp/bar \u8def\u5f84\n\t\tkubectl cp /tmp/foo /:/tmp/bar\n\n\t\t# \u4ece\u4e00\u4e2a\u8fdc\u7a0b\u7684 pod \u7684 /tmp/foo \u8def\u5f84\u590d\u5236\u5230\u672c\u5730 /tmp/bar \u8def\u5f84\n\t\tkubectl cp /:/tmp/foo /tmp/bar\x00\n\t # \u4f7f\u7528\u63d0\u4f9b\u7684 key pair \u540d\u79f0\u4e3atls-secret \u7684 secret:\n\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key\x00\n\t # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-namespace \u7684 namespace\n\t kubectl create namespace my-namespace\x00\n\t # Create a new secret named my-secret with keys for each file in folder bar\n\t kubectl create secret generic my-secret --from-file=path/to/bar\n\n\t # Create a new secret named my-secret with specified keys instead of names on disk\n\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n\n\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret\x00\n\t # Create a new service account named my-service-account\n\t kubectl create serviceaccount my-service-account\x00\n\t# Create a new ExternalName service named my-ns \n\tkubectl create service externalname my-ns --external-name bar.com\x00\n\tCreate an ExternalName service with the specified name.\n\n\tExternalName service references to an external DNS address instead of\n\tonly pods, which will allow application authors to reference services\n\tthat exist off platform, on other clusters, or locally.\x00\n\tHelp provides help for any command in the application.\n\tSimply type kubectl help [path to command] for full details.\x00\n # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-lbs \u7684 LoadBalancer service\n kubectl create service loadbalancer my-lbs --tcp=5678:8080\x00\n # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-cs \u7684 clusterIP service\n kubectl create service clusterip my-cs --tcp=5678:8080\n\n # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-cs \u7684 clusterIP service (\u5728 headless \u6a21\u5f0f)\n kubectl create service clusterip my-cs --clusterip=\"None\"\x00\n # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-dep \u7684 deployment \u5e76\u8fd0\u884c busybox image.\n kubectl create deployment my-dep --image=busybox\x00\n # \u521b\u5efa\u4e00\u4e2a\u540d\u79f0\u4e3a my-ns \u7684 nodeport service\n kubectl create service nodeport my-ns --tcp=5678:8080\x00\n # \u5bfc\u51fa\u5f53\u524d\u7684\u96c6\u7fa4\u72b6\u6001\u4fe1\u606f\u5230 stdout\n kubectl cluster-info dump\n\n # \u5bfc\u51fa\u5f53\u524d\u7684\u96c6\u7fa4\u72b6\u6001 /path/to/cluster-state\n kubectl cluster-info dump --output-directory=/path/to/cluster-state\n\n # \u5bfc\u51fa\u6240\u6709\u5206\u533a\u5230 stdout\n kubectl cluster-info dump --all-namespaces\n\n # \u5bfc\u51fa\u4e00\u7ec4\u5206\u533a\u5230 /path/to/cluster-state\n kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state\x00\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n # If the same annotation is set multiple times, only the last value will be applied\n kubectl annotate pods foo description='my frontend'\n\n # Update a pod identified by type and name in \"pod.json\"\n kubectl annotate -f pod.json description='my frontend'\n\n # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n kubectl annotate --overwrite pods foo description='my frontend running nginx'\n\n # Update all pods in the namespace\n kubectl annotate pods --all description='my frontend running nginx'\n\n # Update pod 'foo' only if the resource is unchanged from version 1.\n kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n\n # \u66f4\u65b0\u540d\u79f0\u4e3a 'foo' \u7684 pod, \u5220\u9664\u4e00\u4e2a\u540d\u79f0\u4e3a 'description' \u7684 annotation \u5982\u679c\u5b83\u5b58\u5728. \n # \u4e0d\u8981\u6c42\u4f7f\u7528 --overwrite flag.\n kubectl annotate pods foo description-\x00\n \u4f7f\u7528\u4e00\u4e2a\u6307\u5b9a\u7684\u540d\u79f0\u521b\u5efa\u4e00\u4e2a LoadBalancer service.\x00\n \u4f7f\u7528\u4e00\u4e2a\u6307\u5b9a\u7684\u540d\u79f0\u521b\u5efa\u4e00\u4e2a clusterIP service.\x00\n \u4f7f\u7528\u4e00\u4e2a\u6307\u5b9a\u7684\u540d\u79f0\u521b\u5efa\u4e00\u4e2a deployment.\x00\n \u4f7f\u7528\u4e00\u4e2a\u6307\u5b9a\u7684\u540d\u79f0\u521b\u5efa\u4e00\u4e2a nodeport service.\x00\n Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n\n The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n based on namespace and pod name.\x00\n Display addresses of the master and services with label kubernetes.io/cluster-service=true\n To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\x00A comma-delimited set of quota scopes that must all match each object tracked by the quota.\x00A comma-delimited set of resource=quantity pairs that define a hard limit.\x00A label selector to use for this budget. Only equality-based selector requirements are supported.\x00A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)\x00A schedule in the Cron format the job should be run with.\x00Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.\x00An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.\x00An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.\x00\u901a\u8fc7\u6587\u4ef6\u540d\u6216\u6807\u51c6\u8f93\u5165\u6d41(stdin)\u5bf9\u8d44\u6e90\u8fdb\u884c\u914d\u7f6e\x00\u540c\u610f\u4e00\u4e2a\u81ea\u7b7e\u8bc1\u4e66\u8bf7\u6c42\x00Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing).\x00Attach \u5230\u4e00\u4e2a\u8fd0\u884c\u4e2d\u7684 container\x00\u81ea\u52a8\u8c03\u6574\u4e00\u4e2a Deployment, ReplicaSet, \u6216\u8005 ReplicationController \u7684\u526f\u672c\u6570\u91cf\x00ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service.\x00ClusterRoleBinding \u5e94\u8be5\u6307\u5b9a ClusterRole\x00RoleBinding \u5e94\u8be5\u6307\u5b9a ClusterRole\x00Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod\x00\u5728\u4e0d\u540c\u7684 API versions \u8f6c\u6362\u914d\u7f6e\u6587\u4ef6\x00\u590d\u5236 files \u548c directories \u5230 containers \u548c\u4ece\u5bb9\u5668\u4e2d\u590d\u5236 files \u548c directories.\x00\u4e3a\u4e00\u4e2a\u6307\u5b9a\u7684 ClusterRole \u521b\u5efa\u4e00\u4e2a ClusterRoleBinding\x00\u521b\u5efa\u4e00\u4e2a LoadBalancer service.\x00\u521b\u5efa\u4e00\u4e2a NodePort service.\x00\u4e3a\u4e00\u4e2a\u6307\u5b9a\u7684 Role \u6216\u8005 ClusterRole\u521b\u5efa\u4e00\u4e2a RoleBinding\x00\u521b\u5efa\u4e00\u4e2a TLS secret\x00\u521b\u5efa\u4e00\u4e2a clusterIP service.\x00\u4ece\u672c\u5730 file, directory \u6216\u8005 literal value \u521b\u5efa\u4e00\u4e2a configmap\x00\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 deployment.\x00\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 namespace\x00\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 pod disruption budget.\x00\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 quota.\x00\u901a\u8fc7\u6587\u4ef6\u540d\u6216\u8005\u6807\u51c6\u8f93\u5165\u6d41(stdin)\u521b\u5efa\u4e00\u4e2a\u8d44\u6e90\x00\u521b\u5efa\u4e00\u4e2a\u7ed9 Docker registry \u4f7f\u7528\u7684 secret\x00\u4ece\u672c\u5730 file, directory \u6216\u8005 literal value \u521b\u5efa\u4e00\u4e2a secret\x00\u4f7f\u7528\u6307\u5b9a\u7684 subcommand \u521b\u5efa\u4e00\u4e2a secret\x00\u521b\u5efa\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684 service account\x00\u4f7f\u7528\u6307\u5b9a\u7684 subcommand \u521b\u5efa\u4e00\u4e2a service.\x00Create an ExternalName service.\x00Delete resources by filenames, stdin, resources and names, or by resources and label selector\x00\u5220\u9664 kubeconfig \u6587\u4ef6\u4e2d\u6307\u5b9a\u7684\u96c6\u7fa4\x00\u5220\u9664 kubeconfig \u6587\u4ef6\u4e2d\u6307\u5b9a\u7684 context\x00\u62d2\u7edd\u4e00\u4e2a\u81ea\u7b7e\u8bc1\u4e66\u8bf7\u6c42\x00Deprecated: Gracefully shut down a resource by name or filename\x00\u63cf\u8ff0\u4e00\u4e2a\u6216\u591a\u4e2a contexts\x00\u663e\u793a nodes \u7684 Resource (CPU/Memory) \u4f7f\u7528\x00\u663e\u793a pods \u7684 Resource (CPU/Memory) \u4f7f\u7528\x00\u663e\u793a Resource (CPU/Memory) \u4f7f\u7528.\x00\u663e\u793a\u96c6\u7fa4\u4fe1\u606f\x00\u663e\u793a kubeconfig \u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u96c6\u7fa4\x00\u663e\u793a\u5408\u5e76\u7684 kubeconfig \u914d\u7f6e\u6216\u4e00\u4e2a\u6307\u5b9a\u7684 kubeconfig \u6587\u4ef6\x00\u663e\u793a\u4e00\u4e2a\u6216\u66f4\u591a resources\x00\u663e\u793a current_context\x00\u67e5\u770b\u8d44\u6e90\u7684\u6587\u6863\x00Drain node in preparation for maintenance\x00Dump lots of relevant info for debugging and diagnosis\x00\u5728\u670d\u52a1\u5668\u4e0a\u7f16\u8f91\u4e00\u4e2a\u8d44\u6e90\x00Email for Docker registry\x00\u5728\u4e00\u4e2a container \u4e2d\u6267\u884c\u4e00\u4e2a\u547d\u4ee4\x00Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.\x00Forward one or more local ports to a pod\x00Help about any command\x00IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).\x00If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'\x00If 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.\x00If 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.\x00Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f\x00\u7ba1\u7406\u4e00\u4e2a deployment \u7684 rollout\x00\u6807\u8bb0 node \u4e3a schedulable\x00\u6807\u8bb0 node \u4e3a unschedulable\x00\u6807\u8bb0\u63d0\u4f9b\u7684 resource \u4e3a\u4e2d\u6b62\u72b6\u6001\x00\u4fee\u6539 certificate \u8d44\u6e90.\x00\u4fee\u6539 kubeconfig \u6587\u4ef6\x00Name or number for the port on the container that the service should direct traffic to. Optional.\x00Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.\x00Output shell completion code for the specified shell (bash or zsh)\x00Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)\x00Password for Docker registry authentication\x00Path to PEM encoded public key certificate.\x00Path to private key associated with given certificate.\x00\u5b8c\u6210\u6307\u5b9a\u7684 ReplicationController \u7684\u6eda\u52a8\u5347\u7ea7\x00Precondition for resource version. Requires that the current resource version match this value in order to scale.\x00\u8f93\u51fa client \u548c server \u7684\u7248\u672c\u4fe1\u606f\x00\u8f93\u51fa\u6240\u6709\u547d\u4ee4\u7684\u5c42\u7ea7\u5173\u7cfb\x00\u8f93\u51fa\u5bb9\u5668\u5728 pod \u4e2d\u7684\u65e5\u5fd7\x00\u901a\u8fc7 filename \u6216\u8005 stdin\u66ff\u6362\u4e00\u4e2a\u8d44\u6e90\x00\u7ee7\u7eed\u4e00\u4e2a\u505c\u6b62\u7684 resource\x00RoleBinding \u7684 Role \u5e94\u8be5\u88ab\u5f15\u7528\x00\u5728\u96c6\u7fa4\u4e2d\u8fd0\u884c\u4e00\u4e2a\u6307\u5b9a\u7684\u955c\u50cf\x00\u8fd0\u884c\u4e00\u4e2a proxy \u5230 Kubernetes API server\x00Server location for Docker registry\x00\u4e3a Deployment, ReplicaSet, Replication Controller \u6216\u8005 Job \u8bbe\u7f6e\u4e00\u4e2a\u65b0\u7684\u526f\u672c\u6570\u91cf\x00\u4e3a objects \u8bbe\u7f6e\u4e00\u4e2a\u6307\u5b9a\u7684\u7279\u5f81\x00Set the last-applied-configuration annotation on a live object to match the contents of a file.\x00\u8bbe\u7f6e resource \u7684 selector\x00\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u4e00\u4e2a\u96c6\u7fa4\u6761\u76ee\x00\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u4e00\u4e2a context \u6761\u76ee\x00\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u4e00\u4e2a\u7528\u6237\u6761\u76ee\x00\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u4e00\u4e2a\u5355\u4e2a\u503c\x00\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u5f53\u524d\u4e0a\u4e0b\u6587\x00\u663e\u793a\u4e00\u4e2a\u6307\u5b9a resource \u6216\u8005 group \u7684 resources \u8be6\u60c5\x00\u663e\u793a rollout \u7684\u72b6\u6001\x00Synonym for --target-port\x00\u4f7f\u7528 replication controller, service, deployment \u6216\u8005 pod \u5e76\u66b4\u9732\u5b83\u4f5c\u4e3a\u4e00\u4e2a \u65b0\u7684 Kubernetes Service\x00\u6307\u5b9a\u5bb9\u5668\u8981\u8fd0\u884c\u7684\u955c\u50cf.\x00\u5bb9\u5668\u7684\u955c\u50cf\u62c9\u53d6\u7b56\u7565. \u5982\u679c\u4e3a\u7a7a, \u8fd9\u4e2a\u503c\u5c06\u4e0d\u4f1a \u88ab client \u6307\u5b9a\u4e14\u4f7f\u7528 server \u7aef\u7684\u9ed8\u8ba4\u503c\x00\u8fd9\u4e2a key \u4f7f\u7528\u6709\u533a\u522b\u5728\u4e24\u4e2a\u4e0d\u540c\u7684 controllers, \u9ed8\u8ba4 'deployment'. \u53ea\u6709\u5f53 --image \u6307\u5b9a\u503c, \u5426\u5219\u5ffd\u7565\x00\u6700\u5c0f\u6570\u91cf\u767e\u5206\u6bd4\u53ef\u7528\u7684 pods \u4f5c\u4e3a budget \u8981\u6c42.\x00\u540d\u79f0\u4e3a\u6700\u65b0\u521b\u5efa\u7684\u5bf9\u8c61.\x00\u540d\u79f0\u4e3a\u6700\u65b0\u521b\u5efa\u7684\u5bf9\u8c61. \u5982\u679c\u6ca1\u6709\u6307\u5b9a, \u8f93\u5165\u8d44\u6e90\u7684 \u540d\u79f0\u5373\u5c06\u88ab\u4f7f\u7528.\x00\u4f7f\u7528 API generator \u7684\u540d\u5b57, \u5728 http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators \u67e5\u770b\u5217\u8868.\x00\u4f7f\u7528 API generator \u7684\u540d\u5b57. \u76ee\u524d\u53ea\u6709 1 \u4e2a generator.\x00\u4f7f\u7528 generator \u7684\u540d\u79f0. \u8fd9\u91cc\u6709 2 \u4e2a generators: 'service/v1' \u548c 'service/v2'. \u4e3a\u4e00\u4e2a\u4e0d\u540c\u5730\u65b9\u662f\u670d\u52a1\u7aef\u53e3\u5728 v1 \u7684\u60c5\u51b5\u4e0b\u53eb 'default', \u5982\u679c\u5728 v2 \u4e2d\u6ca1\u6709\u6307\u5b9a\u540d\u79f0. \u9ed8\u8ba4\u7684\u540d\u79f0\u662f 'service/v2'.\x00\u4f7f\u7528 gnerator \u7684\u540d\u79f0\u521b\u5efa\u4e00\u4e2a service. \u53ea\u6709\u5728 --expose \u4e3a true \u7684\u65f6\u5019\u4f7f\u7528\x00\u521b\u5efa service \u7684\u65f6\u5019\u4f34\u968f\u7740\u4e00\u4e2a\u7f51\u7edc\u534f\u8bae\u88ab\u521b\u5efa. \u9ed8\u8ba4\u662f 'TCP'.\x00\u670d\u52a1\u7684\u7aef\u53e3\u5e94\u8be5\u88ab\u6307\u5b9a. \u5982\u679c\u6ca1\u6709\u6307\u5b9a, \u4ece\u88ab\u521b\u5efa\u7684\u8d44\u6e90\u4e2d\u590d\u5236\x00The port that this container exposes. If --expose is true, this is also the port used by the service that is created.\x00The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.\x00\u8d44\u6e90\u4e3a container \u8bf7\u6c42 requests . \u4f8b\u5982, 'cpu=100m,memory=256Mi'. \u6ce8\u610f\u670d\u52a1\u7aef\u7ec4\u4ef6\u4e5f\u8bb8\u4f1a\u8d4b\u4e88 requests, \u8fd9\u51b3\u5b9a\u4e8e\u670d\u52a1\u5668\u7aef\u914d\u7f6e, \u6bd4\u5982 limit ranges.\x00\u8fd9\u4e2a Pod \u7684 restart policy. Legal values [Always, OnFailure, Never]. \u5982\u679c\u8bbe\u7f6e\u4e3a 'Always' \u4e00\u4e2a deployment \u88ab\u521b\u5efa, \u5982\u679c\u8bbe\u7f6e\u4e3a \u2019OnFailure' \u4e00\u4e2a job \u88ab\u521b\u5efa, \u5982\u679c\u8bbe\u7f6e\u4e3a 'Never', \u4e00\u4e2a\u666e\u901a\u7684 pod \u88ab\u521b\u5efa. \u5bf9\u4e8e\u540e\u9762\u4e24\u4e2a --replicas \u5fc5\u987b\u4e3a 1. \u9ed8\u8ba4 'Always', \u4e3a CronJobs \u8bbe\u7f6e\u4e3a `Never`.\x00\u521b\u5efa secret \u7c7b\u578b\u8d44\u6e90\x00\u5bf9\u4e8e\u670d\u52a1\u7684\u7c7b\u578b: ClusterIP, NodePort, \u6216\u8005 LoadBalancer. \u9ed8\u8ba4\u662f 'ClusterIP\u2019.\x00\u64a4\u9500\u4e0a\u4e00\u6b21\u7684 rollout\x00\u53d6\u6d88\u8bbe\u7f6e kubeconfig \u6587\u4ef6\u4e2d\u7684\u4e00\u4e2a\u5355\u4e2a\u503c\x00\u4f7f\u7528 strategic merge patch \u66f4\u65b0\u4e00\u4e2a\u8d44\u6e90\u7684 field(s)\x00\u66f4\u65b0\u4e00\u4e2a pod template \u7684\u955c\u50cf\x00\u5728\u5bf9\u8c61\u7684 pod templates \u4e0a\u66f4\u65b0\u8d44\u6e90\u7684 requests/limits\x00\u66f4\u65b0\u4e00\u4e2a\u8d44\u6e90\u7684\u6ce8\u89e3\x00\u66f4\u65b0\u5728\u8fd9\u4e2a\u8d44\u6e90\u4e0a\u7684 labels\x00\u66f4\u65b0\u4e00\u4e2a\u6216\u8005\u591a\u4e2a node \u4e0a\u7684 taints\x00Username \u4e3a Docker registry authentication\x00\u663e\u793a\u6700\u540e\u7684 resource/object \u7684 last-applied-configuration annotations\x00\u663e\u793a rollout \u5386\u53f2\x00\u8f93\u51fa\u5230 files. \u5982\u679c\u662f empty or '-' \u4f7f\u7528 stdout, \u5426\u5219\u521b\u5efa\u4e00\u4e2a \u76ee\u5f55\u5c42\u7ea7\u5728\u90a3\u4e2a\u76ee\u5f55\x00dummy restart flag)\x00\u670d\u52a1\u7684\u5916\u90e8\u540d\u79f0\x00kubectl \u63a7\u5236 Kubernetes cluster \u7ba1\u7406\x00") + +func translationsKubectlZh_cnLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlZh_cnLc_messagesK8sMo, nil +} + +func translationsKubectlZh_cnLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlZh_cnLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/zh_CN/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlZh_cnLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR shiywang@redhat.com, 2017. +# FIRST AUTHOR zhengjiajin@caicloud.io, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2017-11-11 19:01+0800\n" +"Last-Translator: zhengjiajin \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.4\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language: zh\n" + +#: pkg/kubectl/cmd/create_clusterrolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # 使用 cluster-admin ClusterRole 为 user1, user2, and group1 创建一个 ClusterRoleBinding\n" +"\t\t kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_rolebinding.go:35 +msgid "" +"\n" +"\t\t # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1" +msgstr "" +"\n" +"\t\t # 使用 admin ClusterRole 为 user1, user2, and group1 创建一个 RoleBinding\n" +"\t\t kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1" + +#: pkg/kubectl/cmd/create_configmap.go:44 +msgid "" +"\n" +"\t\t # Create a new configmap named my-config based on folder bar\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # Create a new configmap named my-config with specified keys instead of file basenames on disk\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # Create a new configmap named my-config with key1=config1 and key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2" +msgstr "" +"\n" +"\t\t # 通过文件夹 bar 创建一个名称为 my-config 的 configmap\n" +"\t\t kubectl create configmap my-config --from-file=path/to/bar\n" +"\n" +"\t\t # 创建一个名称为 my-config 的 configmap 并指定 keys 而不是使用磁盘上所在的文件名\n" +"\t\t kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt\n" +"\n" +"\t\t # 创建一个名称为 my-config 的 configmap 且 key1=config1 和 key2=config2\n" +"\t\t kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2" + +#: pkg/kubectl/cmd/create_secret.go:135 +msgid "" +"\n" +"\t\t # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" +msgstr "" +"\n" +"\t\t # 如果你还没有一个 .dockercfg 文件, 你可以直接使用下面的命令创建一个 dockercfg 的 secret:\n" +"\t\t kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL" + +#: pkg/kubectl/cmd/top_node.go:65 +msgid "" +"\n" +"\t\t # Show metrics for all nodes\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # Show metrics for a given node\n" +"\t\t kubectl top node NODE_NAME" +msgstr "" +"\n" +"\t\t # 显示所有 nodes 上的指标\n" +"\t\t kubectl top node\n" +"\n" +"\t\t # 显示指定 node 上的指标\n" +"\t\t kubectl top node NODE_NAME" + +#: pkg/kubectl/cmd/apply.go:84 +msgid "" +"\n" +"\t\t# Apply the configuration in pod.json to a pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# Apply the JSON passed into stdin to a pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune is still in Alpha\n" +"\t\t# Apply the configuration in manifest.yaml that matches label app=nginx and delete all the other resources that are not in the file and match label app=nginx.\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# Apply the configuration in manifest.yaml and delete all the other configmaps that are not in the file.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap" +msgstr "" +"\n" +"\t\t# 将 pod.json 上的配置应用于 pod.\n" +"\t\tkubectl apply -f ./pod.json\n" +"\n" +"\t\t# 将传入 stdin 的 JSON 应用到一个 pod.\n" +"\t\tcat pod.json | kubectl apply -f -\n" +"\n" +"\t\t# Note: --prune 仍然在 Alpha\n" +"\t\t# 应用在 manifest.yaml 中匹配标签 app=nginx 的资源配置并删除所有不在这个文件中并匹配标签app=nginx 的资源\n" +"\t\tkubectl apply --prune -f manifest.yaml -l app=nginx\n" +"\n" +"\t\t# 应用 manifest.yaml 的配置并删除所有不在这个文件中的 configmaps.\n" +"\t\tkubectl apply --prune -f manifest.yaml --all --prune-whitelist=core/v1/ConfigMap" + +#: pkg/kubectl/cmd/autoscale.go:40 +#, c-format +msgid "" +"\n" +"\t\t# Auto scale a deployment \"foo\", with the number of pods between 2 and 10, target CPU utilization specified so a default autoscaling policy will be used:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# Auto scale a replication controller \"foo\", with the number of pods between 1 and 5, target CPU utilization at 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" +msgstr "" +"\n" +"\t\t# 自动弹性伸缩 deployment \"foo\", pods 的数量在 2 和 10 之间, 目标 CPU 指定为默认的弹性伸缩策略:\n" +"\t\tkubectl autoscale deployment foo --min=2 --max=10\n" +"\n" +"\t\t# 自动弹性伸缩 replication controller \"foo\", pods 的数量在 1 和 5 之间, 目标 CPU 利用率为 80%:\n" +"\t\tkubectl autoscale rc foo --max=5 --cpu-percent=80" + +#: pkg/kubectl/cmd/convert.go:49 +msgid "" +"\n" +"\t\t# Convert 'pod.yaml' to latest version and print to stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# Convert the live state of the resource specified by 'pod.yaml' to the latest version\n" +"\t\t# and print to stdout in json format.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# Convert all files under current directory to latest version and create them all.\n" +"\t\tkubectl convert -f . | kubectl create -f -" +msgstr "" +"\n" +"\t\t# 将’pod.yaml' 转换为最新版本并打印到 stdout.\n" +"\t\tkubectl convert -f pod.yaml\n" +"\n" +"\t\t# 将 ‘pod.yaml' 指定的资源的实时状态转换为最新版本\n" +"\t\t# 并以 json 格式打印到 stdout.\n" +"\t\tkubectl convert -f pod.yaml --local -o json\n" +"\n" +"\t\t# 将当前目录下的所以文件转换为最新版本并创建它们.\n" +"\t\tkubectl convert -f . | kubectl create -f -" + +#: pkg/kubectl/cmd/create_role.go:41 +msgid "" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" that allows user to perform \"get\", \"watch\" and \"list\" on pods\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n" +"\n" +"\t\t# Create a ClusterRole named \"pod-reader\" with ResourceName specified\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod" +msgstr "" +"\n" +"\t\t# 创建一个名为 \"pod-reader\" 的 ClusterRole, 允许用户在 pods 上执行 “get\", \"watch\" 和 \"list\"\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods\n" +"\n" +"\t\t# 创建一个名为 \"pod-reader\" ClusterRole, 其中指定了 ResourceName\n" +"\t\tkubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod" + +#: pkg/kubectl/cmd/create_quota.go:35 +msgid "" +"\n" +"\t\t# Create a new resourcequota named my-quota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n" +"\n" +"\t\t# Create a new resourcequota named best-effort\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" +msgstr "" +"\n" +"\t\t# 创建一个名为 my-quota 的 resourcequota\n" +"\t\tkubectl create quota my-quota --hard=cpu=1,memory=1G,pods=2,services=3,replicationcontrollers=2,resourcequotas=1,secrets=5,persistentvolumeclaims=10\n" +"\n" +"\t\t# 创建一个名为 best-effort 的 resourcequota\n" +"\t\tkubectl create quota best-effort --hard=pods=100 --scopes=BestEffort" + +#: pkg/kubectl/cmd/create_pdb.go:35 +#, c-format +msgid "" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=rails label\n" +"\t\t# and require at least one of them being available at any point in time.\n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n" +"\n" +"\t\t# Create a pod disruption budget named my-pdb that will select all pods with the app=nginx label\n" +"\t\t# and require at least half of the pods selected to be available at any point in time.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" +msgstr "" +"\n" +"\t\t# 创建一个名称为 my-pdb 的 pod disruption budget 并将会选择所有 app=rails 标签的 pods\n" +"\t\t# 并要求他们在同一时间中最少有一个可用. \n" +"\t\tkubectl create poddisruptionbudget my-pdb --selector=app=rails --min-available=1\n" +"\n" +"\t\t# 创建一个名称为 my-pdb 的 pod disruption budget 并将会选择所有 app=rails 标签的 pods\n" +"\t\t# 并要求他们在同一时间中最少有一半可用.\n" +"\t\tkubectl create pdb my-pdb --selector=app=nginx --min-available=50%" + +#: pkg/kubectl/cmd/create.go:47 +msgid "" +"\n" +"\t\t# Create a pod using the data in pod.json.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# Create a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# Edit the data in docker-registry.yaml in JSON using the v1 API format then create the resource using the edited data.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" +msgstr "" +"\n" +"\t\t# 使用在 pod.json 的 数据创建一个 pod.\n" +"\t\tkubectl create -f ./pod.json\n" +"\n" +"\t\t# 根据传入 stdin 的 JSON 创建一个 pod.\n" +"\t\tcat pod.json | kubectl create -f -\n" +"\n" +"\t\t# 使用 v1 API 格式在 JSON 中编辑在 docker-registry.yaml 中的数据然后使用被编辑后的数据创建资源.\n" +"\t\tkubectl create -f docker-registry.yaml --edit --output-version=v1 -o json" + +#: pkg/kubectl/cmd/expose.go:53 +msgid "" +"\n" +"\t\t# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a replication controller identified by type and name specified in \"nginx-controller.yaml\", which serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for a pod valid-pod, which serves on port 444 with the name \"frontend\"\n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name \"nginx-https\"\n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n" +"\n" +"\t\t# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n" +"\n" +"\t\t# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" +msgstr "" +"\n" +"\t\t# 为一个 replicated nginx 创建一个 service, 服务在端口 80 并连接到 containers 的8000端口.\n" +"\t\tkubectl expose rc nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# 使用在 \"nginx-controller.yaml\\ 中指定的 type 和 name 为一个replication controller 创建一个 service, 服务在端口 80 并连接到 containers 的8000端口.\n" +"\t\tkubectl expose -f nginx-controller.yaml --port=80 --target-port=8000\n" +"\n" +"\t\t# 为名为 valid-pod 的 pod 创建一个 service, 服务在端口 444 并命名为 \"frontend\" \n" +"\t\tkubectl expose pod valid-pod --port=444 --name=frontend\n" +"\n" +"\t\t# 基于上面的 service 创建第二个 service, 暴露容器端口 8443 并命名为 \"nginx-https\" 端口为 443 \n" +"\t\tkubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https\n" +"\n" +"\t\t# 为一个名称为 streaming 的应用创建一个 service 暴露端口 4100, 协议为 UDP 名称为 'video-stream'.\n" +"\t\tkubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream\n" +"\n" +"\t\t# 为一个名称为 nginx 的 replica set 创建一个 service, 服务在 端口 80 且连接到容器端口 8000.\n" +"\t\tkubectl expose rs nginx --port=80 --target-port=8000\n" +"\n" +"\t\t# 为一个名称为 nginx 的 deployment 创建一个 service, 服务在端口 80 且 连接到 containers 的 8000 端口.\n" +"\t\tkubectl expose deployment nginx --port=80 --target-port=8000" + +#: pkg/kubectl/cmd/delete.go:68 +msgid "" +"\n" +"\t\t# Delete a pod using the type and name specified in pod.json.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# Delete a pod based on the type and name in the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# Delete pods and services with same names \"baz\" and \"foo\"\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# Delete pods and services with label name=myLabel.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# Delete a pod with minimal delay\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# Force delete a pod on a dead node\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# Delete all pods\n" +"\t\tkubectl delete pods --all" +msgstr "" +"\n" +"\t\t# 使用 pod.json 中的类型和名称删除一个 pod.\n" +"\t\tkubectl delete -f ./pod.json\n" +"\n" +"\t\t# 基于重定向到 stdin 中的 JSON 的类型和名称删除一个 pod.\n" +"\t\tcat pod.json | kubectl delete -f -\n" +"\n" +"\t\t# 删除名为 \"baz\" 和 \"foo\" 的 pod 和 service\n" +"\t\tkubectl delete pod,service baz foo\n" +"\n" +"\t\t# 删除标签为 name=myLabel 的 pods 和 services.\n" +"\t\tkubectl delete pods,services -l name=myLabel\n" +"\n" +"\t\t# 删除最小延迟的 pod\n" +"\t\tkubectl delete pod foo --now\n" +"\n" +"\t\t# 强制删除名为 foo 的 pod\n" +"\t\tkubectl delete pod foo --grace-period=0 --force\n" +"\n" +"\t\t# 删除所有 pods\n" +"\t\tkubectl delete pods --all" + +#: pkg/kubectl/cmd/describe.go:54 +msgid "" +"\n" +"\t\t# Describe a node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# Describe a pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# Describe a pod identified by type and name in \"pod.json\"\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# Describe all pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# Describe pods by label name=myLabel\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# Describe all pods managed by the 'frontend' replication controller (rc-created pods\n" +"\t\t# get the name of the rc as a prefix in the pod the name).\n" +"\t\tkubectl describe pods frontend" +msgstr "" +"\n" +"\t\t# 描述一个 node\n" +"\t\tkubectl describe nodes kubernetes-node-emt8.c.myproject.internal\n" +"\n" +"\t\t# 描述一个 pod\n" +"\t\tkubectl describe pods/nginx\n" +"\n" +"\t\t# 描述一个被 \"pod.json\" 中的类型和名称标识的 pod\n" +"\t\tkubectl describe -f pod.json\n" +"\n" +"\t\t# 描述所有 pods\n" +"\t\tkubectl describe pods\n" +"\n" +"\t\t# 描述标签为 name=myLabel 的 pods\n" +"\t\tkubectl describe po -l name=myLabel\n" +"\n" +"\t\t# 描述所有被名称为 'frontend' 的 replication controller 管理的 pods(rc-创建 pods\n" +"\t\t# 并使用 rc 的名称作为 pod 的前缀).\n" +"\t\tkubectl describe pods frontend" + +#: pkg/kubectl/cmd/drain.go:165 +msgid "" +"\n" +"\t\t# Drain node \"foo\", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet on it.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet, and use a grace period of 15 minutes.\n" +"\t\t$ kubectl drain foo --grace-period=900" +msgstr "" +"\n" +"\t\t# 驱逐节点 \"foo\", 即使很多 pods 没有被一个在 node 上的 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理.\n" +"\t\t$ kubectl drain foo --force\n" +"\n" +"\t\t# 同上, 如果存在 pods 没有被一个 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理超过 15 分钟则退出.\n" +"\t\t$ kubectl drain foo --grace-period=900" + +#: pkg/kubectl/cmd/edit.go:80 +msgid "" +"\n" +"\t\t# Edit the service named 'docker-registry':\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# Use an alternative editor\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# Edit the job 'myjob' in JSON using the v1 API format:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# Edit the deployment 'mydeployment' in YAML and save the modified config in its annotation:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" +msgstr "" +"\n" +"\t\t# 编辑名为 'docker-registry' 的 service:\n" +"\t\tkubectl edit svc/docker-registry\n" +"\n" +"\t\t# 使用一个可选择的编辑器\n" +"\t\tKUBE_EDITOR=\"nano\" kubectl edit svc/docker-registry\n" +"\n" +"\t\t# 使用 v1 API 格式的 JSON 编辑名为 'myjob' 的 job:\n" +"\t\tkubectl edit job.v1.batch/myjob -o json\n" +"\n" +"\t\t# 在 YAML 中编辑名为 'mydeployment' 的 deployment 并在它的注解中保存修改后的配置:\n" +"\t\tkubectl edit deployment/mydeployment -o yaml --save-config" + +#: pkg/kubectl/cmd/exec.go:41 +msgid "" +"\n" +"\t\t# Get output from running 'date' from pod 123456-7890, using the first container by default\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# Get output from running 'date' in ruby-container from pod 123456-7890\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" +msgstr "" +"\n" +"\t\t# 从运行中pod 123456-7890 获取执行 'date' 的输出, 默认使用第一个容器\n" +"\t\tkubectl exec 123456-7890 date\n" +"\n" +"\t\t# 从 pod 123456-7890 的容器 ruby-container 获取执行 'date' 的输出\n" +"\t\tkubectl exec 123456-7890 -c ruby-container date\n" +"\n" +"\t\t# 切换到 terminal 模式, 发送 stdin 到运行在 pod 123456-7890 的容器 ruby-container 'bash' \n" +"\t\t# 并从 'bash' 发送 stdout/stderr 返回到 client\n" +"\t\tkubectl exec 123456-7890 -c ruby-container -i -t -- bash -il" + +#: pkg/kubectl/cmd/attach.go:42 +msgid "" +"\n" +"\t\t# Get output from running pod 123456-7890, using the first container by default\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# Get output from ruby-container from pod 123456-7890\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890\n" +"\t\t# and sends stdout/stderr from 'bash' back to the client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# Get output from the first pod of a ReplicaSet named nginx\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" +msgstr "" +"\n" +"\t\t# 从运行中pod 123456-7890 获取执行 'date' 的输出, 默认使用第一个容器\n" +"\t\tkubectl attach 123456-7890\n" +"\n" +"\t\t# 从 pod 123456-7890 的容器 ruby-container 获取输出\n" +"\t\tkubectl attach 123456-7890 -c ruby-container\n" +"\n" +"\t\t# 切换到 terminal 模式, 发送 stdin 到运行在 pod 123456-7890 的容器 ruby-container 'bash' \n" +"\t\t# 并从 'bash' 发送 stdout/stderr 返回到 client\n" +"\t\tkubectl attach 123456-7890 -c ruby-container -i -t\n" +"\n" +"\t\t# 从名称为 nginx 的 ReplicaSet 获取第一个 pod 的输出\n" +"\t\tkubectl attach rs/nginx\n" +"\t\t" + +#: pkg/kubectl/cmd/explain.go:39 +msgid "" +"\n" +"\t\t# Get the documentation of the resource and its fields\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# Get the documentation of a specific field of a resource\n" +"\t\tkubectl explain pods.spec.containers" +msgstr "" +"\n" +"\t\t# 获取资源及其字段的文档\n" +"\t\tkubectl explain pods\n" +"\n" +"\t\t# 获取资源指定字段的文档\n" +"\t\tkubectl explain pods.spec.containers" + +#: pkg/kubectl/cmd/completion.go:65 +msgid "" +"\n" +"\t\t# Install bash completion on a Mac using homebrew\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash completion support\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for bash into the current shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# Write bash completion code to a file and source if from .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell completion\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# Load the kubectl completion code for zsh[1] into the current shell\n" +"\t\tsource <(kubectl completion zsh)" +msgstr "" +"\n" +"\t\t# 在一个 Mac 中使用 homebrew 安装 bash 补全\n" +"\t\tbrew install bash-completion\n" +"\t\tprintf \"\n" +"# Bash 补全支持\n" +"source $(brew --prefix)/etc/bash_completion\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# 导入 kubectl 补全代码到当前 shell\n" +"\t\tsource <(kubectl completion bash)\n" +"\n" +"\t\t# 写入 bash 补全代码到一个文件并 source 如果它是 .bash_profile\n" +"\t\tkubectl completion bash > ~/.kube/completion.bash.inc\n" +"\t\tprintf \"\n" +"# Kubectl shell 补全\n" +"source '$HOME/.kube/completion.bash.inc'\n" +"\" >> $HOME/.bash_profile\n" +"\t\tsource $HOME/.bash_profile\n" +"\n" +"\t\t# 为 zsh[1] 导入 kubectl 补全代码到当前 shell\n" +"\t\tsource <(kubectl completion zsh)" + +#: pkg/kubectl/cmd/get.go:64 +msgid "" +"\n" +"\t\t# List all pods in ps output format.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# List all pods in ps output format with more information (such as node name).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# List a single replication controller with specified NAME in ps output format.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# List a single pod in JSON output format.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# List a pod identified by type and name specified in \"pod.yaml\" in JSON output format.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# Return only the phase value of the specified pod.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# List all replication controllers and services together in ps output format.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# List one or more resources by their type and names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# List all resources with different types.\n" +"\t\tkubectl get all" +msgstr "" +"\n" +"\t\t# 以 ps 输出格式列出所有 pod.\n" +"\t\tkubectl get pods\n" +"\n" +"\t\t# 以 ps 输出格式列出所有 pod(如节点名称).\n" +"\t\tkubectl get pods -o wide\n" +"\n" +"\t\t# 获取名称为 web 的 replicationcontroller.\n" +"\t\tkubectl get replicationcontroller web\n" +"\n" +"\t\t# 使用 JSON 格式化输出显示一个单独的 pod.\n" +"\t\tkubectl get -o json pod web-pod-13je7\n" +"\n" +"\t\t# 显示一个被 \"pod.yaml\" 中的 type 和 name 标识的 pod 并使用 JSON 格式化输出.\n" +"\t\tkubectl get -f pod.yaml -o json\n" +"\n" +"\t\t# 只返回被指定 pod 中 phase 的值.\n" +"\t\tkubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}\n" +"\n" +"\t\t# 显示所有的 replication controllers 和 services 并格式化输出.\n" +"\t\tkubectl get rc,services\n" +"\n" +"\t\t# 显示一个或者更多 resources 通过它们的 type 和 names.\n" +"\t\tkubectl get rc/web service/frontend pods/web-pod-13je7\n" +"\n" +"\t\t# 使用不同的 types 显示所有 resources.\n" +"\t\tkubectl get all" + +#: pkg/kubectl/cmd/portforward.go:53 +msgid "" +"\n" +"\t\t# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# Listen on port 8888 locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# Listen on a random port locally, forwarding to 5000 in the pod\n" +"\t\tkubectl port-forward mypod 0:5000" +msgstr "" +"\n" +"\t\t# 在本地监听端口 5000 和 6000 , forwarding 数据 to/from 在 pod 5000 和 6000 端口\n" +"\t\tkubectl port-forward mypod 5000 6000\n" +"\n" +"\t\t# 在本地监听端口 8888 , forwarding 到 pod 的 5000端口\n" +"\t\tkubectl port-forward mypod 8888:5000\n" +"\n" +"\t\t# 在本地随机监听一个端口 , forwarding 到 pod 的 5000端口\n" +"\t\tkubectl port-forward mypod :5000\n" +"\n" +"\t\t# 在本地随机监听一个端口 , forwarding 到 pod 的 5000端口\n" +"\t\tkubectl port-forward mypod 0:5000" + +#: pkg/kubectl/cmd/drain.go:118 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as schedulable.\n" +"\t\t$ kubectl uncordon foo" +msgstr "" +"\n" +"\t\t# 标记 node \"foo\" 为 schedulable.\n" +"\t\t$ kubectl uncordon foo" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:93 +msgid "" +"\n" +"\t\t# Mark node \"foo\" as unschedulable.\n" +"\t\tkubectl cordon foo" +msgstr "" +"\n" +"\t\t# 标记 node \"foo\" 为 unschedulable.\n" +"\t\tkubectl cordon foo" + +#: pkg/kubectl/cmd/patch.go:66 +msgid "" +"\n" +"\t\t# Partially update a node using strategic merge patch\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Partially update a node identified by the type and name specified in \"node.json\" using strategic merge patch\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# Update a container's image; spec.containers[*].name is required because it's a merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# Update a container's image using a json patch with positional arrays\n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" +msgstr "" +"\n" +"\t\t# 使用 strategic merge patch 部分更新一个 node\n" +"\t\tkubectl patch node k8s-node-1 -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# 使用 strategic merge patch 部分更新一个被 \"node.json\" 的 type 和 name 标示 的 node.\n" +"\t\tkubectl patch -f node.json -p '{\"spec\":{\"unschedulable\":true}}'\n" +"\n" +"\t\t# 更新一个 container 的 image; spec.containers[*].name 是必须的 因为它是一个 merge key\n" +"\t\tkubectl patch pod valid-pod -p '{\"spec\":{\"containers\":[{\"name\":\"kubernetes-serve-hostname\",\"image\":\"new image\"}]}}'\n" +"\n" +"\t\t# 使用一个 json patch 更新一个指定坐标的 container 的 image \n" +"\t\tkubectl patch pod valid-pod --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/containers/0/image\", \"value\":\"new image\"}]'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:29 +msgid "" +"\n" +"\t\t# Print flags inherited by all commands\n" +"\t\tkubectl options" +msgstr "" +"\n" +"\t\t# 输出所有命令继承的 flags\n" +"\t\tkubectl options" + +#: pkg/kubectl/cmd/clusterinfo.go:41 +msgid "" +"\n" +"\t\t# Print the address of the master and cluster services\n" +"\t\tkubectl cluster-info" +msgstr "" +"\n" +"\t\t# 输出 master 和 cluster services 的地址\n" +"\t\tkubectl cluster-info" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:32 +msgid "" +"\n" +"\t\t# Print the client and server versions for the current context\n" +"\t\tkubectl version" +msgstr "" +"\n" +"\t\t# 输出当前 client 和 server 版本\n" +"\t\tkubectl version" + +#: pkg/kubectl/cmd/apiversions.go:34 +msgid "" +"\n" +"\t\t# Print the supported API versions\n" +"\t\tkubectl api-versions" +msgstr "" +"\n" +"\t\t# 输出支持的 API 版本\n" +"\t\tkubectl api-versions" + +#: pkg/kubectl/cmd/replace.go:50 +msgid "" +"\n" +"\t\t# Replace a pod using the data in pod.json.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# Replace a pod based on the JSON passed into stdin.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# Update a single-container pod's image version (tag) to v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | kubectl replace -f -\n" +"\n" +"\t\t# Force replace, delete and then re-create the resource\n" +"\t\tkubectl replace --force -f ./pod.json" +msgstr "" +"\n" +"\t\t# 使用在 pod.json 中的数据替换一个 pod.\n" +"\t\tkubectl replace -f ./pod.json\n" +"\n" +"\t\t# 基于被重定向到 stdin 中的 JSON 替换一个 pod.\n" +"\t\tcat pod.json | kubectl replace -f -\n" +"\n" +"\t\t# 更新一个单独容器的 pod 的 image 版本 (tag) 到 v4\n" +"\t\tkubectl get pod mypod -o yaml | sed 's/\\(image: myimage\\):.*$/:v4/' | kubectl replace -f -\n" +"\n" +"\t\t# 强制替换, 删除然后重新创建这个 resource\n" +"\t\tkubectl replace --force -f ./pod.json" + +#: pkg/kubectl/cmd/logs.go:40 +msgid "" +"\n" +"\t\t# Return snapshot logs from pod nginx with only one container\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# Return snapshot logs for the pods defined by label app=nginx\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" +msgstr "" +"\n" +"\t\t# 返回仅有一个容器 pod 名称为 nginx 的 snapshot 日志\n" +"\t\tkubectl logs nginx\n" +"\n" +"\t\t# 返回 label 为 app=nginx 的 pods 的 snapshot 日志\n" +"\t\tkubectl logs -lapp=nginx\n" +"\n" +"\t\t# Return snapshot of previous terminated ruby container logs from pod web-1\n" +"\t\tkubectl logs -p -c ruby web-1\n" +"\n" +"\t\t# Begin streaming the logs of the ruby container in pod web-1\n" +"\t\tkubectl logs -f -c ruby web-1\n" +"\n" +"\t\t# Display only the most recent 20 lines of output in pod nginx\n" +"\t\tkubectl logs --tail=20 nginx\n" +"\n" +"\t\t# Show all logs from pod nginx written in the last hour\n" +"\t\tkubectl logs --since=1h nginx\n" +"\n" +"\t\t# Return snapshot logs from first container of a job named hello\n" +"\t\tkubectl logs job/hello\n" +"\n" +"\t\t# Return snapshot logs from container nginx-1 of a deployment named nginx\n" +"\t\tkubectl logs deployment/nginx -c nginx-1" + +#: pkg/kubectl/cmd/proxy.go:53 +msgid "" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver on an arbitrary local port.\n" +"\t\t# The chosen port for the server will be output to stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api\n" +"\t\t# This makes e.g. the pods api available at localhost:8001/k8s-api/v1/pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" +msgstr "" +"\n" +"\t\t# 运行 proxy 到 kubernetes apiserver 的 8011 端口上, 服务静态内容路径为 ./local/www/\n" +"\t\tkubectl proxy --port=8011 --www=./local/www/\n" +"\n" +"\t\t# 在任意的本地端口上运行一个 proxy 到 kubernetes apiserver.\n" +"\t\t# 为这个 server 挑选的端口将会被输出到 stdout.\n" +"\t\tkubectl proxy --port=0\n" +"\n" +"\t\t# 运行一个 proxy 到 kubernetes apiserver, 修改 api prefix 为 k8s-api\n" +"\t\t# 这会使 e.g. 这个 pods 的有效 api 为 localhost:8001/k8s-api/v1/pods/\n" +"\t\tkubectl proxy --api-prefix=/k8s-api" + +#: pkg/kubectl/cmd/scale.go:43 +msgid "" +"\n" +"\t\t# Scale a replicaset named 'foo' to 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale a resource identified by type and name specified in \"foo.yaml\" to 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# If the deployment named mysql's current size is 2, scale mysql to 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale multiple replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale job named 'cron' to 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" +msgstr "" +"\n" +"\t\t# Scale 一个名称为 ‘foo’ 的 replicaset 服本数为 3.\n" +"\t\tkubectl scale --replicas=3 rs/foo\n" +"\n" +"\t\t# Scale 指定的 \"foo.yaml\" 的 type 和 name 标识的 resource 副本数量为 3.\n" +"\t\tkubectl scale --replicas=3 -f foo.yaml\n" +"\n" +"\t\t# 如果名称为 mysql 的 deployment 当前副本数量为 2, scale mysql 到 3.\n" +"\t\tkubectl scale --current-replicas=2 --replicas=3 deployment/mysql\n" +"\n" +"\t\t# Scale 多个 replication controllers.\n" +"\t\tkubectl scale --replicas=5 rc/foo rc/bar rc/baz\n" +"\n" +"\t\t# Scale 名称为 ’cron’ 的 job 副本数量为 3.\n" +"\t\tkubectl scale --replicas=3 job/cron" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:67 +msgid "" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents of a file.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# Set the last-applied-configuration of a resource to match the contents of a file, will create the annotation if it does not already exist.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" +msgstr "" +"\n" +"\t\t# 设置一个资源的 last-applied-configuration 去匹配一个文件的内容.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml\n" +"\n" +"\t\t# Execute set-last-applied against each configuration file in a directory.\n" +"\t\tkubectl apply set-last-applied -f path/\n" +"\n" +"\t\t# 设置一个资源的 last-applied-configuration 去匹配一个文件的内容, 如果不存在将会创建一个 annotation.\n" +"\t\tkubectl apply set-last-applied -f deploy.yaml --create-annotation=true\n" +"\t\t" + +#: pkg/kubectl/cmd/top_pod.go:61 +msgid "" +"\n" +"\t\t# Show metrics for all pods in the default namespace\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# Show metrics for all pods in the given namespace\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# Show metrics for a given pod and its containers\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# Show metrics for the pods defined by label name=myLabel\n" +"\t\tkubectl top pod -l name=myLabel" +msgstr "" +"\n" +"\t\t# 显示 default namespace 下所有 pods 下的 metrics\n" +"\t\tkubectl top pod\n" +"\n" +"\t\t# 显示指定 namespace 下所有 pods 的 metrics\n" +"\t\tkubectl top pod --namespace=NAMESPACE\n" +"\n" +"\t\t# 显示指定 pod 和它的容器的 metrics\n" +"\t\tkubectl top pod POD_NAME --containers\n" +"\n" +"\t\t# 显示指定 label 为 name=myLabel 的 pods 的 metrics\n" +"\t\tkubectl top pod -l name=myLabel" + +#: pkg/kubectl/cmd/stop.go:40 +msgid "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" +msgstr "" +"\n" +"\t\t# Shut down foo.\n" +"\t\tkubectl stop replicationcontroller foo\n" +"\n" +"\t\t# Stop pods and services with label name=myLabel.\n" +"\t\tkubectl stop pods,services -l name=myLabel\n" +"\n" +"\t\t# Shut down the service defined in service.json\n" +"\t\tkubectl stop -f service.json\n" +"\n" +"\t\t# Shut down all resources in the path/to/resources directory\n" +"\t\tkubectl stop -f path/to/resources" + +#: pkg/kubectl/cmd/run.go:57 +msgid "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every 5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" +msgstr "" +"\n" +"\t\t# Start a single instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx\n" +"\n" +"\t\t# Start a single instance of hazelcast and let the container expose port 5701 .\n" +"\t\tkubectl run hazelcast --image=hazelcast --port=5701\n" +"\n" +"\t\t# Start a single instance of hazelcast and set environment variables \"DNS_DOMAIN=cluster\" and \"POD_NAMESPACE=default\" in the container.\n" +"\t\tkubectl run hazelcast --image=hazelcast --env=\"DNS_DOMAIN=cluster\" --env=\"POD_NAMESPACE=default\"\n" +"\n" +"\t\t# Start a replicated instance of nginx.\n" +"\t\tkubectl run nginx --image=nginx --replicas=5\n" +"\n" +"\t\t# Dry run. Print the corresponding API objects without creating them.\n" +"\t\tkubectl run nginx --image=nginx --dry-run\n" +"\n" +"\t\t# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON.\n" +"\t\tkubectl run nginx --image=nginx --overrides='{ \"apiVersion\": \"v1\", \"spec\": { ... } }'\n" +"\n" +"\t\t# Start a pod of busybox and keep it in the foreground, don't restart it if it exits.\n" +"\t\tkubectl run -i -t busybox --image=busybox --restart=Never\n" +"\n" +"\t\t# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command.\n" +"\t\tkubectl run nginx --image=nginx -- ... \n" +"\n" +"\t\t# Start the nginx container using a different command and custom arguments.\n" +"\t\tkubectl run nginx --image=nginx --command -- ... \n" +"\n" +"\t\t# Start the perl container to compute π to 2000 places and print it out.\n" +"\t\tkubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'\n" +"\n" +"\t\t# Start the cron job to compute π to 2000 places and print it out every 5 minutes.\n" +"\t\tkubectl run pi --schedule=\"0/5 * * * ?\" --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'" + +#: pkg/kubectl/cmd/taint.go:67 +msgid "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" +msgstr "" +"\n" +"\t\t# Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule'.\n" +"\t\t# If a taint with that key and effect already exists, its value is replaced as specified.\n" +"\t\tkubectl taint nodes foo dedicated=special-user:NoSchedule\n" +"\n" +"\t\t# Remove from node 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists.\n" +"\t\tkubectl taint nodes foo dedicated:NoSchedule-\n" +"\n" +"\t\t# Remove from node 'foo' all the taints with key 'dedicated'\n" +"\t\tkubectl taint nodes foo dedicated-" + +#: pkg/kubectl/cmd/label.go:77 +msgid "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" +msgstr "" +"\n" +"\t\t# Update pod 'foo' with the label 'unhealthy' and the value 'true'.\n" +"\t\tkubectl label pods foo unhealthy=true\n" +"\n" +"\t\t# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value.\n" +"\t\tkubectl label --overwrite pods foo status=unhealthy\n" +"\n" +"\t\t# Update all pods in the namespace\n" +"\t\tkubectl label pods --all status=unhealthy\n" +"\n" +"\t\t# Update a pod identified by the type and name in \"pod.json\"\n" +"\t\tkubectl label -f pod.json status=unhealthy\n" +"\n" +"\t\t# Update pod 'foo' only if the resource is unchanged from version 1.\n" +"\t\tkubectl label pods foo status=unhealthy --resource-version=1\n" +"\n" +"\t\t# Update pod 'foo' by removing a label named 'bar' if it exists.\n" +"\t\t# Does not require the --overwrite flag.\n" +"\t\tkubectl label pods foo bar-" + +#: pkg/kubectl/cmd/rollingupdate.go:54 +msgid "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" +msgstr "" +"\n" +"\t\t# Update pods of frontend-v1 using new replication controller data in frontend-v2.json.\n" +"\t\tkubectl rolling-update frontend-v1 -f frontend-v2.json\n" +"\n" +"\t\t# Update pods of frontend-v1 using JSON data passed into stdin.\n" +"\t\tcat frontend-v2.json | kubectl rolling-update frontend-v1 -f -\n" +"\n" +"\t\t# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the\n" +"\t\t# name of the replication controller.\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --image=image:v2\n" +"\n" +"\t\t# Update the pods of frontend by just changing the image, and keeping the old name.\n" +"\t\tkubectl rolling-update frontend --image=image:v2\n" +"\n" +"\t\t# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2).\n" +"\t\tkubectl rolling-update frontend-v1 frontend-v2 --rollback" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:52 +msgid "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" +msgstr "" +"\n" +"\t\t# View the last-applied-configuration annotations by type/name in YAML.\n" +"\t\tkubectl apply view-last-applied deployment/nginx\n" +"\n" +"\t\t# View the last-applied-configuration annotations by file in JSON\n" +"\t\tkubectl apply view-last-applied -f deploy.yaml -o json" + +#: pkg/kubectl/cmd/apply.go:75 +msgid "" +"\n" +"\t\tApply a configuration to a resource by filename or stdin.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274." +msgstr "" +"\n" +"\t\t通过文件名或标准输入流(stdin)对资源进行配置.\n" +"\t\tThis resource will be created if it doesn't exist yet.\n" +"\t\tTo use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +"\n" +"\t\tAlpha Disclaimer: the --prune functionality is not yet complete. Do not use unless you are aware of what the current state is. See https://issues.k8s.io/34274." + +#: pkg/kubectl/cmd/convert.go:38 +msgid "" +"\n" +"\t\tConvert config files between different API versions. Both YAML\n" +"\t\tand JSON formats are accepted.\n" +"\n" +"\t\tThe command takes filename, directory, or URL as input, and convert it into format\n" +"\t\tof version specified by --output-version flag. If target version is not specified or\n" +"\t\tnot supported, convert to latest version.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n" +"\t\tto change to output destination." +msgstr "" +"\n" +"\t\t在不同的 API versions 转换配置文件. 接受 YAML\n" +"\t\t和 JSON 格式.\n" +"\n" +"\t\t这个命令以 filename, directory, 或者 URL 作为输入, 并通过 —output-version flag\n" +"\t\t 转换到指定版本的格式. 如果目标版本没有被指定或者\n" +"\t\t不支持, 转换到最后的版本.\n" +"\n" +"\t\t默认以 YAML 格式输出到 stdout. 可以使用 -o option\n" +"\t\t修改目标输出的格式." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_clusterrole.go:31 +msgid "" +"\n" +"\t\tCreate a ClusterRole." +msgstr "" +"\n" +"\t\t创建一个 ClusterRole." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a ClusterRoleBinding for a particular ClusterRole." +msgstr "" +"\n" +"\t\t 为指定的 ClusterRole 创建一个 ClusterRoleBinding." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:32 +msgid "" +"\n" +"\t\tCreate a RoleBinding for a particular Role or ClusterRole." +msgstr "" +"\n" +"\t\t为指定的 Role 或者 ClusterRole 创建一个 RoleBinding." + +#: pkg/kubectl/cmd/create_secret.go:200 +msgid "" +"\n" +"\t\tCreate a TLS secret from the given public/private key pair.\n" +"\n" +"\t\tThe public/private key pair must exist before hand. The public key certificate must be .PEM encoded and match the given private key." +msgstr "" +"\n" +"\t\t为指定的 public/private key pair 创建一个 TLS secret.\n" +"\n" +"\t\tpublic/private key pair 必须在传递前存在. public key certificate 必须以 .PEM 被编码且匹配指定的 private key." + +#: pkg/kubectl/cmd/create_configmap.go:32 +msgid "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a configmap based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single configmap may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a configmap based on a file, the key will default to the basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n" +"\n" +"\t\tWhen creating a configmap based on a directory, each file whose basename is a valid key in the directory will be\n" +"\t\tpackaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:32 +msgid "" +"\n" +"\t\tCreate a namespace with the specified name." +msgstr "" +"\n" +"\t\t创建一个 namespace 并指定名称." + +#: pkg/kubectl/cmd/create_secret.go:119 +msgid "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." +msgstr "" +"\n" +"\t\tCreate a new secret for use with Docker registries.\n" +"\n" +"\t\tDockercfg secrets are used to authenticate against Docker registries.\n" +"\n" +"\t\tWhen using the Docker command line to push images, you can authenticate to a given registry by running\n" +"\n" +"\t\t $ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.\n" +"\n" +" That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to\n" +"\t\tauthenticate to the registry. The email address is optional.\n" +"\n" +"\t\tWhen creating applications, you may have a Docker registry that requires authentication. In order for the\n" +"\t\tnodes to pull images on your behalf, they have to have the credentials. You can provide this information\n" +"\t\tby creating a dockercfg secret and attaching it to your service account." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:32 +msgid "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods" +msgstr "" +"\n" +"\t\tCreate a pod disruption budget with the specified name, selector, and desired minimum available pods" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:42 +msgid "" +"\n" +"\t\tCreate a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted." +msgstr "" +"\n" +"\t\t通过文件名或者标准输入流(stdin)创建一个资源.\n" +"\n" +"\t\tJSON and YAML formats are accepted." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:32 +msgid "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional scopes" +msgstr "" +"\n" +"\t\tCreate a resourcequota with the specified name, hard limits and optional scopes" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_role.go:38 +msgid "" +"\n" +"\t\tCreate a role with single rule." +msgstr "" +"\n" +"\t\t创建单一 rule 的 role." + +#: pkg/kubectl/cmd/create_secret.go:47 +msgid "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." +msgstr "" +"\n" +"\t\tCreate a secret based on a file, directory, or specified literal value.\n" +"\n" +"\t\tA single secret may package one or more key/value pairs.\n" +"\n" +"\t\tWhen creating a secret based on a file, the key will default to the basename of the file, and the value will\n" +"\t\tdefault to the file content. If the basename is an invalid key, you may specify an alternate key.\n" +"\n" +"\t\tWhen creating a secret based on a directory, each file whose basename is a valid key in the directory will be\n" +"\t\tpackaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories,\n" +"\t\tsymlinks, devices, pipes, etc)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:32 +msgid "" +"\n" +"\t\tCreate a service account with the specified name." +msgstr "" +"\n" +"\t\t创建一个指定名称的 service account." + +#: pkg/kubectl/cmd/run.go:52 +msgid "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." +msgstr "" +"\n" +"\t\tCreate and run a particular image, possibly replicated.\n" +"\n" +"\t\tCreates a deployment or job to manage the created container(s)." + +#: pkg/kubectl/cmd/autoscale.go:34 +msgid "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed." +msgstr "" +"\n" +"\t\tCreates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster.\n" +"\n" +"\t\tLooks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference.\n" +"\t\tAn autoscaler can automatically increase or decrease number of pods deployed within the system as needed." + +#: pkg/kubectl/cmd/delete.go:40 +msgid "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n" +"\t\tmultiple processes running on different machines using the same identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their update\n" +"\t\twill be lost along with the rest of the resource." +msgstr "" +"\n" +"\t\tDelete resources by filenames, stdin, resources and names, or by resources and label selector.\n" +"\n" +"\t\tJSON and YAML formats are accepted. Only one type of the arguments may be specified: filenames,\n" +"\t\tresources and names, or resources and label selector.\n" +"\n" +"\t\tSome resources, such as pods, support graceful deletion. These resources define a default period\n" +"\t\tbefore they are forcibly terminated (the grace period) but you may override that value with\n" +"\t\tthe --grace-period flag, or pass --now to set a grace-period of 1. Because these resources often\n" +"\t\trepresent entities in the cluster, deletion may not be acknowledged immediately. If the node\n" +"\t\thosting a pod is down or cannot reach the API server, termination may take significantly longer\n" +"\t\tthan the grace period. To force delete a resource,\tyou must pass a grace\tperiod of 0 and specify\n" +"\t\tthe --force flag.\n" +"\n" +"\t\tIMPORTANT: Force deleting pods does not wait for confirmation that the pod's processes have been\n" +"\t\tterminated, which can leave those processes running until the node detects the deletion and\n" +"\t\tcompletes graceful deletion. If your processes use shared storage or talk to a remote API and\n" +"\t\tdepend on the name of the pod to identify themselves, force deleting those pods may result in\n" +"\t\tmultiple processes running on different machines using the same identification which may lead\n" +"\t\tto data corruption or inconsistency. Only force delete pods when you are sure the pod is\n" +"\t\tterminated, or if your application can tolerate multiple copies of the same pod running at once.\n" +"\t\tAlso, if you force delete pods the scheduler may place new pods on those nodes before the node\n" +"\t\thas released those resources and causing those pods to be evicted immediately.\n" +"\n" +"\t\tNote that the delete command does NOT do resource version checks, so if someone\n" +"\t\tsubmits an update to a resource right when you submit a delete, their update\n" +"\t\twill be lost along with the rest of the resource." + +#: pkg/kubectl/cmd/stop.go:31 +msgid "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." +msgstr "" +"\n" +"\t\tDeprecated: Gracefully shut down a resource by name or filename.\n" +"\n" +"\t\tThe stop command is deprecated, all its functionalities are covered by delete command.\n" +"\t\tSee 'kubectl delete --help' for more details.\n" +"\n" +"\t\tAttempts to shut down and delete a resource that supports graceful termination.\n" +"\t\tIf the resource is scalable it will be scaled to 0 before deletion." + +#: pkg/kubectl/cmd/top_node.go:60 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of nodes.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." +msgstr "" +"\n" +"\t\t显示 node 的资源(CPU/Memory/Storage)使用.\n" +"\n" +"\t\tThe top-node command allows you to see the resource consumption of nodes." + +#: pkg/kubectl/cmd/top_pod.go:53 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage of pods.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n" +"\t\tsince pod creation." +msgstr "" +"\n" +"\t\t显示 pods 资源(CPU/Memory/Storage)使用.\n" +"\n" +"\t\tThe 'top pod' command allows you to see the resource consumption of pods.\n" +"\n" +"\t\tDue to the metrics pipeline delay, they may be unavailable for a few minutes\n" +"\t\tsince pod creation." + +#: pkg/kubectl/cmd/top.go:33 +msgid "" +"\n" +"\t\tDisplay Resource (CPU/Memory/Storage) usage.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on the server. " +msgstr "" +"\n" +"\t\t显示资源(CPU/Memory/Storage)使用.\n" +"\n" +"\t\tThe top command allows you to see the resource consumption for nodes or pods.\n" +"\n" +"\t\tThis command requires Heapster to be correctly configured and working on the server. " + +#: pkg/kubectl/cmd/drain.go:140 +msgid "" +"\n" +"\t\tDrain node in preparation for maintenance.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" +msgstr "" +"\n" +"\t\t清理节点为节点维护做准备.\n" +"\n" +"\t\tThe given node will be marked unschedulable to prevent new pods from arriving.\n" +"\t\t'drain' evicts the pods if the APIServer supports eviction\n" +"\t\t(http://kubernetes.io/docs/admin/disruptions/). Otherwise, it will use normal DELETE\n" +"\t\tto delete the pods.\n" +"\t\tThe 'drain' evicts or deletes all pods except mirror pods (which cannot be deleted through\n" +"\t\tthe API server). If there are DaemonSet-managed pods, drain will not proceed\n" +"\t\twithout --ignore-daemonsets, and regardless it will not delete any\n" +"\t\tDaemonSet-managed pods, because those pods would be immediately replaced by the\n" +"\t\tDaemonSet controller, which ignores unschedulable markings. If there are any\n" +"\t\tpods that are neither mirror pods nor managed by ReplicationController,\n" +"\t\tReplicaSet, DaemonSet, StatefulSet or Job, then drain will not delete any pods unless you\n" +"\t\tuse --force. --force will also allow deletion to proceed if the managing resource of one\n" +"\t\tor more pods is missing.\n" +"\n" +"\t\t'drain' waits for graceful termination. You should not operate on the machine until\n" +"\t\tthe command completes.\n" +"\n" +"\t\tWhen you are ready to put the node back into service, use kubectl uncordon, which\n" +"\t\twill make the node schedulable again.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_drain.svg)" + +#: pkg/kubectl/cmd/edit.go:56 +msgid "" +"\n" +"\t\tEdit a resource from the default editor.\n" +"\n" +"\t\tThe edit command allows you to directly edit any API resource you can retrieve via the\n" +"\t\tcommand line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR\n" +"\t\tenvironment variables, or fall back to 'vi' for Linux or 'notepad' for Windows.\n" +"\t\tYou can edit multiple objects, although changes are applied one at a time. The command\n" +"\t\taccepts filenames as well as command line arguments, although the files you point to must\n" +"\t\tbe previously saved versions of resources.\n" +"\n" +"\t\tEditing is done with the API version used to fetch the resource.\n" +"\t\tTo edit using a specific API version, fully-qualify the resource, version, and group.\n" +"\n" +"\t\tThe default format is YAML. To edit in JSON, specify \"-o json\".\n" +"\n" +"\t\tThe flag --windows-line-endings can be used to force Windows line endings,\n" +"\t\totherwise the default for your operating system will be used.\n" +"\n" +"\t\tIn the event an error occurs while updating, a temporary file will be created on disk\n" +"\t\tthat contains your unapplied changes. The most common error when updating a resource\n" +"\t\tis another editor changing the resource on the server. When this occurs, you will have\n" +"\t\tto apply your changes to the newer version of the resource, or update your temporary\n" +"\t\tsaved copy to include the latest resource version." +msgstr "" +"\n" +"\t\t使用默认的编辑器修改资源.\n" +"\n" +"\t\tedit 命令允许你通过命令行直接修改 API 资源.\n" +"\t\t它会打开你在 KUBE_EDITOR 或者EDITOR 环境变量中定义的编辑器\n" +"\t\t或者回滚到 Linux vi 编辑器或者 Windows notepad.\n" +"\t\t你可以修改多个对象, 虽然每次只能修改一次. 这个命令\n" +"\t\t同时也接受文件名作为命令行参数, 尽管这些文件你指出必须是\n" +"\t\t你之前保存的资源版本.\n" +"\n" +"\t\tEditing 是通过用于获取资源的API版本完成的.\n" +"\t\t为了能通过指定的 API 版本修改, 请完全限定 resource, version 和 group.\n" +"\n" +"\t\t默认是 YAML 格式. 想在 JSON 中修改, 指定 \"-o json\".\n" +"\n" +"\t\t--windows-line-endings 命令行参数可以用来强制使用 Windows line endings,\n" +"\t\t否则会使用你操作系统的默认值.\n" +"\n" +"\t\t如果更新时发生错误,将在磁盘上创建一个临时文件\n" +"\t\t里面包含您未应用的更改. 更新资源时最常见的错误\n" +"\t\t是另一个编辑器也在服务器中修改这个资源. 当发生这种情况时, 你将\n" +"\t\t需要应用你的修改到资源的最新版本, 或者更新你被保存的临时文件\n" +"\t\t复制它并使用最新的版本." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:115 +msgid "" +"\n" +"\t\tMark node as schedulable." +msgstr "" +"\n" +"\t\t标记 node 为 schedulable." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:90 +msgid "" +"\n" +"\t\tMark node as unschedulable." +msgstr "" +"\n" +"\t\t标记 node 为 unschedulable." + +#: pkg/kubectl/cmd/completion.go:47 +msgid "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2" +msgstr "" +"\n" +"\t\tOutput shell completion code for the specified shell (bash or zsh).\n" +"\t\tThe shell code must be evaluated to provide interactive\n" +"\t\tcompletion of kubectl commands. This can be done by sourcing it from\n" +"\t\tthe .bash_profile.\n" +"\n" +"\t\tNote: this requires the bash-completion framework, which is not installed\n" +"\t\tby default on Mac. This can be installed by using homebrew:\n" +"\n" +"\t\t $ brew install bash-completion\n" +"\n" +"\t\tOnce installed, bash_completion must be evaluated. This can be done by adding the\n" +"\t\tfollowing line to the .bash_profile\n" +"\n" +"\t\t $ source $(brew --prefix)/etc/bash_completion\n" +"\n" +"\t\tNote for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2" + +#: pkg/kubectl/cmd/rollingupdate.go:45 +msgid "" +"\n" +"\t\tPerform a rolling update of the given ReplicationController.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n" +"\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" +msgstr "" +"\n" +"\t\t完成指定的 ReplicationController 的滚动升级.\n" +"\n" +"\t\tReplaces the specified replication controller with a new replication controller by updating one pod at a time to use the\n" +"\t\tnew PodTemplate. The new-controller.json must specify the same namespace as the\n" +"\t\texisting replication controller and overwrite at least one (common) label in its replicaSelector.\n" +"\n" +"\t\t![Workflow](http://kubernetes.io/images/docs/kubectl_rollingupdate.svg)" + +#: pkg/kubectl/cmd/replace.go:40 +msgid "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" +msgstr "" +"\n" +"\t\tReplace a resource by filename or stdin.\n" +"\n" +"\t\tJSON and YAML formats are accepted. If replacing an existing resource, the\n" +"\t\tcomplete resource spec must be provided. This can be obtained by\n" +"\n" +"\t\t $ kubectl get TYPE NAME -o yaml\n" + +#: pkg/kubectl/cmd/scale.go:34 +msgid "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n" +"\t\tscale is sent to the server." +msgstr "" +"\n" +"\t\tSet a new size for a Deployment, ReplicaSet, Replication Controller, or Job.\n" +"\n" +"\t\tScale also allows users to specify one or more preconditions for the scale action.\n" +"\n" +"\t\tIf --current-replicas or --resource-version is specified, it is validated before the\n" +"\t\tscale is attempted, and it is guaranteed that the precondition holds true when the\n" +"\t\tscale is sent to the server." + +#: pkg/kubectl/cmd/apply_set_last_applied.go:62 +msgid "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." +msgstr "" +"\n" +"\t\tSet the latest last-applied-configuration annotations by setting it to match the contents of a file.\n" +"\t\tThis results in the last-applied-configuration being updated as though 'kubectl apply -f ' was run,\n" +"\t\twithout updating any other parts of the object." + +#: pkg/kubectl/cmd/proxy.go:36 +msgid "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" +msgstr "" +"\n" +"\t\tTo proxy all of the kubernetes api and nothing else, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/\n" +"\n" +"\t\tTo proxy only part of the kubernetes api and also some static files:\n" +"\n" +"\t\t $ kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/api/v1/pods'.\n" +"\n" +"\t\tTo proxy the entire kubernetes api at a different root, use:\n" +"\n" +"\t\t $ kubectl proxy --api-prefix=/custom/\n" +"\n" +"\t\tThe above lets you 'curl localhost:8001/custom/api/v1/pods'" + +#: pkg/kubectl/cmd/patch.go:59 +msgid "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" +msgstr "" +"\n" +"\t\tUpdate field(s) of a resource using strategic merge patch\n" +"\n" +"\t\tJSON and YAML formats are accepted.\n" + +#: pkg/kubectl/cmd/label.go:70 +#, c-format +msgid "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used." +msgstr "" +"\n" +"\t\tUpdate the labels on a resource.\n" +"\n" +"\t\t* A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error.\n" +"\t\t* If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used." + +#: pkg/kubectl/cmd/taint.go:58 +#, c-format +msgid "" +"\n" +"\t\tUpdate the taints on one or more nodes.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." +msgstr "" +"\n" +"\t\t更新一个或者多个 node 上的 taints.\n" +"\n" +"\t\t* A taint consists of a key, value, and effect. As an argument here, it is expressed as key=value:effect.\n" +"\t\t* The key must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters.\n" +"\t\t* The value must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[2]d characters.\n" +"\t\t* The effect must be NoSchedule, PreferNoSchedule or NoExecute.\n" +"\t\t* Currently taint can only apply to node." + +#: pkg/kubectl/cmd/apply_view_last_applied.go:46 +msgid "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n" +"\t\tto change output format." +msgstr "" +"\n" +"\t\tView the latest last-applied-configuration annotations by type/name or file.\n" +"\n" +"\t\tThe default output will be printed to stdout in YAML format. One can use -o option\n" +"\t\tto change output format." + +#: pkg/kubectl/cmd/cp.go:37 +msgid "" +"\n" +"\t # !!!Important Note!!!\n" +"\t # Requires that the 'tar' binary is present in your container\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace\n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace \n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# Copy /tmp/foo from a remote pod to /tmp/bar locally\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" +msgstr "" +"\n" +"\t # !!!注意!!!\n" +"\t # 要求容器中有 'tar' 命令\n" +"\t # image. If 'tar' is not present, 'kubectl cp' will fail.\n" +"\n" +"\t # 复制本地目录 /tmp/foo_dir 到 default namespace 下的远程 pod 的 /tmp/bar_dir 路径 \n" +"\t\tkubectl cp /tmp/foo_dir :/tmp/bar_dir\n" +"\n" +" # 复制 /tmp/foo local 本地文件到指定远程 pod 的指定容器的 /tmp/bar 路径\n" +"\t\tkubectl cp /tmp/foo :/tmp/bar -c \n" +"\n" +"\t\t# 复制 /tmp/foo 本地文件到在 namespace 下的某个 pod 的 /tmp/bar 路径\n" +"\t\tkubectl cp /tmp/foo /:/tmp/bar\n" +"\n" +"\t\t# 从一个远程的 pod 的 /tmp/foo 路径复制到本地 /tmp/bar 路径\n" +"\t\tkubectl cp /:/tmp/foo /tmp/bar" + +#: pkg/kubectl/cmd/create_secret.go:205 +msgid "" +"\n" +"\t # Create a new TLS secret named tls-secret with the given key pair:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key" +msgstr "" +"\n" +"\t # 使用提供的 key pair 名称为tls-secret 的 secret:\n" +"\t kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key" + +#: pkg/kubectl/cmd/create_namespace.go:35 +msgid "" +"\n" +"\t # Create a new namespace named my-namespace\n" +"\t kubectl create namespace my-namespace" +msgstr "" +"\n" +"\t # 创建一个名称为 my-namespace 的 namespace\n" +"\t kubectl create namespace my-namespace" + +#: pkg/kubectl/cmd/create_secret.go:59 +msgid "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret" +msgstr "" +"\n" +"\t # Create a new secret named my-secret with keys for each file in folder bar\n" +"\t kubectl create secret generic my-secret --from-file=path/to/bar\n" +"\n" +"\t # Create a new secret named my-secret with specified keys instead of names on disk\n" +"\t kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub\n" +"\n" +"\t # Create a new secret named my-secret with key1=supersecret and key2=topsecret\n" +"\t kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret" + +#: pkg/kubectl/cmd/create_serviceaccount.go:35 +msgid "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" +msgstr "" +"\n" +"\t # Create a new service account named my-service-account\n" +"\t kubectl create serviceaccount my-service-account" + +#: pkg/kubectl/cmd/create_service.go:232 +msgid "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" +msgstr "" +"\n" +"\t# Create a new ExternalName service named my-ns \n" +"\tkubectl create service externalname my-ns --external-name bar.com" + +#: pkg/kubectl/cmd/create_service.go:225 +msgid "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." +msgstr "" +"\n" +"\tCreate an ExternalName service with the specified name.\n" +"\n" +"\tExternalName service references to an external DNS address instead of\n" +"\tonly pods, which will allow application authors to reference services\n" +"\tthat exist off platform, on other clusters, or locally." + +#: pkg/kubectl/cmd/help.go:30 +msgid "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." +msgstr "" +"\n" +"\tHelp provides help for any command in the application.\n" +"\tSimply type kubectl help [path to command] for full details." + +#: pkg/kubectl/cmd/create_service.go:173 +msgid "" +"\n" +" # Create a new LoadBalancer service named my-lbs\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" +msgstr "" +"\n" +" # 创建一个名称为 my-lbs 的 LoadBalancer service\n" +" kubectl create service loadbalancer my-lbs --tcp=5678:8080" + +#: pkg/kubectl/cmd/create_service.go:53 +msgid "" +"\n" +" # Create a new clusterIP service named my-cs\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # Create a new clusterIP service named my-cs (in headless mode)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" +msgstr "" +"\n" +" # 创建一个名称为 my-cs 的 clusterIP service\n" +" kubectl create service clusterip my-cs --tcp=5678:8080\n" +"\n" +" # 创建一个名称为 my-cs 的 clusterIP service (在 headless 模式)\n" +" kubectl create service clusterip my-cs --clusterip=\"None\"" + +#: pkg/kubectl/cmd/create_deployment.go:36 +msgid "" +"\n" +" # Create a new deployment named my-dep that runs the busybox image.\n" +" kubectl create deployment my-dep --image=busybox" +msgstr "" +"\n" +" # 创建一个名称为 my-dep 的 deployment 并运行 busybox image.\n" +" kubectl create deployment my-dep --image=busybox" + +#: pkg/kubectl/cmd/create_service.go:116 +msgid "" +"\n" +" # Create a new nodeport service named my-ns\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" +msgstr "" +"\n" +" # 创建一个名称为 my-ns 的 nodeport service\n" +" kubectl create service nodeport my-ns --tcp=5678:8080" + +#: pkg/kubectl/cmd/clusterinfo_dump.go:62 +msgid "" +"\n" +" # Dump current cluster state to stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # Dump current cluster state to /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # Dump all namespaces to stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # Dump a set of namespaces to /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state" +msgstr "" +"\n" +" # 导出当前的集群状态信息到 stdout\n" +" kubectl cluster-info dump\n" +"\n" +" # 导出当前的集群状态 /path/to/cluster-state\n" +" kubectl cluster-info dump --output-directory=/path/to/cluster-state\n" +"\n" +" # 导出所有分区到 stdout\n" +" kubectl cluster-info dump --all-namespaces\n" +"\n" +" # 导出一组分区到 /path/to/cluster-state\n" +" kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state" + +#: pkg/kubectl/cmd/annotate.go:78 +msgid "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n" +" # If the same annotation is set multiple times, only the last value will be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n" +"\n" +" # Update pod 'foo' by removing an annotation named 'description' if it exists.\n" +" # Does not require the --overwrite flag.\n" +" kubectl annotate pods foo description-" +msgstr "" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my frontend'.\n" +" # If the same annotation is set multiple times, only the last value will be applied\n" +" kubectl annotate pods foo description='my frontend'\n" +"\n" +" # Update a pod identified by type and name in \"pod.json\"\n" +" kubectl annotate -f pod.json description='my frontend'\n" +"\n" +" # Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value.\n" +" kubectl annotate --overwrite pods foo description='my frontend running nginx'\n" +"\n" +" # Update all pods in the namespace\n" +" kubectl annotate pods --all description='my frontend running nginx'\n" +"\n" +" # Update pod 'foo' only if the resource is unchanged from version 1.\n" +" kubectl annotate pods foo description='my frontend running nginx' --resource-version=1\n" +"\n" +" # 更新名称为 'foo' 的 pod, 删除一个名称为 'description' 的 annotation 如果它存在. \n" +" # 不要求使用 --overwrite flag.\n" +" kubectl annotate pods foo description-" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_service.go:170 +msgid "" +"\n" +" Create a LoadBalancer service with the specified name." +msgstr "" +"\n" +" 使用一个指定的名称创建一个 LoadBalancer service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_service.go:50 +msgid "" +"\n" +" Create a clusterIP service with the specified name." +msgstr "" +"\n" +" 使用一个指定的名称创建一个 clusterIP service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:33 +msgid "" +"\n" +" Create a deployment with the specified name." +msgstr "" +"\n" +" 使用一个指定的名称创建一个 deployment." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_service.go:113 +msgid "" +"\n" +" Create a nodeport service with the specified name." +msgstr "" +"\n" +" 使用一个指定的名称创建一个 nodeport service." + +#: pkg/kubectl/cmd/clusterinfo_dump.go:53 +msgid "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n" +" based on namespace and pod name." +msgstr "" +"\n" +" Dumps cluster info out suitable for debugging and diagnosing cluster problems. By default, dumps everything to\n" +" stdout. You can optionally specify a directory with --output-directory. If you specify a directory, kubernetes will\n" +" build a set of files in that directory. By default only dumps things in the 'kube-system' namespace, but you can\n" +" switch to a different namespace with the --namespaces flag, or specify --all-namespaces to dump all namespaces.\n" +"\n" +" The command also dumps the logs of all of the pods in the cluster, these logs are dumped into different directories\n" +" based on namespace and pod name." + +#: pkg/kubectl/cmd/clusterinfo.go:37 +msgid "" +"\n" +" Display addresses of the master and services with label kubernetes.io/cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'." +msgstr "" +"\n" +" Display addresses of the master and services with label kubernetes.io/cluster-service=true\n" +" To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L61 +#: pkg/kubectl/cmd/create_quota.go:62 +msgid "A comma-delimited set of quota scopes that must all match each object tracked by the quota." +msgstr "A comma-delimited set of quota scopes that must all match each object tracked by the quota." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L60 +#: pkg/kubectl/cmd/create_quota.go:61 +msgid "A comma-delimited set of resource=quantity pairs that define a hard limit." +msgstr "A comma-delimited set of resource=quantity pairs that define a hard limit." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L63 +#: pkg/kubectl/cmd/create_pdb.go:64 +msgid "A label selector to use for this budget. Only equality-based selector requirements are supported." +msgstr "A label selector to use for this budget. Only equality-based selector requirements are supported." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L106 +#: pkg/kubectl/cmd/expose.go:104 +msgid "A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)" +msgstr "A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L136 +#: pkg/kubectl/cmd/run.go:139 +msgid "A schedule in the Cron format the job should be run with." +msgstr "A schedule in the Cron format the job should be run with." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L111 +#: pkg/kubectl/cmd/expose.go:109 +msgid "Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP." +msgstr "Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L119 +#: pkg/kubectl/cmd/expose.go:110 pkg/kubectl/cmd/run.go:122 +msgid "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field." +msgstr "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L134 +#: pkg/kubectl/cmd/run.go:137 +msgid "An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true." +msgstr "An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true." + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "通过文件名或标准输入流(stdin)对资源进行配置" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L71 +#: pkg/kubectl/cmd/certificates.go:72 +msgid "Approve a certificate signing request" +msgstr "同意一个自签证书请求" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L81 +#: pkg/kubectl/cmd/create_service.go:82 +msgid "Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing)." +msgstr "Assign your own ClusterIP or set to 'None' for a 'headless' service (no loadbalancing)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/attach.go#L64 +#: pkg/kubectl/cmd/attach.go:70 +msgid "Attach to a running container" +msgstr "Attach 到一个运行中的 container" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L55 +#: pkg/kubectl/cmd/autoscale.go:56 +msgid "Auto-scale a Deployment, ReplicaSet, or ReplicationController" +msgstr "自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L115 +#: pkg/kubectl/cmd/expose.go:113 +msgid "ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service." +msgstr "ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create a headless service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L55 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:56 +msgid "ClusterRole this ClusterRoleBinding should reference" +msgstr "ClusterRoleBinding 应该指定 ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L55 +#: pkg/kubectl/cmd/create_rolebinding.go:56 +msgid "ClusterRole this RoleBinding should reference" +msgstr "RoleBinding 应该指定 ClusterRole" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L101 +#: pkg/kubectl/cmd/rollingupdate.go:102 +msgid "Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod" +msgstr "Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert.go#L67 +#: pkg/kubectl/cmd/convert.go:68 +msgid "Convert config files between different API versions" +msgstr "在不同的 API versions 转换配置文件" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cp.go#L64 +#: pkg/kubectl/cmd/cp.go:65 +msgid "Copy files and directories to and from containers." +msgstr "复制 files 和 directories 到 containers 和从容器中复制 files 和 directories." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_clusterrolebinding.go#L43 +#: pkg/kubectl/cmd/create_clusterrolebinding.go:44 +msgid "Create a ClusterRoleBinding for a particular ClusterRole" +msgstr "为一个指定的 ClusterRole 创建一个 ClusterRoleBinding" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L181 +#: pkg/kubectl/cmd/create_service.go:182 +msgid "Create a LoadBalancer service." +msgstr "创建一个 LoadBalancer service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L124 +#: pkg/kubectl/cmd/create_service.go:125 +msgid "Create a NodePort service." +msgstr "创建一个 NodePort service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L43 +#: pkg/kubectl/cmd/create_rolebinding.go:44 +msgid "Create a RoleBinding for a particular Role or ClusterRole" +msgstr "为一个指定的 Role 或者 ClusterRole创建一个 RoleBinding" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L214 +#: pkg/kubectl/cmd/create_secret.go:214 +msgid "Create a TLS secret" +msgstr "创建一个 TLS secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L68 +#: pkg/kubectl/cmd/create_service.go:69 +msgid "Create a clusterIP service." +msgstr "创建一个 clusterIP service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_configmap.go#L59 +#: pkg/kubectl/cmd/create_configmap.go:60 +msgid "Create a configmap from a local file, directory or literal value" +msgstr "从本地 file, directory 或者 literal value 创建一个 configmap" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_deployment.go#L44 +#: pkg/kubectl/cmd/create_deployment.go:46 +msgid "Create a deployment with the specified name." +msgstr "创建一个指定名称的 deployment." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_namespace.go#L44 +#: pkg/kubectl/cmd/create_namespace.go:45 +msgid "Create a namespace with the specified name" +msgstr "创建一个指定名称的 namespace" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L49 +#: pkg/kubectl/cmd/create_pdb.go:50 +msgid "Create a pod disruption budget with the specified name." +msgstr "创建一个指定名称的 pod disruption budget." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_quota.go#L47 +#: pkg/kubectl/cmd/create_quota.go:48 +msgid "Create a quota with the specified name." +msgstr "创建一个指定名称的 quota." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create.go#L56 +#: pkg/kubectl/cmd/create.go:63 +msgid "Create a resource by filename or stdin" +msgstr "通过文件名或者标准输入流(stdin)创建一个资源" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L143 +#: pkg/kubectl/cmd/create_secret.go:144 +msgid "Create a secret for use with a Docker registry" +msgstr "创建一个给 Docker registry 使用的 secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L73 +#: pkg/kubectl/cmd/create_secret.go:74 +msgid "Create a secret from a local file, directory or literal value" +msgstr "从本地 file, directory 或者 literal value 创建一个 secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L34 +#: pkg/kubectl/cmd/create_secret.go:35 +msgid "Create a secret using specified subcommand" +msgstr "使用指定的 subcommand 创建一个 secret" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_serviceaccount.go#L44 +#: pkg/kubectl/cmd/create_serviceaccount.go:45 +msgid "Create a service account with the specified name" +msgstr "创建一个指定名称的 service account" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L36 +#: pkg/kubectl/cmd/create_service.go:37 +msgid "Create a service using specified subcommand." +msgstr "使用指定的 subcommand 创建一个 service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L240 +#: pkg/kubectl/cmd/create_service.go:241 +msgid "Create an ExternalName service." +msgstr "Create an ExternalName service." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/delete.go#L130 +#: pkg/kubectl/cmd/delete.go:132 +msgid "Delete resources by filenames, stdin, resources and names, or by resources and label selector" +msgstr "Delete resources by filenames, stdin, resources and names, or by resources and label selector" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_cluster.go#L38 +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "删除 kubeconfig 文件中指定的集群" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/delete_context.go#L38 +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "删除 kubeconfig 文件中指定的 context" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L121 +#: pkg/kubectl/cmd/certificates.go:122 +msgid "Deny a certificate signing request" +msgstr "拒绝一个自签证书请求" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/stop.go#L58 +#: pkg/kubectl/cmd/stop.go:59 +msgid "Deprecated: Gracefully shut down a resource by name or filename" +msgstr "Deprecated: Gracefully shut down a resource by name or filename" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_contexts.go#L62 +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "描述一个或多个 contexts" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 +#: pkg/kubectl/cmd/top_node.go:78 +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "显示 nodes 的 Resource (CPU/Memory) 使用" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 +#: pkg/kubectl/cmd/top_pod.go:80 +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "显示 pods 的 Resource (CPU/Memory) 使用" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 +#: pkg/kubectl/cmd/top.go:44 +msgid "Display Resource (CPU/Memory) usage." +msgstr "显示 Resource (CPU/Memory) 使用." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 +#: pkg/kubectl/cmd/clusterinfo.go:51 +msgid "Display cluster info" +msgstr "显示集群信息" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/get_clusters.go#L40 +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "显示 kubeconfig 文件中定义的集群" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/view.go#L64 +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "显示合并的 kubeconfig 配置或一个指定的 kubeconfig 文件" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/get.go#L107 +#: pkg/kubectl/cmd/get.go:111 +msgid "Display one or many resources" +msgstr "显示一个或更多 resources" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/current_context.go#L48 +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "显示当前的 context" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/explain.go#L50 +#: pkg/kubectl/cmd/explain.go:51 +msgid "Documentation of resources" +msgstr "查看资源的文档" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L176 +#: pkg/kubectl/cmd/drain.go:178 +msgid "Drain node in preparation for maintenance" +msgstr "Drain node in preparation for maintenance" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L37 +#: pkg/kubectl/cmd/clusterinfo_dump.go:39 +msgid "Dump lots of relevant info for debugging and diagnosis" +msgstr "Dump lots of relevant info for debugging and diagnosis" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L100 +#: pkg/kubectl/cmd/edit.go:110 +msgid "Edit a resource on the server" +msgstr "在服务器上编辑一个资源" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L159 +#: pkg/kubectl/cmd/create_secret.go:160 +msgid "Email for Docker registry" +msgstr "Email for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/exec.go#L68 +#: pkg/kubectl/cmd/exec.go:69 +msgid "Execute a command in a container" +msgstr "在一个 container 中执行一个命令" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L102 +#: pkg/kubectl/cmd/rollingupdate.go:103 +msgid "Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise." +msgstr "Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/portforward.go#L75 +#: pkg/kubectl/cmd/portforward.go:76 +msgid "Forward one or more local ports to a pod" +msgstr "Forward one or more local ports to a pod" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/help.go#L36 +#: pkg/kubectl/cmd/help.go:37 +msgid "Help about any command" +msgstr "Help about any command" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L105 +#: pkg/kubectl/cmd/expose.go:103 +msgid "IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific)." +msgstr "IP to assign to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific)." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L114 +#: pkg/kubectl/cmd/expose.go:112 +msgid "If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'" +msgstr "If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/annotate.go#L135 +#: pkg/kubectl/cmd/annotate.go:136 +msgid "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." +msgstr "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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L132 +#: pkg/kubectl/cmd/label.go:134 +msgid "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." +msgstr "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." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L98 +#: pkg/kubectl/cmd/rollingupdate.go:99 +msgid "Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f" +msgstr "Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout.go#L46 +#: pkg/kubectl/cmd/rollout/rollout.go:47 +msgid "Manage a deployment rollout" +msgstr "管理一个 deployment 的 rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L127 +#: pkg/kubectl/cmd/drain.go:128 +msgid "Mark node as schedulable" +msgstr "标记 node 为 schedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/drain.go#L102 +#: pkg/kubectl/cmd/drain.go:103 +msgid "Mark node as unschedulable" +msgstr "标记 node 为 unschedulable" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_pause.go#L73 +#: pkg/kubectl/cmd/rollout/rollout_pause.go:74 +msgid "Mark the provided resource as paused" +msgstr "标记提供的 resource 为中止状态" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/certificates.go#L35 +#: pkg/kubectl/cmd/certificates.go:36 +msgid "Modify certificate resources." +msgstr "修改 certificate 资源." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/config.go#L39 +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "修改 kubeconfig 文件" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L110 +#: pkg/kubectl/cmd/expose.go:108 +msgid "Name or number for the port on the container that the service should direct traffic to. Optional." +msgstr "Name or number for the port on the container that the service should direct traffic to. Optional." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L108 +#: pkg/kubectl/cmd/logs.go:113 +msgid "Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used." +msgstr "Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/completion.go#L97 +#: pkg/kubectl/cmd/completion.go:104 +msgid "Output shell completion code for the specified shell (bash or zsh)" +msgstr "Output shell completion code for the specified shell (bash or zsh)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/edit.go#L115 +#: pkg/kubectl/cmd/convert.go:85 +msgid "Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)" +msgstr "Output the formatted object with the given group version (for ex: 'extensions/v1beta1').)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L157 +#: pkg/kubectl/cmd/create_secret.go:158 +msgid "Password for Docker registry authentication" +msgstr "Password for Docker registry authentication" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L226 +#: pkg/kubectl/cmd/create_secret.go:226 +msgid "Path to PEM encoded public key certificate." +msgstr "Path to PEM encoded public key certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L227 +#: pkg/kubectl/cmd/create_secret.go:227 +msgid "Path to private key associated with given certificate." +msgstr "Path to private key associated with given certificate." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L84 +#: pkg/kubectl/cmd/rollingupdate.go:85 +msgid "Perform a rolling update of the given ReplicationController" +msgstr "完成指定的 ReplicationController 的滚动升级" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L82 +#: pkg/kubectl/cmd/scale.go:83 +msgid "Precondition for resource version. Requires that the current resource version match this value in order to scale." +msgstr "Precondition for resource version. Requires that the current resource version match this value in order to scale." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/version.go#L39 +#: pkg/kubectl/cmd/version.go:40 +msgid "Print the client and server version information" +msgstr "输出 client 和 server 的版本信息" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/options.go#L37 +#: pkg/kubectl/cmd/options.go:38 +msgid "Print the list of flags inherited by all commands" +msgstr "输出所有命令的层级关系" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/logs.go#L86 +#: pkg/kubectl/cmd/logs.go:93 +msgid "Print the logs for a container in a pod" +msgstr "输出容器在 pod 中的日志" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/replace.go#L70 +#: pkg/kubectl/cmd/replace.go:71 +msgid "Replace a resource by filename or stdin" +msgstr "通过 filename 或者 stdin替换一个资源" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_resume.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_resume.go:72 +msgid "Resume a paused resource" +msgstr "继续一个停止的 resource" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_rolebinding.go#L56 +#: pkg/kubectl/cmd/create_rolebinding.go:57 +msgid "Role this RoleBinding should reference" +msgstr "RoleBinding 的 Role 应该被引用" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L94 +#: pkg/kubectl/cmd/run.go:97 +msgid "Run a particular image on the cluster" +msgstr "在集群中运行一个指定的镜像" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/proxy.go#L68 +#: pkg/kubectl/cmd/proxy.go:69 +msgid "Run a proxy to the Kubernetes API server" +msgstr "运行一个 proxy 到 Kubernetes API server" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L161 +#: pkg/kubectl/cmd/create_secret.go:161 +msgid "Server location for Docker registry" +msgstr "Server location for Docker registry" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/scale.go#L71 +#: pkg/kubectl/cmd/scale.go:71 +msgid "Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job" +msgstr "为 Deployment, ReplicaSet, Replication Controller 或者 Job 设置一个新的副本数量" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set.go#L37 +#: pkg/kubectl/cmd/set/set.go:38 +msgid "Set specific features on objects" +msgstr "为 objects 设置一个指定的特征" + +#: pkg/kubectl/cmd/apply_set_last_applied.go:83 +msgid "Set the last-applied-configuration annotation on a live object to match the contents of a file." +msgstr "Set the last-applied-configuration annotation on a live object to match the contents of a file." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_selector.go#L81 +#: pkg/kubectl/cmd/set/set_selector.go:82 +msgid "Set the selector on a resource" +msgstr "设置 resource 的 selector" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_cluster.go#L67 +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "设置 kubeconfig 文件中的一个集群条目" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_context.go#L57 +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "设置 kubeconfig 文件中的一个 context 条目" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/create_authinfo.go#L103 +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "设置 kubeconfig 文件中的一个用户条目" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/set.go#L59 +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "设置 kubeconfig 文件中的一个单个值" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/use_context.go#L48 +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "设置 kubeconfig 文件中的当前上下文" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/describe.go#L80 +#: pkg/kubectl/cmd/describe.go:86 +msgid "Show details of a specific resource or group of resources" +msgstr "显示一个指定 resource 或者 group 的 resources 详情" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_status.go#L57 +#: pkg/kubectl/cmd/rollout/rollout_status.go:58 +msgid "Show the status of the rollout" +msgstr "显示 rollout 的状态" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L108 +#: pkg/kubectl/cmd/expose.go:106 +msgid "Synonym for --target-port" +msgstr "Synonym for --target-port" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L87 +#: pkg/kubectl/cmd/expose.go:88 +msgid "Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service" +msgstr "使用 replication controller, service, deployment 或者 pod 并暴露它作为一个 新的 Kubernetes Service" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L114 +#: pkg/kubectl/cmd/run.go:117 +msgid "The image for the container to run." +msgstr "指定容器要运行的镜像." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L116 +#: pkg/kubectl/cmd/run.go:119 +msgid "The image pull policy for the container. If left empty, this value will not be specified by the client and defaulted by the server" +msgstr "容器的镜像拉取策略. 如果为空, 这个值将不会 被 client 指定且使用 server 端的默认值" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollingupdate.go#L100 +#: pkg/kubectl/cmd/rollingupdate.go:101 +msgid "The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise" +msgstr "这个 key 使用有区别在两个不同的 controllers, 默认 'deployment'. 只有当 --image 指定值, 否则忽略" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_pdb.go#L62 +#: pkg/kubectl/cmd/create_pdb.go:63 +msgid "The minimum number or percentage of available pods this budget requires." +msgstr "最小数量百分比可用的 pods 作为 budget 要求." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L113 +#: pkg/kubectl/cmd/expose.go:111 +msgid "The name for the newly created object." +msgstr "名称为最新创建的对象." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L71 +#: pkg/kubectl/cmd/autoscale.go:72 +msgid "The name for the newly created object. If not specified, the name of the input resource will be used." +msgstr "名称为最新创建的对象. 如果没有指定, 输入资源的 名称即将被使用." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L113 +#: pkg/kubectl/cmd/run.go:116 +msgid "The name of the API generator to use, see http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators for a list." +msgstr "使用 API generator 的名字, 在 http://kubernetes.io/docs/user-guide/kubectl-conventions/#generators 查看列表." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/autoscale.go#L66 +#: pkg/kubectl/cmd/autoscale.go:67 +msgid "The name of the API generator to use. Currently there is only 1 generator." +msgstr "使用 API generator 的名字. 目前只有 1 个 generator." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L98 +#: pkg/kubectl/cmd/expose.go:99 +msgid "The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'." +msgstr "使用 generator 的名称. 这里有 2 个 generators: 'service/v1' 和 'service/v2'. 为一个不同地方是服务端口在 v1 的情况下叫 'default', 如果在 v2 中没有指定名称. 默认的名称是 'service/v2'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L133 +#: pkg/kubectl/cmd/run.go:136 +msgid "The name of the generator to use for creating a service. Only used if --expose is true" +msgstr "使用 gnerator 的名称创建一个 service. 只有在 --expose 为 true 的时候使用" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L99 +#: pkg/kubectl/cmd/expose.go:100 +msgid "The network protocol for the service to be created. Default is 'TCP'." +msgstr "创建 service 的时候伴随着一个网络协议被创建. 默认是 'TCP'." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L100 +#: pkg/kubectl/cmd/expose.go:101 +msgid "The port that the service should serve on. Copied from the resource being exposed, if unspecified" +msgstr "服务的端口应该被指定. 如果没有指定, 从被创建的资源中复制" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L121 +#: pkg/kubectl/cmd/run.go:124 +msgid "The port that this container exposes. If --expose is true, this is also the port used by the service that is created." +msgstr "The port that this container exposes. If --expose is true, this is also the port used by the service that is created." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L131 +#: pkg/kubectl/cmd/run.go:134 +msgid "The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges." +msgstr "The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L130 +#: pkg/kubectl/cmd/run.go:133 +msgid "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." +msgstr "资源为 container 请求 requests . 例如, 'cpu=100m,memory=256Mi'. 注意服务端组件也许会赋予 requests, 这决定于服务器端配置, 比如 limit ranges." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/run.go#L128 +#: pkg/kubectl/cmd/run.go:131 +msgid "The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created, if set to 'OnFailure' a job is created, if set to 'Never', a regular pod is created. For the latter two --replicas must be 1. Default 'Always', for CronJobs ` + "`" + `Never` + "`" + `." +msgstr "这个 Pod 的 restart policy. Legal values [Always, OnFailure, Never]. 如果设置为 'Always' 一个 deployment 被创建, 如果设置为 ’OnFailure' 一个 job 被创建, 如果设置为 'Never', 一个普通的 pod 被创建. 对于后面两个 --replicas 必须为 1. 默认 'Always', 为 CronJobs 设置为 ` + "`" + `Never` + "`" + `." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L87 +#: pkg/kubectl/cmd/create_secret.go:88 +msgid "The type of secret to create" +msgstr "创建 secret 类型资源" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/expose.go#L101 +#: pkg/kubectl/cmd/expose.go:102 +msgid "Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'." +msgstr "对于服务的类型: ClusterIP, NodePort, 或者 LoadBalancer. 默认是 'ClusterIP’." + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_undo.go#L71 +#: pkg/kubectl/cmd/rollout/rollout_undo.go:72 +msgid "Undo a previous rollout" +msgstr "撤销上一次的 rollout" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/config/unset.go#L47 +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "取消设置 kubeconfig 文件中的一个单个值" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/patch.go#L91 +#: pkg/kubectl/cmd/patch.go:96 +msgid "Update field(s) of a resource using strategic merge patch" +msgstr "使用 strategic merge patch 更新一个资源的 field(s)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_image.go#L94 +#: pkg/kubectl/cmd/set/set_image.go:95 +msgid "Update image of a pod template" +msgstr "更新一个 pod template 的镜像" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/set/set_resources.go#L101 +#: pkg/kubectl/cmd/set/set_resources.go:102 +msgid "Update resource requests/limits on objects with pod templates" +msgstr "在对象的 pod templates 上更新资源的 requests/limits" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "更新一个资源的注解" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/label.go#L109 +#: pkg/kubectl/cmd/label.go:114 +msgid "Update the labels on a resource" +msgstr "更新在这个资源上的 labels" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/taint.go#L88 +#: pkg/kubectl/cmd/taint.go:87 +msgid "Update the taints on one or more nodes" +msgstr "更新一个或者多个 node 上的 taints" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_secret.go#L155 +#: pkg/kubectl/cmd/create_secret.go:156 +msgid "Username for Docker registry authentication" +msgstr "Username 为 Docker registry authentication" + +#: pkg/kubectl/cmd/apply_view_last_applied.go:64 +msgid "View latest last-applied-configuration annotations of a resource/object" +msgstr "显示最后的 resource/object 的 last-applied-configuration annotations" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/rollout/rollout_history.go#L51 +#: pkg/kubectl/cmd/rollout/rollout_history.go:52 +msgid "View rollout history" +msgstr "显示 rollout 历史" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo_dump.go#L45 +#: pkg/kubectl/cmd/clusterinfo_dump.go:46 +msgid "Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory" +msgstr "输出到 files. 如果是 empty or '-' 使用 stdout, 否则创建一个 目录层级在那个目录" + +#: pkg/kubectl/cmd/run_test.go:85 +msgid "dummy restart flag)" +msgstr "dummy restart flag)" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/create_service.go#L253 +#: pkg/kubectl/cmd/create_service.go:254 +msgid "external name of service" +msgstr "服务的外部名称" + +# https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cmd.go#L217 +#: pkg/kubectl/cmd/cmd.go:227 +msgid "kubectl controls the Kubernetes cluster manager" +msgstr "kubectl 控制 Kubernetes cluster 管理" + +#~ msgid "watch is only supported on individual resources and resource collections - %d resources were found" +#~ msgid_plural "watch is only supported on individual resources and resource collections - %d resources were found" +#~ msgstr[0] "watch 仅支持单独的资源或者资源集合 - 找到了 %d 个资源watch is only supported on individual resources and resource collections - %d resource was found" +#~ msgstr[1] "watch 仅支持单独的资源或者资源集合 - 找到了 %d 个资源watch is only supported on individual resources and resource collections - %d resources were found" +`) + +func translationsKubectlZh_cnLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlZh_cnLc_messagesK8sPo, nil +} + +func translationsKubectlZh_cnLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlZh_cnLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/zh_CN/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlZh_twLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x11\x00\x00\x00\x1c\x00\x00\x00\xa4\x00\x00\x00\x17\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00\x88\x01\x00\x008\x00\x00\x00\x89\x01\x00\x000\x00\x00\x00\xc2\x01\x00\x000\x00\x00\x00\xf3\x01\x00\x00\x1d\x00\x00\x00$\x02\x00\x00*\x00\x00\x00B\x02\x00\x00A\x00\x00\x00m\x02\x00\x00\x1c\x00\x00\x00\xaf\x02\x00\x00\x17\x00\x00\x00\xcc\x02\x00\x00\"\x00\x00\x00\xe4\x02\x00\x00\"\x00\x00\x00\a\x03\x00\x00\x1f\x00\x00\x00*\x03\x00\x00-\x00\x00\x00J\x03\x00\x00-\x00\x00\x00x\x03\x00\x00/\x00\x00\x00\xa6\x03\x00\x00$\x00\x00\x00\xd6\x03\x00\x00\xc5\x00\x00\x00\xfb\x03\x00\x00\x98\x01\x00\x00\xc1\x04\x00\x00=\x00\x00\x00Z\x06\x00\x003\x00\x00\x00\x98\x06\x00\x00,\x00\x00\x00\xcc\x06\x00\x00\x1d\x00\x00\x00\xf9\x06\x00\x003\x00\x00\x00\x17\a\x00\x00E\x00\x00\x00K\a\x00\x00\x17\x00\x00\x00\x91\a\x00\x00\x18\x00\x00\x00\xa9\a\x00\x009\x00\x00\x00\xc2\a\x00\x003\x00\x00\x00\xfc\a\x00\x003\x00\x00\x000\b\x00\x00'\x00\x00\x00d\b\x00\x00,\x00\x00\x00\x8c\b\x00\x00-\x00\x00\x00\xb9\b\x00\x00(\x00\x00\x00\xe7\b\x00\x00\x8f\x00\x00\x00\x10\t\x00\x00\x01\x00\x00\x00\n\x00\x00\x00\v\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\a\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\f\x00\x00\x00\x05\x00\x00\x00\r\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00Apply a configuration to a resource by filename or stdin\x00Delete the specified cluster from the kubeconfig\x00Delete the specified context from the kubeconfig\x00Describe one or many contexts\x00Display clusters defined in the kubeconfig\x00Display merged kubeconfig settings or a specified kubeconfig file\x00Displays the current-context\x00Modify kubeconfig files\x00Sets a cluster entry in kubeconfig\x00Sets a context entry in kubeconfig\x00Sets a user entry in kubeconfig\x00Sets an individual value in a kubeconfig file\x00Sets the current-context in a kubeconfig file\x00Unsets an individual value in a kubeconfig file\x00Update the annotations on a resource\x00watch is only supported on individual resources and resource collections - %d resources were found\x00watch is only supported on individual resources and resource collections - %d resources were found\x00Project-Id-Version: hello-world\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2017-05-26 08:28+0800\nPO-Revision-Date: 2017-06-02 09:13+0800\nLast-Translator: William Chang \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 2.0.2\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=2; plural=(n > 1);\nLanguage: zh\n\x00\u901a\u904e\u6a94\u6848\u540d\u6216\u6a19\u6e96\u8f38\u5165\u6d41(stdin)\u5c0d\u8cc7\u6e90\u9032\u884c\u914d\u7f6e\x00\u522a\u9664 kubeconfig \u6a94\u6848\u4e2d\u6307\u5b9a\u7684\u53e2\u96c6(cluster)\x00\u522a\u9664 kubeconfig \u6a94\u6848\u4e2d\u6307\u5b9a\u7684 context\x00\u63cf\u8ff0\u4e00\u500b\u6216\u591a\u500b context\x00\u986f\u793a kubeconfig \u6a94\u6848\u4e2d\u5b9a\u7fa9\u7684\u53e2\u96c6(cluster)\x00\u986f\u793a\u5408\u4f75\u7684 kubeconfig \u914d\u7f6e\u6216\u4e00\u500b\u6307\u5b9a\u7684 kubeconfig \u6a94\u6848\x00\u986f\u793a\u76ee\u524d\u7684 context\x00\u4fee\u6539 kubeconfig \u6a94\u6848\x00\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u4e00\u500b\u53e2\u96c6(cluster)\u689d\u76ee\x00\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u4e00\u500b context \u689d\u76ee\x00\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u4e00\u500b\u4f7f\u7528\u8005\u689d\u76ee\x00\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u4e00\u500b\u503c\x00\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u76ee\u524d context\x00\u53d6\u6d88\u8a2d\u7f6e kubeconfig \u6a94\u6848\u4e2d\u7684\u4e00\u500b\u503c\x00\u66f4\u65b0\u4e00\u500b\u8cc7\u6e90\u7684\u6ce8\u89e3(annotations)\x00\u4e00\u6b21\u53ea\u80fd watch \u4e00\u500b\u8cc7\u6e90\u6216\u8cc7\u6599\u96c6\u5408 - \u627e\u5230\u4e86 %d \u500b\u8cc7\u6e90\x00\u4e00\u6b21\u53ea\u80fd watch \u4e00\u500b\u8cc7\u6e90\u6216\u8cc7\u6599\u96c6\u5408 - \u627e\u5230\u4e86 %d \u500b\u8cc7\u6e90\x00") + +func translationsKubectlZh_twLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsKubectlZh_twLc_messagesK8sMo, nil +} + +func translationsKubectlZh_twLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsKubectlZh_twLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/zh_TW/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsKubectlZh_twLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2017 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR warmchang@outlook.com, 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: hello-world\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-26 08:28+0800\n" +"PO-Revision-Date: 2017-06-02 09:13+0800\n" +"Last-Translator: William Chang \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language: zh\n" + +#: pkg/kubectl/cmd/apply.go:104 +msgid "Apply a configuration to a resource by filename or stdin" +msgstr "通過檔案名或標準輸入流(stdin)對資源進行配置" + +#: pkg/kubectl/cmd/config/delete_cluster.go:39 +msgid "Delete the specified cluster from the kubeconfig" +msgstr "刪除 kubeconfig 檔案中指定的叢集(cluster)" + +#: pkg/kubectl/cmd/config/delete_context.go:39 +msgid "Delete the specified context from the kubeconfig" +msgstr "刪除 kubeconfig 檔案中指定的 context" + +#: pkg/kubectl/cmd/config/get_contexts.go:64 +msgid "Describe one or many contexts" +msgstr "描述一個或多個 context" + +#: pkg/kubectl/cmd/config/get_clusters.go:41 +msgid "Display clusters defined in the kubeconfig" +msgstr "顯示 kubeconfig 檔案中定義的叢集(cluster)" + +#: pkg/kubectl/cmd/config/view.go:67 +msgid "Display merged kubeconfig settings or a specified kubeconfig file" +msgstr "顯示合併的 kubeconfig 配置或一個指定的 kubeconfig 檔案" + +#: pkg/kubectl/cmd/config/current_context.go:49 +msgid "Displays the current-context" +msgstr "顯示目前的 context" + +#: pkg/kubectl/cmd/config/config.go:40 +msgid "Modify kubeconfig files" +msgstr "修改 kubeconfig 檔案" + +#: pkg/kubectl/cmd/config/create_cluster.go:68 +msgid "Sets a cluster entry in kubeconfig" +msgstr "設置 kubeconfig 檔案中的一個叢集(cluster)條目" + +#: pkg/kubectl/cmd/config/create_context.go:58 +msgid "Sets a context entry in kubeconfig" +msgstr "設置 kubeconfig 檔案中的一個 context 條目" + +#: pkg/kubectl/cmd/config/create_authinfo.go:104 +msgid "Sets a user entry in kubeconfig" +msgstr "設置 kubeconfig 檔案中的一個使用者條目" + +#: pkg/kubectl/cmd/config/set.go:60 +msgid "Sets an individual value in a kubeconfig file" +msgstr "設置 kubeconfig 檔案中的一個值" + +#: pkg/kubectl/cmd/config/use_context.go:49 +msgid "Sets the current-context in a kubeconfig file" +msgstr "設置 kubeconfig 檔案中的目前 context" + +#: pkg/kubectl/cmd/config/unset.go:48 +msgid "Unsets an individual value in a kubeconfig file" +msgstr "取消設置 kubeconfig 檔案中的一個值" + +#: pkg/kubectl/cmd/annotate.go:116 +msgid "Update the annotations on a resource" +msgstr "更新一個資源的注解(annotations)" + +msgid "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgid_plural "" +"watch is only supported on individual resources and resource collections - " +"%d resources were found" +msgstr[0] "一次只能 watch 一個資源或資料集合 - 找到了 %d 個資源" +msgstr[1] "一次只能 watch 一個資源或資料集合 - 找到了 %d 個資源" +`) + +func translationsKubectlZh_twLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsKubectlZh_twLc_messagesK8sPo, nil +} + +func translationsKubectlZh_twLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsKubectlZh_twLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/kubectl/zh_TW/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsTestDefaultLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x00\x004\x00\x00\x00\x05\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x17\x00\x00\x00a\x00\x00\x00\v\x00\x00\x00y\x00\x00\x00\xac\x01\x00\x00\x85\x00\x00\x00%\x00\x00\x002\x02\x00\x00\x03\x00\x00\x00X\x02\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00test_plural\x00test_plural\x00test_string\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2016-12-13 21:35-0800\nLast-Translator: Brendan Burns \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 1.6.10\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=2; plural=(n != 1);\nLanguage: en\n\x00there was %d item\x00there were %d items\x00foo\x00") + +func translationsTestDefaultLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsTestDefaultLc_messagesK8sMo, nil +} + +func translationsTestDefaultLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsTestDefaultLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/test/default/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsTestDefaultLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2016 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR brendan.d.burns@gmail.com, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2016-12-13 21:35-0800\n" +"Last-Translator: Brendan Burns \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: en\n" + +msgid "test_plural" +msgid_plural "test_plural" +msgstr[0] "there was %d item" +msgstr[1] "there were %d items" + +msgid "test_string" +msgstr "foo" +`) + +func translationsTestDefaultLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsTestDefaultLc_messagesK8sPo, nil +} + +func translationsTestDefaultLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsTestDefaultLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/test/default/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsTestEn_usLc_messagesK8sMo = []byte("\xde\x12\x04\x95\x00\x00\x00\x00\x03\x00\x00\x00\x1c\x00\x00\x004\x00\x00\x00\x05\x00\x00\x00L\x00\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x17\x00\x00\x00a\x00\x00\x00\v\x00\x00\x00y\x00\x00\x00\xac\x01\x00\x00\x85\x00\x00\x00%\x00\x00\x002\x02\x00\x00\x03\x00\x00\x00X\x02\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00test_plural\x00test_plural\x00test_string\x00Project-Id-Version: gettext-go-examples-hello\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-12-12 20:03+0000\nPO-Revision-Date: 2016-12-13 22:12-0800\nLast-Translator: Brendan Burns \nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nX-Generator: Poedit 1.6.10\nX-Poedit-SourceCharset: UTF-8\nLanguage-Team: \nPlural-Forms: nplurals=2; plural=(n != 1);\nLanguage: en\n\x00there was %d item\x00there were %d items\x00baz\x00") + +func translationsTestEn_usLc_messagesK8sMoBytes() ([]byte, error) { + return _translationsTestEn_usLc_messagesK8sMo, nil +} + +func translationsTestEn_usLc_messagesK8sMo() (*asset, error) { + bytes, err := translationsTestEn_usLc_messagesK8sMoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/test/en_US/LC_MESSAGES/k8s.mo", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _translationsTestEn_usLc_messagesK8sPo = []byte(`# Test translations for unit tests. +# Copyright (C) 2016 +# This file is distributed under the same license as the Kubernetes package. +# FIRST AUTHOR brendan.d.burns@gmail.com, 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: gettext-go-examples-hello\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-12 20:03+0000\n" +"PO-Revision-Date: 2016-12-13 22:12-0800\n" +"Last-Translator: Brendan Burns \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: en\n" + +msgid "test_plural" +msgid_plural "test_plural" +msgstr[0] "there was %d item" +msgstr[1] "there were %d items" + +msgid "test_string" +msgstr "baz" +`) + +func translationsTestEn_usLc_messagesK8sPoBytes() ([]byte, error) { + return _translationsTestEn_usLc_messagesK8sPo, nil +} + +func translationsTestEn_usLc_messagesK8sPo() (*asset, error) { + bytes, err := translationsTestEn_usLc_messagesK8sPoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "translations/test/en_US/LC_MESSAGES/k8s.po", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "translations/OWNERS": translationsOwners, + "translations/extract.py": translationsExtractPy, + "translations/kubectl/OWNERS": translationsKubectlOwners, + "translations/kubectl/de_DE/LC_MESSAGES/k8s.mo": translationsKubectlDe_deLc_messagesK8sMo, + "translations/kubectl/de_DE/LC_MESSAGES/k8s.po": translationsKubectlDe_deLc_messagesK8sPo, + "translations/kubectl/default/LC_MESSAGES/k8s.mo": translationsKubectlDefaultLc_messagesK8sMo, + "translations/kubectl/default/LC_MESSAGES/k8s.po": translationsKubectlDefaultLc_messagesK8sPo, + "translations/kubectl/en_US/LC_MESSAGES/k8s.mo": translationsKubectlEn_usLc_messagesK8sMo, + "translations/kubectl/en_US/LC_MESSAGES/k8s.po": translationsKubectlEn_usLc_messagesK8sPo, + "translations/kubectl/fr_FR/LC_MESSAGES/k8s.mo": translationsKubectlFr_frLc_messagesK8sMo, + "translations/kubectl/fr_FR/LC_MESSAGES/k8s.po": translationsKubectlFr_frLc_messagesK8sPo, + "translations/kubectl/it_IT/LC_MESSAGES/k8s.mo": translationsKubectlIt_itLc_messagesK8sMo, + "translations/kubectl/it_IT/LC_MESSAGES/k8s.po": translationsKubectlIt_itLc_messagesK8sPo, + "translations/kubectl/ja_JP/LC_MESSAGES/k8s.mo": translationsKubectlJa_jpLc_messagesK8sMo, + "translations/kubectl/ja_JP/LC_MESSAGES/k8s.po": translationsKubectlJa_jpLc_messagesK8sPo, + "translations/kubectl/ko_KR/LC_MESSAGES/k8s.mo": translationsKubectlKo_krLc_messagesK8sMo, + "translations/kubectl/ko_KR/LC_MESSAGES/k8s.po": translationsKubectlKo_krLc_messagesK8sPo, + "translations/kubectl/template.pot": translationsKubectlTemplatePot, + "translations/kubectl/zh_CN/LC_MESSAGES/k8s.mo": translationsKubectlZh_cnLc_messagesK8sMo, + "translations/kubectl/zh_CN/LC_MESSAGES/k8s.po": translationsKubectlZh_cnLc_messagesK8sPo, + "translations/kubectl/zh_TW/LC_MESSAGES/k8s.mo": translationsKubectlZh_twLc_messagesK8sMo, + "translations/kubectl/zh_TW/LC_MESSAGES/k8s.po": translationsKubectlZh_twLc_messagesK8sPo, + "translations/test/default/LC_MESSAGES/k8s.mo": translationsTestDefaultLc_messagesK8sMo, + "translations/test/default/LC_MESSAGES/k8s.po": translationsTestDefaultLc_messagesK8sPo, + "translations/test/en_US/LC_MESSAGES/k8s.mo": translationsTestEn_usLc_messagesK8sMo, + "translations/test/en_US/LC_MESSAGES/k8s.po": translationsTestEn_usLc_messagesK8sPo, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "translations": {nil, map[string]*bintree{ + "OWNERS": {translationsOwners, map[string]*bintree{}}, + "extract.py": {translationsExtractPy, map[string]*bintree{}}, + "kubectl": {nil, map[string]*bintree{ + "OWNERS": {translationsKubectlOwners, map[string]*bintree{}}, + "de_DE": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlDe_deLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlDe_deLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "default": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlDefaultLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlDefaultLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "en_US": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlEn_usLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlEn_usLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "fr_FR": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlFr_frLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlFr_frLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "it_IT": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlIt_itLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlIt_itLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "ja_JP": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlJa_jpLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlJa_jpLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "ko_KR": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlKo_krLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlKo_krLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "template.pot": {translationsKubectlTemplatePot, map[string]*bintree{}}, + "zh_CN": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlZh_cnLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlZh_cnLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "zh_TW": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsKubectlZh_twLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsKubectlZh_twLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + }}, + "test": {nil, map[string]*bintree{ + "default": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsTestDefaultLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsTestDefaultLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + "en_US": {nil, map[string]*bintree{ + "LC_MESSAGES": {nil, map[string]*bintree{ + "k8s.mo": {translationsTestEn_usLc_messagesK8sMo, map[string]*bintree{}}, + "k8s.po": {translationsTestEn_usLc_messagesK8sPo, map[string]*bintree{}}, + }}, + }}, + }}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/vendor/k8s.io/kubectl/pkg/rawhttp/raw.go b/vendor/k8s.io/kubectl/pkg/rawhttp/raw.go new file mode 100644 index 000000000..9bd366f7a --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/rawhttp/raw.go @@ -0,0 +1,94 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rawhttp + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + + "k8s.io/cli-runtime/pkg/genericclioptions" + "k8s.io/client-go/rest" +) + +// RawPost uses the REST client to POST content +func RawPost(restClient *rest.RESTClient, streams genericclioptions.IOStreams, url, filename string) error { + return raw(restClient, streams, url, filename, "POST") +} + +// RawPut uses the REST client to PUT content +func RawPut(restClient *rest.RESTClient, streams genericclioptions.IOStreams, url, filename string) error { + return raw(restClient, streams, url, filename, "PUT") +} + +// RawGet uses the REST client to GET content +func RawGet(restClient *rest.RESTClient, streams genericclioptions.IOStreams, url string) error { + return raw(restClient, streams, url, "", "GET") +} + +// RawDelete uses the REST client to DELETE content +func RawDelete(restClient *rest.RESTClient, streams genericclioptions.IOStreams, url, filename string) error { + return raw(restClient, streams, url, filename, "DELETE") +} + +// raw makes a simple HTTP request to the provided path on the server using the default credentials. +func raw(restClient *rest.RESTClient, streams genericclioptions.IOStreams, url, filename, requestType string) error { + var data io.ReadCloser + switch { + case len(filename) == 0: + data = ioutil.NopCloser(bytes.NewBuffer([]byte{})) + + case filename == "-": + data = ioutil.NopCloser(streams.In) + + default: + var err error + data, err = os.Open(filename) + if err != nil { + return err + } + } + + var request *rest.Request + switch requestType { + case "GET": + request = restClient.Get().RequestURI(url) + case "PUT": + request = restClient.Put().RequestURI(url).Body(data) + case "POST": + request = restClient.Post().RequestURI(url).Body(data) + case "DELETE": + request = restClient.Delete().RequestURI(url).Body(data) + + default: + return fmt.Errorf("unknown requestType: %q", requestType) + } + + stream, err := request.Stream() + if err != nil { + return err + } + defer stream.Close() + + _, err = io.Copy(streams.Out, stream) + if err != nil && err != io.EOF { + return err + } + return nil +} diff --git a/vendor/k8s.io/kubectl/pkg/scheme/install.go b/vendor/k8s.io/kubectl/pkg/scheme/install.go new file mode 100644 index 000000000..ffd15bf1b --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/scheme/install.go @@ -0,0 +1,83 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scheme + +import ( + admissionv1 "k8s.io/api/admission/v1" + admissionv1beta1 "k8s.io/api/admission/v1beta1" + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" + appsv1 "k8s.io/api/apps/v1" + appsv1beta1 "k8s.io/api/apps/v1beta1" + appsv1beta2 "k8s.io/api/apps/v1beta2" + authenticationv1 "k8s.io/api/authentication/v1" + authenticationv1beta1 "k8s.io/api/authentication/v1beta1" + authorizationv1 "k8s.io/api/authorization/v1" + authorizationv1beta1 "k8s.io/api/authorization/v1beta1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1" + batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + corev1 "k8s.io/api/core/v1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" + imagepolicyv1alpha1 "k8s.io/api/imagepolicy/v1alpha1" + networkingv1 "k8s.io/api/networking/v1" + policyv1beta1 "k8s.io/api/policy/v1beta1" + rbacv1 "k8s.io/api/rbac/v1" + rbacv1alpha1 "k8s.io/api/rbac/v1alpha1" + rbacv1beta1 "k8s.io/api/rbac/v1beta1" + schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1" + settingsv1alpha1 "k8s.io/api/settings/v1alpha1" + storagev1 "k8s.io/api/storage/v1" + storagev1beta1 "k8s.io/api/storage/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/kubernetes/scheme" +) + +// Register all groups in the kubectl's registry, but no componentconfig group since it's not in k8s.io/api +// The code in this file mostly duplicate the install under k8s.io/kubernetes/pkg/api and k8s.io/kubernetes/pkg/apis, +// but does NOT register the internal types. +func init() { + // Register external types for Scheme + metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(metav1beta1.AddMetaToScheme(Scheme)) + utilruntime.Must(metav1.AddMetaToScheme(Scheme)) + utilruntime.Must(scheme.AddToScheme(Scheme)) + + utilruntime.Must(Scheme.SetVersionPriority(corev1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(admissionv1beta1.SchemeGroupVersion, admissionv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(admissionregistrationv1beta1.SchemeGroupVersion, admissionregistrationv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(appsv1beta1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion, appsv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(certificatesv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(extensionsv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(imagepolicyv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(networkingv1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(policyv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(schedulingv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(settingsv1alpha1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(storagev1.SchemeGroupVersion, storagev1beta1.SchemeGroupVersion)) +} diff --git a/vendor/k8s.io/kubectl/pkg/scheme/scheme.go b/vendor/k8s.io/kubectl/pkg/scheme/scheme.go new file mode 100644 index 000000000..d1d7847b8 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/scheme/scheme.go @@ -0,0 +1,39 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package scheme + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" +) + +// All kubectl code should eventually switch to use this Registry and Scheme instead of the global ones. + +// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. +var Scheme = runtime.NewScheme() + +// Codecs provides access to encoding and decoding for the scheme +var Codecs = serializer.NewCodecFactory(Scheme) + +// ParameterCodec handles versioning of objects that are converted to query parameters. +var ParameterCodec = runtime.NewParameterCodec(Scheme) + +// DefaultJSONEncoder returns a default encoder for our scheme +func DefaultJSONEncoder() runtime.Encoder { + return unstructured.NewJSONFallbackEncoder(Codecs.LegacyCodec(Scheme.PrioritizedVersionsAllGroups()...)) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/i18n/i18n.go b/vendor/k8s.io/kubectl/pkg/util/i18n/i18n.go new file mode 100644 index 000000000..31e830c64 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/i18n/i18n.go @@ -0,0 +1,147 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package i18n + +import ( + "archive/zip" + "bytes" + "errors" + "fmt" + "os" + "strings" + + "k8s.io/kubectl/pkg/generated" + + "github.com/chai2010/gettext-go/gettext" + "k8s.io/klog" +) + +var knownTranslations = map[string][]string{ + "kubectl": { + "default", + "en_US", + "fr_FR", + "zh_CN", + "ja_JP", + "zh_TW", + "it_IT", + "de_DE", + "ko_KR", + }, + // only used for unit tests. + "test": { + "default", + "en_US", + }, +} + +func loadSystemLanguage() string { + // Implements the following locale priority order: LC_ALL, LC_MESSAGES, LANG + // Similarly to: https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html + langStr := os.Getenv("LC_ALL") + if langStr == "" { + langStr = os.Getenv("LC_MESSAGES") + } + if langStr == "" { + langStr = os.Getenv("LANG") + } + + if langStr == "" { + klog.V(3).Infof("Couldn't find the LC_ALL, LC_MESSAGES or LANG environment variables, defaulting to en_US") + return "default" + } + pieces := strings.Split(langStr, ".") + if len(pieces) != 2 { + klog.V(3).Infof("Unexpected system language (%s), defaulting to en_US", langStr) + return "default" + } + return pieces[0] +} + +func findLanguage(root string, getLanguageFn func() string) string { + langStr := getLanguageFn() + + translations := knownTranslations[root] + for ix := range translations { + if translations[ix] == langStr { + return langStr + } + } + klog.V(3).Infof("Couldn't find translations for %s, using default", langStr) + return "default" +} + +// LoadTranslations loads translation files. getLanguageFn should return a language +// string (e.g. 'en-US'). If getLanguageFn is nil, then the loadSystemLanguage function +// is used, which uses the 'LANG' environment variable. +func LoadTranslations(root string, getLanguageFn func() string) error { + if getLanguageFn == nil { + getLanguageFn = loadSystemLanguage + } + + langStr := findLanguage(root, getLanguageFn) + translationFiles := []string{ + fmt.Sprintf("%s/%s/LC_MESSAGES/k8s.po", root, langStr), + fmt.Sprintf("%s/%s/LC_MESSAGES/k8s.mo", root, langStr), + } + + klog.V(3).Infof("Setting language to %s", langStr) + // TODO: list the directory and load all files. + buf := new(bytes.Buffer) + w := zip.NewWriter(buf) + + // Make sure to check the error on Close. + for _, file := range translationFiles { + filename := "translations/" + file + f, err := w.Create(file) + if err != nil { + return err + } + data, err := generated.Asset(filename) + if err != nil { + return err + } + if _, err := f.Write(data); err != nil { + return nil + } + } + if err := w.Close(); err != nil { + return err + } + gettext.BindTextdomain("k8s", root+".zip", buf.Bytes()) + gettext.Textdomain("k8s") + gettext.SetLocale(langStr) + return nil +} + +// T translates a string, possibly substituting arguments into it along +// the way. If len(args) is > 0, args1 is assumed to be the plural value +// and plural translation is used. +func T(defaultValue string, args ...int) string { + if len(args) == 0 { + return gettext.PGettext("", defaultValue) + } + return fmt.Sprintf(gettext.PNGettext("", defaultValue, defaultValue+".plural", args[0]), + args[0]) +} + +// Errorf produces an error with a translated error string. +// Substitution is performed via the `T` function above, following +// the same rules. +func Errorf(defaultValue string, args ...int) error { + return errors.New(T(defaultValue, args...)) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go b/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go new file mode 100644 index 000000000..0265b9fb1 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go @@ -0,0 +1,104 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package interrupt + +import ( + "os" + "os/signal" + "sync" + "syscall" +) + +// terminationSignals are signals that cause the program to exit in the +// supported platforms (linux, darwin, windows). +var terminationSignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT} + +// Handler guarantees execution of notifications after a critical section (the function passed +// to a Run method), even in the presence of process termination. It guarantees exactly once +// invocation of the provided notify functions. +type Handler struct { + notify []func() + final func(os.Signal) + once sync.Once +} + +// Chain creates a new handler that invokes all notify functions when the critical section exits +// and then invokes the optional handler's notifications. This allows critical sections to be +// nested without losing exactly once invocations. Notify functions can invoke any cleanup needed +// but should not exit (which is the responsibility of the parent handler). +func Chain(handler *Handler, notify ...func()) *Handler { + if handler == nil { + return New(nil, notify...) + } + return New(handler.Signal, append(notify, handler.Close)...) +} + +// New creates a new handler that guarantees all notify functions are run after the critical +// section exits (or is interrupted by the OS), then invokes the final handler. If no final +// handler is specified, the default final is `os.Exit(1)`. A handler can only be used for +// one critical section. +func New(final func(os.Signal), notify ...func()) *Handler { + return &Handler{ + final: final, + notify: notify, + } +} + +// Close executes all the notification handlers if they have not yet been executed. +func (h *Handler) Close() { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + }) +} + +// Signal is called when an os.Signal is received, and guarantees that all notifications +// are executed, then the final handler is executed. This function should only be called once +// per Handler instance. +func (h *Handler) Signal(s os.Signal) { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + if h.final == nil { + os.Exit(1) + } + h.final(s) + }) +} + +// Run ensures that any notifications are invoked after the provided fn exits (even if the +// process is interrupted by an OS termination signal). Notifications are only invoked once +// per Handler instance, so calling Run more than once will not behave as the user expects. +func (h *Handler) Run(fn func() error) error { + ch := make(chan os.Signal, 1) + signal.Notify(ch, terminationSignals...) + defer func() { + signal.Stop(ch) + close(ch) + }() + go func() { + sig, ok := <-ch + if !ok { + return + } + h.Signal(sig) + }() + defer h.Close() + return fn() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/OWNERS b/vendor/k8s.io/kubectl/pkg/util/openapi/OWNERS new file mode 100644 index 000000000..99dabed08 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- apelisse +reviewers: +- apelisse diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/doc.go b/vendor/k8s.io/kubectl/pkg/util/openapi/doc.go new file mode 100644 index 000000000..08194d580 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package openapi is a collection of libraries for fetching the openapi spec +// from a Kubernetes server and then indexing the type definitions. +// The openapi spec contains the object model definitions and extensions metadata +// such as the patchStrategy and patchMergeKey for creating patches. +package openapi // k8s.io/kubectl/pkg/util/openapi diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/dryrun.go b/vendor/k8s.io/kubectl/pkg/util/openapi/dryrun.go new file mode 100644 index 000000000..33cf9e9e5 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/dryrun.go @@ -0,0 +1,65 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package openapi + +import ( + "errors" + + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + yaml "gopkg.in/yaml.v2" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func hasGVKExtension(extensions []*openapi_v2.NamedAny, gvk schema.GroupVersionKind) bool { + for _, extension := range extensions { + if extension.GetValue().GetYaml() == "" || + extension.GetName() != "x-kubernetes-group-version-kind" { + continue + } + var value map[string]string + err := yaml.Unmarshal([]byte(extension.GetValue().GetYaml()), &value) + if err != nil { + continue + } + + if value["group"] == gvk.Group && value["kind"] == gvk.Kind && value["version"] == gvk.Version { + return true + } + return false + } + return false +} + +// SupportsDryRun is a method that let's us look in the OpenAPI if the +// specific group-version-kind supports the dryRun query parameter for +// the PATCH end-point. +func SupportsDryRun(doc *openapi_v2.Document, gvk schema.GroupVersionKind) (bool, error) { + for _, path := range doc.GetPaths().GetPath() { + // Is this describing the gvk we're looking for? + if !hasGVKExtension(path.GetValue().GetPatch().GetVendorExtension(), gvk) { + continue + } + for _, param := range path.GetValue().GetPatch().GetParameters() { + if param.GetParameter().GetNonBodyParameter().GetQueryParameterSubSchema().GetName() == "dryRun" { + return true, nil + } + } + return false, nil + } + + return false, errors.New("couldn't find GVK in openapi") +} diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/extensions.go b/vendor/k8s.io/kubectl/pkg/util/openapi/extensions.go new file mode 100644 index 000000000..f1b5cdd4f --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/extensions.go @@ -0,0 +1,27 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package openapi + +import "github.com/go-openapi/spec" + +// PrintColumnsKey is the key that defines which columns should be printed +const PrintColumnsKey = "x-kubernetes-print-columns" + +// GetPrintColumns looks for the open API extension for the display columns. +func GetPrintColumns(extensions spec.Extensions) (string, bool) { + return extensions.GetString(PrintColumnsKey) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/openapi.go b/vendor/k8s.io/kubectl/pkg/util/openapi/openapi.go new file mode 100644 index 000000000..c8f370b99 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/openapi.go @@ -0,0 +1,128 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package openapi + +import ( + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/kube-openapi/pkg/util/proto" +) + +// Resources interface describe a resources provider, that can give you +// resource based on group-version-kind. +type Resources interface { + LookupResource(gvk schema.GroupVersionKind) proto.Schema +} + +// groupVersionKindExtensionKey is the key used to lookup the +// GroupVersionKind value for an object definition from the +// definition's "extensions" map. +const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind" + +// document is an implementation of `Resources`. It looks for +// resources in an openapi Schema. +type document struct { + // Maps gvk to model name + resources map[schema.GroupVersionKind]string + models proto.Models +} + +var _ Resources = &document{} + +// NewOpenAPIData creates a new `Resources` out of the openapi document +func NewOpenAPIData(doc *openapi_v2.Document) (Resources, error) { + models, err := proto.NewOpenAPIData(doc) + if err != nil { + return nil, err + } + + resources := map[schema.GroupVersionKind]string{} + for _, modelName := range models.ListModels() { + model := models.LookupModel(modelName) + if model == nil { + panic("ListModels returns a model that can't be looked-up.") + } + gvkList := parseGroupVersionKind(model) + for _, gvk := range gvkList { + if len(gvk.Kind) > 0 { + resources[gvk] = modelName + } + } + } + + return &document{ + resources: resources, + models: models, + }, nil +} + +func (d *document) LookupResource(gvk schema.GroupVersionKind) proto.Schema { + modelName, found := d.resources[gvk] + if !found { + return nil + } + return d.models.LookupModel(modelName) +} + +// Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one. +func parseGroupVersionKind(s proto.Schema) []schema.GroupVersionKind { + extensions := s.GetExtensions() + + gvkListResult := []schema.GroupVersionKind{} + + // Get the extensions + gvkExtension, ok := extensions[groupVersionKindExtensionKey] + if !ok { + return []schema.GroupVersionKind{} + } + + // gvk extension must be a list of at least 1 element. + gvkList, ok := gvkExtension.([]interface{}) + if !ok { + return []schema.GroupVersionKind{} + } + + for _, gvk := range gvkList { + // gvk extension list must be a map with group, version, and + // kind fields + gvkMap, ok := gvk.(map[interface{}]interface{}) + if !ok { + continue + } + group, ok := gvkMap["group"].(string) + if !ok { + continue + } + version, ok := gvkMap["version"].(string) + if !ok { + continue + } + kind, ok := gvkMap["kind"].(string) + if !ok { + continue + } + + gvkListResult = append(gvkListResult, schema.GroupVersionKind{ + Group: group, + Version: version, + Kind: kind, + }) + } + + return gvkListResult +} diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/openapi_getter.go b/vendor/k8s.io/kubectl/pkg/util/openapi/openapi_getter.go new file mode 100644 index 000000000..d5c9476a0 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/openapi_getter.go @@ -0,0 +1,65 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package openapi + +import ( + "sync" + + "k8s.io/client-go/discovery" +) + +// synchronizedOpenAPIGetter fetches the openapi schema once and then caches it in memory +type synchronizedOpenAPIGetter struct { + // Cached results + sync.Once + openAPISchema Resources + err error + + openAPIClient discovery.OpenAPISchemaInterface +} + +var _ Getter = &synchronizedOpenAPIGetter{} + +// Getter is an interface for fetching openapi specs and parsing them into an Resources struct +type Getter interface { + // OpenAPIData returns the parsed OpenAPIData + Get() (Resources, error) +} + +// NewOpenAPIGetter returns an object to return OpenAPIDatas which reads +// from a server, and then stores in memory for subsequent invocations +func NewOpenAPIGetter(openAPIClient discovery.OpenAPISchemaInterface) Getter { + return &synchronizedOpenAPIGetter{ + openAPIClient: openAPIClient, + } +} + +// Resources implements Getter +func (g *synchronizedOpenAPIGetter) Get() (Resources, error) { + g.Do(func() { + s, err := g.openAPIClient.OpenAPISchema() + if err != nil { + g.err = err + return + } + + g.openAPISchema, g.err = NewOpenAPIData(s) + }) + + // Return the save result + return g.openAPISchema, g.err +} diff --git a/vendor/k8s.io/kubectl/pkg/util/openapi/validation/validation.go b/vendor/k8s.io/kubectl/pkg/util/openapi/validation/validation.go new file mode 100644 index 000000000..25aec97ed --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/openapi/validation/validation.go @@ -0,0 +1,140 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "errors" + + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/kube-openapi/pkg/util/proto/validation" + "k8s.io/kubectl/pkg/util/openapi" +) + +// SchemaValidation validates the object against an OpenAPI schema. +type SchemaValidation struct { + resources openapi.Resources +} + +// NewSchemaValidation creates a new SchemaValidation that can be used +// to validate objects. +func NewSchemaValidation(resources openapi.Resources) *SchemaValidation { + return &SchemaValidation{ + resources: resources, + } +} + +// ValidateBytes will validates the object against using the Resources +// object. +func (v *SchemaValidation) ValidateBytes(data []byte) error { + obj, err := parse(data) + if err != nil { + return err + } + + gvk, errs := getObjectKind(obj) + if errs != nil { + return utilerrors.NewAggregate(errs) + } + + if (gvk == schema.GroupVersionKind{Version: "v1", Kind: "List"}) { + return utilerrors.NewAggregate(v.validateList(obj)) + } + + return utilerrors.NewAggregate(v.validateResource(obj, gvk)) +} + +func (v *SchemaValidation) validateList(object interface{}) []error { + fields, ok := object.(map[string]interface{}) + if !ok || fields == nil { + return []error{errors.New("invalid object to validate")} + } + + allErrors := []error{} + if _, ok := fields["items"].([]interface{}); !ok { + return []error{errors.New("invalid object to validate")} + } + for _, item := range fields["items"].([]interface{}) { + if gvk, errs := getObjectKind(item); errs != nil { + allErrors = append(allErrors, errs...) + } else { + allErrors = append(allErrors, v.validateResource(item, gvk)...) + } + } + return allErrors +} + +func (v *SchemaValidation) validateResource(obj interface{}, gvk schema.GroupVersionKind) []error { + resource := v.resources.LookupResource(gvk) + if resource == nil { + // resource is not present, let's just skip validation. + return nil + } + + return validation.ValidateModel(obj, resource, gvk.Kind) +} + +func parse(data []byte) (interface{}, error) { + var obj interface{} + out, err := yaml.ToJSON(data) + if err != nil { + return nil, err + } + if err := json.Unmarshal(out, &obj); err != nil { + return nil, err + } + return obj, nil +} + +func getObjectKind(object interface{}) (schema.GroupVersionKind, []error) { + var listErrors []error + fields, ok := object.(map[string]interface{}) + if !ok || fields == nil { + listErrors = append(listErrors, errors.New("invalid object to validate")) + return schema.GroupVersionKind{}, listErrors + } + + var group string + var version string + apiVersion := fields["apiVersion"] + if apiVersion == nil { + listErrors = append(listErrors, errors.New("apiVersion not set")) + } else if _, ok := apiVersion.(string); !ok { + listErrors = append(listErrors, errors.New("apiVersion isn't string type")) + } else { + gv, err := schema.ParseGroupVersion(apiVersion.(string)) + if err != nil { + listErrors = append(listErrors, err) + } else { + group = gv.Group + version = gv.Version + } + } + kind := fields["kind"] + if kind == nil { + listErrors = append(listErrors, errors.New("kind not set")) + } else if _, ok := kind.(string); !ok { + listErrors = append(listErrors, errors.New("kind isn't string type")) + } + if listErrors != nil { + return schema.GroupVersionKind{}, listErrors + } + + return schema.GroupVersionKind{Group: group, Version: version, Kind: kind.(string)}, nil +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go b/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go new file mode 100644 index 000000000..447a39621 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go @@ -0,0 +1,59 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "github.com/spf13/cobra" +) + +type CommandGroup struct { + Message string + Commands []*cobra.Command +} + +type CommandGroups []CommandGroup + +func (g CommandGroups) Add(c *cobra.Command) { + for _, group := range g { + c.AddCommand(group.Commands...) + } +} + +func (g CommandGroups) Has(c *cobra.Command) bool { + for _, group := range g { + for _, command := range group.Commands { + if command == c { + return true + } + } + } + return false +} + +func AddAdditionalCommands(g CommandGroups, message string, cmds []*cobra.Command) CommandGroups { + group := CommandGroup{Message: message} + for _, c := range cmds { + // Don't show commands that have no short description + if !g.Has(c) && len(c.Short) != 0 { + group.Commands = append(group.Commands, c) + } + } + if len(group.Commands) == 0 { + return g + } + return append(g, group) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go b/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go new file mode 100644 index 000000000..65ee886d1 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go @@ -0,0 +1,147 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "bytes" + "fmt" + "strings" + + "github.com/russross/blackfriday" +) + +const linebreak = "\n" + +// ASCIIRenderer implements blackfriday.Renderer +var _ blackfriday.Renderer = &ASCIIRenderer{} + +// ASCIIRenderer is a blackfriday.Renderer intended for rendering markdown +// documents as plain text, well suited for human reading on terminals. +type ASCIIRenderer struct { + Indentation string + + listItemCount uint + listLevel uint +} + +// NormalText gets a text chunk *after* the markdown syntax was already +// processed and does a final cleanup on things we don't expect here, like +// removing linebreaks on things that are not a paragraph break (auto unwrap). +func (r *ASCIIRenderer) NormalText(out *bytes.Buffer, text []byte) { + raw := string(text) + lines := strings.Split(raw, linebreak) + for _, line := range lines { + trimmed := strings.Trim(line, " \n\t") + if len(trimmed) > 0 && trimmed[0] != '_' { + out.WriteString(" ") + } + out.WriteString(trimmed) + } +} + +// List renders the start and end of a list. +func (r *ASCIIRenderer) List(out *bytes.Buffer, text func() bool, flags int) { + r.listLevel++ + out.WriteString(linebreak) + text() + r.listLevel-- +} + +// ListItem renders list items and supports both ordered and unordered lists. +func (r *ASCIIRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) { + if flags&blackfriday.LIST_ITEM_BEGINNING_OF_LIST != 0 { + r.listItemCount = 1 + } else { + r.listItemCount++ + } + indent := strings.Repeat(r.Indentation, int(r.listLevel)) + var bullet string + if flags&blackfriday.LIST_TYPE_ORDERED != 0 { + bullet += fmt.Sprintf("%d.", r.listItemCount) + } else { + bullet += "*" + } + out.WriteString(indent + bullet + " ") + r.fw(out, text) + out.WriteString(linebreak) +} + +// Paragraph renders the start and end of a paragraph. +func (r *ASCIIRenderer) Paragraph(out *bytes.Buffer, text func() bool) { + out.WriteString(linebreak) + text() + out.WriteString(linebreak) +} + +// BlockCode renders a chunk of text that represents source code. +func (r *ASCIIRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string) { + out.WriteString(linebreak) + lines := []string{} + for _, line := range strings.Split(string(text), linebreak) { + indented := r.Indentation + line + lines = append(lines, indented) + } + out.WriteString(strings.Join(lines, linebreak)) +} + +func (r *ASCIIRenderer) GetFlags() int { return 0 } +func (r *ASCIIRenderer) HRule(out *bytes.Buffer) { + out.WriteString(linebreak + "----------" + linebreak) +} +func (r *ASCIIRenderer) LineBreak(out *bytes.Buffer) { out.WriteString(linebreak) } +func (r *ASCIIRenderer) TitleBlock(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) Header(out *bytes.Buffer, text func() bool, level int, id string) { text() } +func (r *ASCIIRenderer) BlockHtml(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) BlockQuote(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) TableRow(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) } +func (r *ASCIIRenderer) TableCell(out *bytes.Buffer, text []byte, align int) { r.fw(out, text) } +func (r *ASCIIRenderer) Footnotes(out *bytes.Buffer, text func() bool) { text() } +func (r *ASCIIRenderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) { r.fw(out, text) } +func (r *ASCIIRenderer) AutoLink(out *bytes.Buffer, link []byte, kind int) { r.fw(out, link) } +func (r *ASCIIRenderer) CodeSpan(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) DoubleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) Emphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) RawHtmlTag(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) TripleEmphasis(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) StrikeThrough(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { r.fw(out, ref) } +func (r *ASCIIRenderer) Entity(out *bytes.Buffer, entity []byte) { r.fw(out, entity) } +func (r *ASCIIRenderer) Smartypants(out *bytes.Buffer, text []byte) { r.fw(out, text) } +func (r *ASCIIRenderer) DocumentHeader(out *bytes.Buffer) {} +func (r *ASCIIRenderer) DocumentFooter(out *bytes.Buffer) {} +func (r *ASCIIRenderer) TocHeaderWithAnchor(text []byte, level int, anchor string) {} +func (r *ASCIIRenderer) TocHeader(text []byte, level int) {} +func (r *ASCIIRenderer) TocFinalize() {} + +func (r *ASCIIRenderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) { + r.fw(out, header, body) +} + +func (r *ASCIIRenderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { + r.fw(out, link) +} + +func (r *ASCIIRenderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { + r.fw(out, link) +} + +func (r *ASCIIRenderer) fw(out *bytes.Buffer, text ...[]byte) { + for _, t := range text { + out.Write(t) + } +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go b/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go new file mode 100644 index 000000000..f90412058 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go @@ -0,0 +1,97 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/russross/blackfriday" + "github.com/spf13/cobra" +) + +const Indentation = ` ` + +// LongDesc normalizes a command's long description to follow the conventions. +func LongDesc(s string) string { + if len(s) == 0 { + return s + } + return normalizer{s}.heredoc().markdown().trim().string +} + +// Examples normalizes a command's examples to follow the conventions. +func Examples(s string) string { + if len(s) == 0 { + return s + } + return normalizer{s}.trim().indent().string +} + +// Normalize perform all required normalizations on a given command. +func Normalize(cmd *cobra.Command) *cobra.Command { + if len(cmd.Long) > 0 { + cmd.Long = LongDesc(cmd.Long) + } + if len(cmd.Example) > 0 { + cmd.Example = Examples(cmd.Example) + } + return cmd +} + +// NormalizeAll perform all required normalizations in the entire command tree. +func NormalizeAll(cmd *cobra.Command) *cobra.Command { + if cmd.HasSubCommands() { + for _, subCmd := range cmd.Commands() { + NormalizeAll(subCmd) + } + } + Normalize(cmd) + return cmd +} + +type normalizer struct { + string +} + +func (s normalizer) markdown() normalizer { + bytes := []byte(s.string) + formatted := blackfriday.Markdown(bytes, &ASCIIRenderer{Indentation: Indentation}, blackfriday.EXTENSION_NO_INTRA_EMPHASIS) + s.string = string(formatted) + return s +} + +func (s normalizer) heredoc() normalizer { + s.string = heredoc.Doc(s.string) + return s +} + +func (s normalizer) trim() normalizer { + s.string = strings.TrimSpace(s.string) + return s +} + +func (s normalizer) indent() normalizer { + indentedLines := []string{} + for _, line := range strings.Split(s.string, "\n") { + trimmed := strings.TrimSpace(line) + indented := Indentation + trimmed + indentedLines = append(indentedLines, indented) + } + s.string = strings.Join(indentedLines, "\n") + return s +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/templater.go b/vendor/k8s.io/kubectl/pkg/util/templates/templater.go new file mode 100644 index 000000000..18901348a --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/templater.go @@ -0,0 +1,297 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "bytes" + "fmt" + "strings" + "text/template" + "unicode" + + "k8s.io/kubectl/pkg/util/term" + + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" +) + +type FlagExposer interface { + ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer +} + +func ActsAsRootCommand(cmd *cobra.Command, filters []string, groups ...CommandGroup) FlagExposer { + if cmd == nil { + panic("nil root command") + } + templater := &templater{ + RootCmd: cmd, + UsageTemplate: MainUsageTemplate(), + HelpTemplate: MainHelpTemplate(), + CommandGroups: groups, + Filtered: filters, + } + cmd.SetFlagErrorFunc(templater.FlagErrorFunc()) + cmd.SetUsageFunc(templater.UsageFunc()) + cmd.SetHelpFunc(templater.HelpFunc()) + return templater +} + +func UseOptionsTemplates(cmd *cobra.Command) { + templater := &templater{ + UsageTemplate: OptionsUsageTemplate(), + HelpTemplate: OptionsHelpTemplate(), + } + cmd.SetUsageFunc(templater.UsageFunc()) + cmd.SetHelpFunc(templater.HelpFunc()) +} + +type templater struct { + UsageTemplate string + HelpTemplate string + RootCmd *cobra.Command + CommandGroups + Filtered []string +} + +func (templater *templater) FlagErrorFunc(exposedFlags ...string) func(*cobra.Command, error) error { + return func(c *cobra.Command, err error) error { + c.SilenceUsage = true + switch c.CalledAs() { + case "options": + return fmt.Errorf("%s\nRun '%s' without flags.", err, c.CommandPath()) + default: + return fmt.Errorf("%s\nSee '%s --help' for usage.", err, c.CommandPath()) + } + } +} + +func (templater *templater) ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer { + cmd.SetUsageFunc(templater.UsageFunc(flags...)) + return templater +} + +func (templater *templater) HelpFunc() func(*cobra.Command, []string) { + return func(c *cobra.Command, s []string) { + t := template.New("help") + t.Funcs(templater.templateFuncs()) + template.Must(t.Parse(templater.HelpTemplate)) + out := term.NewResponsiveWriter(c.OutOrStdout()) + err := t.Execute(out, c) + if err != nil { + c.Println(err) + } + } +} + +func (templater *templater) UsageFunc(exposedFlags ...string) func(*cobra.Command) error { + return func(c *cobra.Command) error { + t := template.New("usage") + t.Funcs(templater.templateFuncs(exposedFlags...)) + template.Must(t.Parse(templater.UsageTemplate)) + out := term.NewResponsiveWriter(c.OutOrStderr()) + return t.Execute(out, c) + } +} + +func (templater *templater) templateFuncs(exposedFlags ...string) template.FuncMap { + return template.FuncMap{ + "trim": strings.TrimSpace, + "trimRight": func(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) }, + "trimLeft": func(s string) string { return strings.TrimLeftFunc(s, unicode.IsSpace) }, + "gt": cobra.Gt, + "eq": cobra.Eq, + "rpad": rpad, + "appendIfNotPresent": appendIfNotPresent, + "flagsNotIntersected": flagsNotIntersected, + "visibleFlags": visibleFlags, + "flagsUsages": flagsUsages, + "cmdGroups": templater.cmdGroups, + "cmdGroupsString": templater.cmdGroupsString, + "rootCmd": templater.rootCmdName, + "isRootCmd": templater.isRootCmd, + "optionsCmdFor": templater.optionsCmdFor, + "usageLine": templater.usageLine, + "exposed": func(c *cobra.Command) *flag.FlagSet { + exposed := flag.NewFlagSet("exposed", flag.ContinueOnError) + if len(exposedFlags) > 0 { + for _, name := range exposedFlags { + if flag := c.Flags().Lookup(name); flag != nil { + exposed.AddFlag(flag) + } + } + } + return exposed + }, + } +} + +func (templater *templater) cmdGroups(c *cobra.Command, all []*cobra.Command) []CommandGroup { + if len(templater.CommandGroups) > 0 && c == templater.RootCmd { + all = filter(all, templater.Filtered...) + return AddAdditionalCommands(templater.CommandGroups, "Other Commands:", all) + } + all = filter(all, "options") + return []CommandGroup{ + { + Message: "Available Commands:", + Commands: all, + }, + } +} + +func (t *templater) cmdGroupsString(c *cobra.Command) string { + groups := []string{} + for _, cmdGroup := range t.cmdGroups(c, c.Commands()) { + cmds := []string{cmdGroup.Message} + for _, cmd := range cmdGroup.Commands { + if cmd.IsAvailableCommand() { + cmds = append(cmds, " "+rpad(cmd.Name(), cmd.NamePadding())+" "+cmd.Short) + } + } + groups = append(groups, strings.Join(cmds, "\n")) + } + return strings.Join(groups, "\n\n") +} + +func (t *templater) rootCmdName(c *cobra.Command) string { + return t.rootCmd(c).CommandPath() +} + +func (t *templater) isRootCmd(c *cobra.Command) bool { + return t.rootCmd(c) == c +} + +func (t *templater) parents(c *cobra.Command) []*cobra.Command { + parents := []*cobra.Command{c} + for current := c; !t.isRootCmd(current) && current.HasParent(); { + current = current.Parent() + parents = append(parents, current) + } + return parents +} + +func (t *templater) rootCmd(c *cobra.Command) *cobra.Command { + if c != nil && !c.HasParent() { + return c + } + if t.RootCmd == nil { + panic("nil root cmd") + } + return t.RootCmd +} + +func (t *templater) optionsCmdFor(c *cobra.Command) string { + if !c.Runnable() { + return "" + } + rootCmdStructure := t.parents(c) + for i := len(rootCmdStructure) - 1; i >= 0; i-- { + cmd := rootCmdStructure[i] + if _, _, err := cmd.Find([]string{"options"}); err == nil { + return cmd.CommandPath() + " options" + } + } + return "" +} + +func (t *templater) usageLine(c *cobra.Command) string { + usage := c.UseLine() + suffix := "[options]" + if c.HasFlags() && !strings.Contains(usage, suffix) { + usage += " " + suffix + } + return usage +} + +func flagsUsages(f *flag.FlagSet) string { + x := new(bytes.Buffer) + + f.VisitAll(func(flag *flag.Flag) { + if flag.Hidden { + return + } + format := "--%s=%s: %s\n" + + if flag.Value.Type() == "string" { + format = "--%s='%s': %s\n" + } + + if len(flag.Shorthand) > 0 { + format = " -%s, " + format + } else { + format = " %s " + format + } + + fmt.Fprintf(x, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) + }) + + return x.String() +} + +func rpad(s string, padding int) string { + template := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(template, s) +} + +func appendIfNotPresent(s, stringToAppend string) string { + if strings.Contains(s, stringToAppend) { + return s + } + return s + " " + stringToAppend +} + +func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet { + f := flag.NewFlagSet("notIntersected", flag.ContinueOnError) + l.VisitAll(func(flag *flag.Flag) { + if r.Lookup(flag.Name) == nil { + f.AddFlag(flag) + } + }) + return f +} + +func visibleFlags(l *flag.FlagSet) *flag.FlagSet { + hidden := "help" + f := flag.NewFlagSet("visible", flag.ContinueOnError) + l.VisitAll(func(flag *flag.Flag) { + if flag.Name != hidden { + f.AddFlag(flag) + } + }) + return f +} + +func filter(cmds []*cobra.Command, names ...string) []*cobra.Command { + out := []*cobra.Command{} + for _, c := range cmds { + if c.Hidden { + continue + } + skip := false + for _, name := range names { + if name == c.Name() { + skip = true + break + } + } + if skip { + continue + } + out = append(out, c) + } + return out +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/templates.go b/vendor/k8s.io/kubectl/pkg/util/templates/templates.go new file mode 100644 index 000000000..9f3b75b57 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/templates.go @@ -0,0 +1,103 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "strings" + "unicode" +) + +const ( + // SectionVars is the help template section that declares variables to be used in the template. + SectionVars = `{{$isRootCmd := isRootCmd .}}` + + `{{$rootCmd := rootCmd .}}` + + `{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` + + `{{$explicitlyExposedFlags := exposed .}}` + + `{{$optionsCmdFor := optionsCmdFor .}}` + + `{{$usageLine := usageLine .}}` + + // SectionAliases is the help template section that displays command aliases. + SectionAliases = `{{if gt .Aliases 0}}Aliases: +{{.NameAndAliases}} + +{{end}}` + + // SectionExamples is the help template section that displays command examples. + SectionExamples = `{{if .HasExample}}Examples: +{{trimRight .Example}} + +{{end}}` + + // SectionSubcommands is the help template section that displays the command's subcommands. + SectionSubcommands = `{{if .HasAvailableSubCommands}}{{cmdGroupsString .}} + +{{end}}` + + // SectionFlags is the help template section that displays the command's flags. + SectionFlags = `{{ if or $visibleFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options: +{{ if $visibleFlags.HasFlags}}{{trimRight (flagsUsages $visibleFlags)}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{ if $visibleFlags.HasFlags}} +{{end}}{{trimRight (flagsUsages $explicitlyExposedFlags)}}{{end}} + +{{end}}` + + // SectionUsage is the help template section that displays the command's usage. + SectionUsage = `{{if and .Runnable (ne .UseLine "") (ne .UseLine $rootCmd)}}Usage: + {{$usageLine}} + +{{end}}` + + // SectionTipsHelp is the help template section that displays the '--help' hint. + SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} --help" for more information about a given command. +{{end}}` + + // SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags. + SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands). +{{end}}` +) + +// MainHelpTemplate if the template for 'help' used by most commands. +func MainHelpTemplate() string { + return `{{with or .Long .Short }}{{. | trim}}{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` +} + +// MainUsageTemplate if the template for 'usage' used by most commands. +func MainUsageTemplate() string { + sections := []string{ + "\n\n", + SectionVars, + SectionAliases, + SectionExamples, + SectionSubcommands, + SectionFlags, + SectionUsage, + SectionTipsHelp, + SectionTipsGlobalOptions, + } + return strings.TrimRightFunc(strings.Join(sections, ""), unicode.IsSpace) +} + +// OptionsHelpTemplate if the template for 'help' used by the 'options' command. +func OptionsHelpTemplate() string { + return "" +} + +// OptionsUsageTemplate if the template for 'usage' used by the 'options' command. +func OptionsUsageTemplate() string { + return `{{ if .HasInheritedFlags}}The following options can be passed to any command: + +{{flagsUsages .InheritedFlags}}{{end}}` +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resize.go b/vendor/k8s.io/kubectl/pkg/util/term/resize.go new file mode 100644 index 000000000..7ca09a858 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resize.go @@ -0,0 +1,132 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "fmt" + + "github.com/docker/docker/pkg/term" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// GetSize returns the current size of the user's terminal. If it isn't a terminal, +// nil is returned. +func (t TTY) GetSize() *remotecommand.TerminalSize { + outFd, isTerminal := term.GetFdInfo(t.Out) + if !isTerminal { + return nil + } + return GetSize(outFd) +} + +// GetSize returns the current size of the terminal associated with fd. +func GetSize(fd uintptr) *remotecommand.TerminalSize { + winsize, err := term.GetWinsize(fd) + if err != nil { + runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err)) + return nil + } + + return &remotecommand.TerminalSize{Width: winsize.Width, Height: winsize.Height} +} + +// MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with +// initialSizes, or nil if there's no TTY present. +func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecommand.TerminalSizeQueue { + outFd, isTerminal := term.GetFdInfo(t.Out) + if !isTerminal { + return nil + } + + t.sizeQueue = &sizeQueue{ + t: *t, + // make it buffered so we can send the initial terminal sizes without blocking, prior to starting + // the streaming below + resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)), + stopResizing: make(chan struct{}), + } + + t.sizeQueue.monitorSize(outFd, initialSizes...) + + return t.sizeQueue +} + +// sizeQueue implements remotecommand.TerminalSizeQueue +type sizeQueue struct { + t TTY + // resizeChan receives a Size each time the user's terminal is resized. + resizeChan chan remotecommand.TerminalSize + stopResizing chan struct{} +} + +// make sure sizeQueue implements the resize.TerminalSizeQueue interface +var _ remotecommand.TerminalSizeQueue = &sizeQueue{} + +// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each +// new event, it sends the current terminal size to resizeChan. +func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.TerminalSize) { + // send the initial sizes + for i := range initialSizes { + if initialSizes[i] != nil { + s.resizeChan <- *initialSizes[i] + } + } + + resizeEvents := make(chan remotecommand.TerminalSize, 1) + + monitorResizeEvents(outFd, resizeEvents, s.stopResizing) + + // listen for resize events in the background + go func() { + defer runtime.HandleCrash() + + for { + select { + case size, ok := <-resizeEvents: + if !ok { + return + } + + select { + // try to send the size to resizeChan, but don't block + case s.resizeChan <- size: + // send successful + default: + // unable to send / no-op + } + case <-s.stopResizing: + return + } + } + }() +} + +// Next returns the new terminal size after the terminal has been resized. It returns nil when +// monitoring has been stopped. +func (s *sizeQueue) Next() *remotecommand.TerminalSize { + size, ok := <-s.resizeChan + if !ok { + return nil + } + return &size +} + +// stop stops the background goroutine that is monitoring for terminal resizes. +func (s *sizeQueue) stop() { + close(s.stopResizing) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go new file mode 100644 index 000000000..e3476f978 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go @@ -0,0 +1,61 @@ +// +build !windows + +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "os" + "os/signal" + + "golang.org/x/sys/unix" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the +// terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send +// it to the resizeEvents channel. The goroutine stops when the stop channel is closed. +func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { + go func() { + defer runtime.HandleCrash() + + winch := make(chan os.Signal, 1) + signal.Notify(winch, unix.SIGWINCH) + defer signal.Stop(winch) + + for { + select { + case <-winch: + size := GetSize(fd) + if size == nil { + return + } + + // try to send size + select { + case resizeEvents <- *size: + // success + default: + // not sent + } + case <-stop: + return + } + } + }() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go new file mode 100644 index 000000000..adccf8734 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go @@ -0,0 +1,62 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "time" + + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// monitorResizeEvents spawns a goroutine that periodically gets the terminal size and tries to send +// it to the resizeEvents channel if the size has changed. The goroutine stops when the stop channel +// is closed. +func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { + go func() { + defer runtime.HandleCrash() + + size := GetSize(fd) + if size == nil { + return + } + lastSize := *size + + for { + // see if we need to stop running + select { + case <-stop: + return + default: + } + + size := GetSize(fd) + if size == nil { + return + } + + if size.Height != lastSize.Height || size.Width != lastSize.Width { + lastSize.Height = size.Height + lastSize.Width = size.Width + resizeEvents <- *size + } + + // sleep to avoid hot looping + time.Sleep(250 * time.Millisecond) + } + }() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/term.go b/vendor/k8s.io/kubectl/pkg/util/term/term.go new file mode 100644 index 000000000..18183c0c9 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/term.go @@ -0,0 +1,110 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "io" + "os" + + "github.com/docker/docker/pkg/term" + + "k8s.io/kubectl/pkg/util/interrupt" +) + +// SafeFunc is a function to be invoked by TTY. +type SafeFunc func() error + +// TTY helps invoke a function and preserve the state of the terminal, even if the process is +// terminated during execution. It also provides support for terminal resizing for remote command +// execution/attachment. +type TTY struct { + // In is a reader representing stdin. It is a required field. + In io.Reader + // Out is a writer representing stdout. It must be set to support terminal resizing. It is an + // optional field. + Out io.Writer + // Raw is true if the terminal should be set raw. + Raw bool + // TryDev indicates the TTY should try to open /dev/tty if the provided input + // is not a file descriptor. + TryDev bool + // Parent is an optional interrupt handler provided to this function - if provided + // it will be invoked after the terminal state is restored. If it is not provided, + // a signal received during the TTY will result in os.Exit(0) being invoked. + Parent *interrupt.Handler + + // sizeQueue is set after a call to MonitorSize() and is used to monitor SIGWINCH signals when the + // user's terminal resizes. + sizeQueue *sizeQueue +} + +// IsTerminalIn returns true if t.In is a terminal. Does not check /dev/tty +// even if TryDev is set. +func (t TTY) IsTerminalIn() bool { + return IsTerminal(t.In) +} + +// IsTerminalOut returns true if t.Out is a terminal. Does not check /dev/tty +// even if TryDev is set. +func (t TTY) IsTerminalOut() bool { + return IsTerminal(t.Out) +} + +// IsTerminal returns whether the passed object is a terminal or not +func IsTerminal(i interface{}) bool { + _, terminal := term.GetFdInfo(i) + return terminal +} + +// Safe invokes the provided function and will attempt to ensure that when the +// function returns (or a termination signal is sent) that the terminal state +// is reset to the condition it was in prior to the function being invoked. If +// t.Raw is true the terminal will be put into raw mode prior to calling the function. +// If the input file descriptor is not a TTY and TryDev is true, the /dev/tty file +// will be opened (if available). +func (t TTY) Safe(fn SafeFunc) error { + inFd, isTerminal := term.GetFdInfo(t.In) + + if !isTerminal && t.TryDev { + if f, err := os.Open("/dev/tty"); err == nil { + defer f.Close() + inFd = f.Fd() + isTerminal = term.IsTerminal(inFd) + } + } + if !isTerminal { + return fn() + } + + var state *term.State + var err error + if t.Raw { + state, err = term.MakeRaw(inFd) + } else { + state, err = term.SaveState(inFd) + } + if err != nil { + return err + } + return interrupt.Chain(t.Parent, func() { + if t.sizeQueue != nil { + t.sizeQueue.stop() + } + + term.RestoreTerminal(inFd, state) + }).Run(fn) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go b/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go new file mode 100644 index 000000000..2d72d1e45 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go @@ -0,0 +1,124 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "io" + "os" + + "github.com/docker/docker/pkg/term" + wordwrap "github.com/mitchellh/go-wordwrap" +) + +type wordWrapWriter struct { + limit uint + writer io.Writer +} + +// NewResponsiveWriter creates a Writer that detects the column width of the +// terminal we are in, and adjusts every line width to fit and use recommended +// terminal sizes for better readability. Does proper word wrapping automatically. +// if terminal width >= 120 columns use 120 columns +// if terminal width >= 100 columns use 100 columns +// if terminal width >= 80 columns use 80 columns +// In case we're not in a terminal or if it's smaller than 80 columns width, +// doesn't do any wrapping. +func NewResponsiveWriter(w io.Writer) io.Writer { + file, ok := w.(*os.File) + if !ok { + return w + } + fd := file.Fd() + if !term.IsTerminal(fd) { + return w + } + + terminalSize := GetSize(fd) + if terminalSize == nil { + return w + } + + var limit uint + switch { + case terminalSize.Width >= 120: + limit = 120 + case terminalSize.Width >= 100: + limit = 100 + case terminalSize.Width >= 80: + limit = 80 + } + + return NewWordWrapWriter(w, limit) +} + +// NewWordWrapWriter is a Writer that supports a limit of characters on every line +// and does auto word wrapping that respects that limit. +func NewWordWrapWriter(w io.Writer, limit uint) io.Writer { + return &wordWrapWriter{ + limit: limit, + writer: w, + } +} + +func (w wordWrapWriter) Write(p []byte) (nn int, err error) { + if w.limit == 0 { + return w.writer.Write(p) + } + original := string(p) + wrapped := wordwrap.WrapString(original, w.limit) + return w.writer.Write([]byte(wrapped)) +} + +// NewPunchCardWriter is a NewWordWrapWriter that limits the line width to 80 columns. +func NewPunchCardWriter(w io.Writer) io.Writer { + return NewWordWrapWriter(w, 80) +} + +type maxWidthWriter struct { + maxWidth uint + currentWidth uint + written uint + writer io.Writer +} + +// NewMaxWidthWriter is a Writer that supports a limit of characters on every +// line, but doesn't do any word wrapping automatically. +func NewMaxWidthWriter(w io.Writer, maxWidth uint) io.Writer { + return &maxWidthWriter{ + maxWidth: maxWidth, + writer: w, + } +} + +func (m maxWidthWriter) Write(p []byte) (nn int, err error) { + for _, b := range p { + if m.currentWidth == m.maxWidth { + m.writer.Write([]byte{'\n'}) + m.currentWidth = 0 + } + if b == '\n' { + m.currentWidth = 0 + } + _, err := m.writer.Write([]byte{b}) + if err != nil { + return int(m.written), err + } + m.written++ + m.currentWidth++ + } + return len(p), nil +} diff --git a/vendor/k8s.io/kubectl/pkg/validation/schema.go b/vendor/k8s.io/kubectl/pkg/validation/schema.go new file mode 100644 index 000000000..6eef61939 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/validation/schema.go @@ -0,0 +1,103 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package validation + +import ( + "bytes" + "encoding/json" + "fmt" + + ejson "github.com/exponent-io/jsonpath" + utilerrors "k8s.io/apimachinery/pkg/util/errors" +) + +// Schema is an interface that knows how to validate an API object serialized to a byte array. +type Schema interface { + ValidateBytes(data []byte) error +} + +// NullSchema always validates bytes. +type NullSchema struct{} + +// ValidateBytes never fails for NullSchema. +func (NullSchema) ValidateBytes(data []byte) error { return nil } + +// NoDoubleKeySchema is a schema that disallows double keys. +type NoDoubleKeySchema struct{} + +// ValidateBytes validates bytes. +func (NoDoubleKeySchema) ValidateBytes(data []byte) error { + var list []error + if err := validateNoDuplicateKeys(data, "metadata", "labels"); err != nil { + list = append(list, err) + } + if err := validateNoDuplicateKeys(data, "metadata", "annotations"); err != nil { + list = append(list, err) + } + return utilerrors.NewAggregate(list) +} + +func validateNoDuplicateKeys(data []byte, path ...string) error { + r := ejson.NewDecoder(bytes.NewReader(data)) + // This is Go being unfriendly. The 'path ...string' comes in as a + // []string, and SeekTo takes ...interface{}, so we can't just pass + // the path straight in, we have to copy it. *sigh* + ifacePath := []interface{}{} + for ix := range path { + ifacePath = append(ifacePath, path[ix]) + } + found, err := r.SeekTo(ifacePath...) + if err != nil { + return err + } + if !found { + return nil + } + seen := map[string]bool{} + for { + tok, err := r.Token() + if err != nil { + return err + } + switch t := tok.(type) { + case json.Delim: + if t.String() == "}" { + return nil + } + case ejson.KeyString: + if seen[string(t)] { + return fmt.Errorf("duplicate key: %s", string(t)) + } + seen[string(t)] = true + } + } +} + +// ConjunctiveSchema encapsulates a schema list. +type ConjunctiveSchema []Schema + +// ValidateBytes validates bytes per a ConjunctiveSchema. +func (c ConjunctiveSchema) ValidateBytes(data []byte) error { + var list []error + schemas := []Schema(c) + for ix := range schemas { + if err := schemas[ix].ValidateBytes(data); err != nil { + list = append(list, err) + } + } + return utilerrors.NewAggregate(list) +} diff --git a/vendor/k8s.io/utils/exec/doc.go b/vendor/k8s.io/utils/exec/doc.go new file mode 100644 index 000000000..cbb44bdb5 --- /dev/null +++ b/vendor/k8s.io/utils/exec/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package exec provides an injectable interface and implementations for running commands. +package exec // import "k8s.io/utils/exec" diff --git a/vendor/k8s.io/utils/exec/exec.go b/vendor/k8s.io/utils/exec/exec.go new file mode 100644 index 000000000..96bec01ca --- /dev/null +++ b/vendor/k8s.io/utils/exec/exec.go @@ -0,0 +1,252 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package exec + +import ( + "context" + "io" + osexec "os/exec" + "syscall" + "time" +) + +// ErrExecutableNotFound is returned if the executable is not found. +var ErrExecutableNotFound = osexec.ErrNotFound + +// Interface is an interface that presents a subset of the os/exec API. Use this +// when you want to inject fakeable/mockable exec behavior. +type Interface interface { + // Command returns a Cmd instance which can be used to run a single command. + // This follows the pattern of package os/exec. + Command(cmd string, args ...string) Cmd + + // CommandContext returns a Cmd instance which can be used to run a single command. + // + // The provided context is used to kill the process if the context becomes done + // before the command completes on its own. For example, a timeout can be set in + // the context. + CommandContext(ctx context.Context, cmd string, args ...string) Cmd + + // LookPath wraps os/exec.LookPath + LookPath(file string) (string, error) +} + +// Cmd is an interface that presents an API that is very similar to Cmd from os/exec. +// As more functionality is needed, this can grow. Since Cmd is a struct, we will have +// to replace fields with get/set method pairs. +type Cmd interface { + // Run runs the command to the completion. + Run() error + // CombinedOutput runs the command and returns its combined standard output + // and standard error. This follows the pattern of package os/exec. + CombinedOutput() ([]byte, error) + // Output runs the command and returns standard output, but not standard err + Output() ([]byte, error) + SetDir(dir string) + SetStdin(in io.Reader) + SetStdout(out io.Writer) + SetStderr(out io.Writer) + SetEnv(env []string) + + // StdoutPipe and StderrPipe for getting the process' Stdout and Stderr as + // Readers + StdoutPipe() (io.ReadCloser, error) + StderrPipe() (io.ReadCloser, error) + + // Start and Wait are for running a process non-blocking + Start() error + Wait() error + + // Stops the command by sending SIGTERM. It is not guaranteed the + // process will stop before this function returns. If the process is not + // responding, an internal timer function will send a SIGKILL to force + // terminate after 10 seconds. + Stop() +} + +// ExitError is an interface that presents an API similar to os.ProcessState, which is +// what ExitError from os/exec is. This is designed to make testing a bit easier and +// probably loses some of the cross-platform properties of the underlying library. +type ExitError interface { + String() string + Error() string + Exited() bool + ExitStatus() int +} + +// Implements Interface in terms of really exec()ing. +type executor struct{} + +// New returns a new Interface which will os/exec to run commands. +func New() Interface { + return &executor{} +} + +// Command is part of the Interface interface. +func (executor *executor) Command(cmd string, args ...string) Cmd { + return (*cmdWrapper)(osexec.Command(cmd, args...)) +} + +// CommandContext is part of the Interface interface. +func (executor *executor) CommandContext(ctx context.Context, cmd string, args ...string) Cmd { + return (*cmdWrapper)(osexec.CommandContext(ctx, cmd, args...)) +} + +// LookPath is part of the Interface interface +func (executor *executor) LookPath(file string) (string, error) { + return osexec.LookPath(file) +} + +// Wraps exec.Cmd so we can capture errors. +type cmdWrapper osexec.Cmd + +var _ Cmd = &cmdWrapper{} + +func (cmd *cmdWrapper) SetDir(dir string) { + cmd.Dir = dir +} + +func (cmd *cmdWrapper) SetStdin(in io.Reader) { + cmd.Stdin = in +} + +func (cmd *cmdWrapper) SetStdout(out io.Writer) { + cmd.Stdout = out +} + +func (cmd *cmdWrapper) SetStderr(out io.Writer) { + cmd.Stderr = out +} + +func (cmd *cmdWrapper) SetEnv(env []string) { + cmd.Env = env +} + +func (cmd *cmdWrapper) StdoutPipe() (io.ReadCloser, error) { + r, err := (*osexec.Cmd)(cmd).StdoutPipe() + return r, handleError(err) +} + +func (cmd *cmdWrapper) StderrPipe() (io.ReadCloser, error) { + r, err := (*osexec.Cmd)(cmd).StderrPipe() + return r, handleError(err) +} + +func (cmd *cmdWrapper) Start() error { + err := (*osexec.Cmd)(cmd).Start() + return handleError(err) +} + +func (cmd *cmdWrapper) Wait() error { + err := (*osexec.Cmd)(cmd).Wait() + return handleError(err) +} + +// Run is part of the Cmd interface. +func (cmd *cmdWrapper) Run() error { + err := (*osexec.Cmd)(cmd).Run() + return handleError(err) +} + +// CombinedOutput is part of the Cmd interface. +func (cmd *cmdWrapper) CombinedOutput() ([]byte, error) { + out, err := (*osexec.Cmd)(cmd).CombinedOutput() + return out, handleError(err) +} + +func (cmd *cmdWrapper) Output() ([]byte, error) { + out, err := (*osexec.Cmd)(cmd).Output() + return out, handleError(err) +} + +// Stop is part of the Cmd interface. +func (cmd *cmdWrapper) Stop() { + c := (*osexec.Cmd)(cmd) + + if c.Process == nil { + return + } + + c.Process.Signal(syscall.SIGTERM) + + time.AfterFunc(10*time.Second, func() { + if !c.ProcessState.Exited() { + c.Process.Signal(syscall.SIGKILL) + } + }) +} + +func handleError(err error) error { + if err == nil { + return nil + } + + switch e := err.(type) { + case *osexec.ExitError: + return &ExitErrorWrapper{e} + case *osexec.Error: + if e.Err == osexec.ErrNotFound { + return ErrExecutableNotFound + } + } + + return err +} + +// ExitErrorWrapper is an implementation of ExitError in terms of os/exec ExitError. +// Note: standard exec.ExitError is type *os.ProcessState, which already implements Exited(). +type ExitErrorWrapper struct { + *osexec.ExitError +} + +var _ ExitError = &ExitErrorWrapper{} + +// ExitStatus is part of the ExitError interface. +func (eew ExitErrorWrapper) ExitStatus() int { + ws, ok := eew.Sys().(syscall.WaitStatus) + if !ok { + panic("can't call ExitStatus() on a non-WaitStatus exitErrorWrapper") + } + return ws.ExitStatus() +} + +// CodeExitError is an implementation of ExitError consisting of an error object +// and an exit code (the upper bits of os.exec.ExitStatus). +type CodeExitError struct { + Err error + Code int +} + +var _ ExitError = CodeExitError{} + +func (e CodeExitError) Error() string { + return e.Err.Error() +} + +func (e CodeExitError) String() string { + return e.Err.Error() +} + +// Exited is to check if the process has finished +func (e CodeExitError) Exited() bool { + return true +} + +// ExitStatus is for checking the error code +func (e CodeExitError) ExitStatus() int { + return e.Code +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d710630f7..91965f3fe 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -7,9 +7,9 @@ github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm # github.com/Azure/go-autorest/autorest v0.9.0 => github.com/Azure/go-autorest/autorest v0.9.0 github.com/Azure/go-autorest/autorest +github.com/Azure/go-autorest/autorest/azure # github.com/Azure/go-autorest/autorest/adal v0.5.0 => github.com/Azure/go-autorest/autorest/adal v0.5.0 github.com/Azure/go-autorest/autorest/adal -github.com/Azure/go-autorest/autorest/azure # github.com/Azure/go-autorest/autorest/date v0.1.0 => github.com/Azure/go-autorest/autorest/date v0.1.0 github.com/Azure/go-autorest/autorest/date # github.com/Azure/go-autorest/logger v0.1.0 => github.com/Azure/go-autorest/logger v0.1.0 @@ -18,6 +18,8 @@ github.com/Azure/go-autorest/logger github.com/Azure/go-autorest/tracing # github.com/BurntSushi/toml v0.3.1 => github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml +# github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd +github.com/MakeNowJust/heredoc # github.com/Microsoft/go-winio v0.4.12 => github.com/Microsoft/go-winio v0.4.12 github.com/Microsoft/go-winio # github.com/NYTimes/gziphandler v1.1.1 => github.com/NYTimes/gziphandler v1.1.1 @@ -84,6 +86,11 @@ github.com/beorn7/perks/quantile github.com/blang/semver # github.com/cenkalti/backoff v2.2.1+incompatible => github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff +# github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 +github.com/chai2010/gettext-go/gettext +github.com/chai2010/gettext-go/gettext/mo +github.com/chai2010/gettext-go/gettext/plural +github.com/chai2010/gettext-go/gettext/po # github.com/cheekybits/genny v1.0.0 => github.com/cheekybits/genny v1.0.0 github.com/cheekybits/genny/generic # github.com/coreos/etcd v3.3.17+incompatible => github.com/coreos/etcd v3.3.17+incompatible @@ -170,9 +177,9 @@ github.com/elastic/go-elasticsearch/v7/estransport github.com/elastic/go-elasticsearch/v7/internal/version # github.com/emicklei/go-restful v2.9.5+incompatible => github.com/emicklei/go-restful v2.9.5+incompatible github.com/emicklei/go-restful +github.com/emicklei/go-restful/log # github.com/emicklei/go-restful-openapi v1.0.0 => github.com/emicklei/go-restful-openapi v1.0.0 github.com/emicklei/go-restful-openapi -github.com/emicklei/go-restful/log # github.com/emirpasic/gods v1.12.0 => github.com/emirpasic/gods v1.12.0 github.com/emirpasic/gods/containers github.com/emirpasic/gods/lists @@ -182,6 +189,8 @@ github.com/emirpasic/gods/trees/binaryheap github.com/emirpasic/gods/utils # github.com/evanphx/json-patch v4.5.0+incompatible => github.com/evanphx/json-patch v4.5.0+incompatible github.com/evanphx/json-patch +# github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d +github.com/exponent-io/jsonpath # github.com/fatih/camelcase v1.0.0 => github.com/fatih/camelcase v1.0.0 github.com/fatih/camelcase # github.com/fatih/color v1.7.0 => github.com/fatih/color v1.7.0 @@ -279,6 +288,8 @@ github.com/golang/protobuf/ptypes/empty github.com/golang/protobuf/ptypes/struct github.com/golang/protobuf/ptypes/timestamp github.com/golang/protobuf/ptypes/wrappers +# github.com/google/btree v1.0.0 => github.com/google/btree v1.0.0 +github.com/google/btree # github.com/google/go-cmp v0.3.0 => github.com/google/go-cmp v0.3.0 github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/internal/diff @@ -307,6 +318,9 @@ github.com/gophercloud/gophercloud/pagination github.com/gorilla/mux # github.com/gorilla/websocket v1.4.0 => github.com/gorilla/websocket v1.4.0 github.com/gorilla/websocket +# github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 +github.com/gregjones/httpcache +github.com/gregjones/httpcache/diskcache # github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 => github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-middleware github.com/grpc-ecosystem/go-grpc-middleware/recovery @@ -419,6 +433,8 @@ github.com/kubesphere/s2ioperator/pkg/util/reflectutils github.com/kubesphere/sonargo/sonar # github.com/leodido/go-urn v1.1.0 => github.com/leodido/go-urn v1.1.0 github.com/leodido/go-urn +# github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de +github.com/liggitt/tabwriter # github.com/lucas-clemente/quic-go v0.11.1 => github.com/lucas-clemente/quic-go v0.11.1 github.com/lucas-clemente/quic-go github.com/lucas-clemente/quic-go/h2quic @@ -489,6 +505,8 @@ github.com/mholt/certmagic github.com/miekg/dns # github.com/mitchellh/go-homedir v1.1.0 => github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir +# github.com/mitchellh/go-wordwrap v1.0.0 +github.com/mitchellh/go-wordwrap # github.com/mitchellh/mapstructure v1.1.2 => github.com/mitchellh/mapstructure v1.1.2 github.com/mitchellh/mapstructure # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd => github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd @@ -502,7 +520,7 @@ github.com/naoina/go-stringutil # github.com/naoina/toml v0.1.1 => github.com/naoina/toml v0.1.1 github.com/naoina/toml github.com/naoina/toml/ast -# github.com/onsi/ginkgo v1.8.0 => github.com/onsi/ginkgo v1.8.0 +# github.com/onsi/ginkgo v1.10.1 => github.com/onsi/ginkgo v1.8.0 github.com/onsi/ginkgo github.com/onsi/ginkgo/config github.com/onsi/ginkgo/extensions/table @@ -522,7 +540,7 @@ github.com/onsi/ginkgo/reporters/stenographer github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types -# github.com/onsi/gomega v1.5.0 => github.com/onsi/gomega v1.5.0 +# github.com/onsi/gomega v1.7.0 => github.com/onsi/gomega v1.5.0 github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/gbytes @@ -553,6 +571,8 @@ github.com/pborman/uuid github.com/pelletier/go-buffruneio # github.com/pelletier/go-toml v1.2.0 => github.com/pelletier/go-toml v1.2.0 github.com/pelletier/go-toml +# github.com/peterbourgon/diskv v2.0.1+incompatible => github.com/peterbourgon/diskv v2.0.1+incompatible +github.com/peterbourgon/diskv # github.com/pkg/errors v0.8.1 => github.com/pkg/errors v0.8.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 => github.com/pmezard/go-difflib v1.0.0 @@ -926,7 +946,7 @@ istio.io/client-go/pkg/listers/security/v1beta1 # istio.io/gogo-genproto v0.0.0-20190930162913-45029607206a => istio.io/gogo-genproto v0.0.0-20190930162913-45029607206a istio.io/gogo-genproto/googleapis/google/api istio.io/gogo-genproto/googleapis/google/rpc -# k8s.io/api v0.0.0-20191114100352-16d7abae0d2a => k8s.io/api v0.0.0-20191114100352-16d7abae0d2a +# k8s.io/api v0.17.0 => k8s.io/api v0.0.0-20191114100352-16d7abae0d2a k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 k8s.io/api/admissionregistration/v1 @@ -952,6 +972,7 @@ k8s.io/api/core/v1 k8s.io/api/discovery/v1alpha1 k8s.io/api/events/v1beta1 k8s.io/api/extensions/v1beta1 +k8s.io/api/imagepolicy/v1alpha1 k8s.io/api/networking/v1 k8s.io/api/networking/v1beta1 k8s.io/api/node/v1alpha1 @@ -975,7 +996,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1 -# k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb => k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb +# k8s.io/apimachinery v0.17.0 => k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/meta @@ -985,6 +1006,7 @@ k8s.io/apimachinery/pkg/api/validation/path k8s.io/apimachinery/pkg/apis/meta/internalversion k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/apis/meta/v1/unstructured +k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme k8s.io/apimachinery/pkg/apis/meta/v1/validation k8s.io/apimachinery/pkg/apis/meta/v1beta1 k8s.io/apimachinery/pkg/apis/meta/v1beta1/validation @@ -1005,6 +1027,7 @@ k8s.io/apimachinery/pkg/types k8s.io/apimachinery/pkg/util/cache k8s.io/apimachinery/pkg/util/clock k8s.io/apimachinery/pkg/util/diff +k8s.io/apimachinery/pkg/util/duration k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/framer k8s.io/apimachinery/pkg/util/httpstream @@ -1134,8 +1157,22 @@ k8s.io/apiserver/plugin/pkg/audit/truncate k8s.io/apiserver/plugin/pkg/audit/webhook k8s.io/apiserver/plugin/pkg/authenticator/token/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook -# k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 => k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 +# k8s.io/cli-runtime v0.17.0 +k8s.io/cli-runtime/pkg/genericclioptions +k8s.io/cli-runtime/pkg/kustomize +k8s.io/cli-runtime/pkg/kustomize/k8sdeps +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch +k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator +k8s.io/cli-runtime/pkg/printers +k8s.io/cli-runtime/pkg/resource +# k8s.io/client-go v0.17.0 => k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 k8s.io/client-go/discovery +k8s.io/client-go/discovery/cached/disk k8s.io/client-go/discovery/fake k8s.io/client-go/dynamic k8s.io/client-go/informers @@ -1318,6 +1355,14 @@ k8s.io/client-go/plugin/pkg/client/auth/openstack k8s.io/client-go/rest k8s.io/client-go/rest/watch k8s.io/client-go/restmapper +k8s.io/client-go/scale +k8s.io/client-go/scale/scheme +k8s.io/client-go/scale/scheme/appsint +k8s.io/client-go/scale/scheme/appsv1beta1 +k8s.io/client-go/scale/scheme/appsv1beta2 +k8s.io/client-go/scale/scheme/autoscalingv1 +k8s.io/client-go/scale/scheme/extensionsint +k8s.io/client-go/scale/scheme/extensionsv1beta1 k8s.io/client-go/testing k8s.io/client-go/third_party/forked/golang/template k8s.io/client-go/tools/auth @@ -1334,6 +1379,7 @@ k8s.io/client-go/tools/record k8s.io/client-go/tools/record/util k8s.io/client-go/tools/reference k8s.io/client-go/tools/remotecommand +k8s.io/client-go/tools/watch k8s.io/client-go/transport k8s.io/client-go/transport/spdy k8s.io/client-go/util/cert @@ -1345,7 +1391,7 @@ k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 +# k8s.io/code-generator v0.17.0 => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 k8s.io/code-generator/cmd/client-gen k8s.io/code-generator/cmd/client-gen/args k8s.io/code-generator/cmd/client-gen/generators @@ -1364,7 +1410,7 @@ k8s.io/code-generator/cmd/lister-gen/args k8s.io/code-generator/cmd/lister-gen/generators k8s.io/code-generator/pkg/namer k8s.io/code-generator/pkg/util -# k8s.io/component-base v0.0.0-20191114102325-35a9586014f7 => k8s.io/component-base v0.0.0-20191114102325-35a9586014f7 +# k8s.io/component-base v0.17.0 => k8s.io/component-base v0.0.0-20191114102325-35a9586014f7 k8s.io/component-base/cli/flag k8s.io/component-base/featuregate k8s.io/component-base/logs @@ -1393,9 +1439,24 @@ k8s.io/kube-openapi/pkg/handler k8s.io/kube-openapi/pkg/schemaconv k8s.io/kube-openapi/pkg/util k8s.io/kube-openapi/pkg/util/proto +k8s.io/kube-openapi/pkg/util/proto/validation k8s.io/kube-openapi/pkg/util/sets +# k8s.io/kubectl v0.17.0 +k8s.io/kubectl/pkg/cmd/get +k8s.io/kubectl/pkg/cmd/util +k8s.io/kubectl/pkg/generated +k8s.io/kubectl/pkg/rawhttp +k8s.io/kubectl/pkg/scheme +k8s.io/kubectl/pkg/util/i18n +k8s.io/kubectl/pkg/util/interrupt +k8s.io/kubectl/pkg/util/openapi +k8s.io/kubectl/pkg/util/openapi/validation +k8s.io/kubectl/pkg/util/templates +k8s.io/kubectl/pkg/util/term +k8s.io/kubectl/pkg/validation # k8s.io/utils v0.0.0-20191114184206-e782cd3c129f => k8s.io/utils v0.0.0-20191114184206-e782cd3c129f k8s.io/utils/buffer +k8s.io/utils/exec k8s.io/utils/integer k8s.io/utils/path k8s.io/utils/pointer @@ -1471,6 +1532,29 @@ sigs.k8s.io/controller-tools/pkg/schemapatcher sigs.k8s.io/controller-tools/pkg/schemapatcher/internal/yaml sigs.k8s.io/controller-tools/pkg/version sigs.k8s.io/controller-tools/pkg/webhook +# sigs.k8s.io/kustomize v2.0.3+incompatible +sigs.k8s.io/kustomize/pkg/commands/build +sigs.k8s.io/kustomize/pkg/constants +sigs.k8s.io/kustomize/pkg/expansion +sigs.k8s.io/kustomize/pkg/factory +sigs.k8s.io/kustomize/pkg/fs +sigs.k8s.io/kustomize/pkg/git +sigs.k8s.io/kustomize/pkg/gvk +sigs.k8s.io/kustomize/pkg/ifc +sigs.k8s.io/kustomize/pkg/ifc/transformer +sigs.k8s.io/kustomize/pkg/image +sigs.k8s.io/kustomize/pkg/internal/error +sigs.k8s.io/kustomize/pkg/loader +sigs.k8s.io/kustomize/pkg/patch +sigs.k8s.io/kustomize/pkg/patch/transformer +sigs.k8s.io/kustomize/pkg/resid +sigs.k8s.io/kustomize/pkg/resmap +sigs.k8s.io/kustomize/pkg/resource +sigs.k8s.io/kustomize/pkg/target +sigs.k8s.io/kustomize/pkg/transformers +sigs.k8s.io/kustomize/pkg/transformers/config +sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig +sigs.k8s.io/kustomize/pkg/types # sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca => sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca sigs.k8s.io/structured-merge-diff/fieldpath sigs.k8s.io/structured-merge-diff/merge @@ -1483,3 +1567,5 @@ sigs.k8s.io/testing_frameworks/integration/addr sigs.k8s.io/testing_frameworks/integration/internal # sigs.k8s.io/yaml v1.1.0 => sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml +# vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc +vbom.ml/util/sortorder diff --git a/vendor/sigs.k8s.io/kustomize/LICENSE b/vendor/sigs.k8s.io/kustomize/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go new file mode 100644 index 000000000..e62747e32 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/commands/build/build.go @@ -0,0 +1,129 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package build + +import ( + "io" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + "sigs.k8s.io/kustomize/pkg/loader" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/target" +) + +// Options contain the options for running a build +type Options struct { + kustomizationPath string + outputPath string +} + +// NewOptions creates a Options object +func NewOptions(p, o string) *Options { + return &Options{ + kustomizationPath: p, + outputPath: o, + } +} + +var examples = ` +Use the file somedir/kustomization.yaml to generate a set of api resources: + build somedir + +Use a url pointing to a remote directory/kustomization.yaml to generate a set of api resources: + build url +The url should follow hashicorp/go-getter URL format described in +https://github.com/hashicorp/go-getter#url-format + +url examples: + sigs.k8s.io/kustomize//examples/multibases?ref=v1.0.6 + github.com/Liujingfang1/mysql + github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2 +` + +// NewCmdBuild creates a new build command. +func NewCmdBuild( + out io.Writer, fs fs.FileSystem, + rf *resmap.Factory, + ptf transformer.Factory) *cobra.Command { + var o Options + + cmd := &cobra.Command{ + Use: "build [path]", + Short: "Print current configuration per contents of " + constants.KustomizationFileNames[0], + Example: examples, + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + err := o.Validate(args) + if err != nil { + return err + } + return o.RunBuild(out, fs, rf, ptf) + }, + } + cmd.Flags().StringVarP( + &o.outputPath, + "output", "o", "", + "If specified, write the build output to this path.") + return cmd +} + +// Validate validates build command. +func (o *Options) Validate(args []string) error { + if len(args) > 1 { + return errors.New("specify one path to " + constants.KustomizationFileNames[0]) + } + if len(args) == 0 { + o.kustomizationPath = "./" + } else { + o.kustomizationPath = args[0] + } + + return nil +} + +// RunBuild runs build command. +func (o *Options) RunBuild( + out io.Writer, fSys fs.FileSystem, + rf *resmap.Factory, ptf transformer.Factory) error { + ldr, err := loader.NewLoader(o.kustomizationPath, fSys) + if err != nil { + return err + } + defer ldr.Cleanup() + kt, err := target.NewKustTarget(ldr, rf, ptf) + if err != nil { + return err + } + allResources, err := kt.MakeCustomizedResMap() + if err != nil { + return err + } + // Output the objects. + res, err := allResources.EncodeAsYaml() + if err != nil { + return err + } + if o.outputPath != "" { + return fSys.WriteFile(o.outputPath, res) + } + _, err = out.Write(res) + return err +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go b/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go new file mode 100644 index 000000000..dd50230fb --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/constants/constants.go @@ -0,0 +1,28 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package constants holds global constants for the kustomize tool. +package constants + +// KustomizationFileNames is a list of filenames that can be recognized and consumbed +// by Kustomize. +// In each directory, Kustomize searches for file with the name in this list. +// Only one match is allowed. +var KustomizationFileNames = []string{ + "kustomization.yaml", + "kustomization.yml", + "Kustomization", +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go b/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go new file mode 100644 index 000000000..de55e4614 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/expansion/expand.go @@ -0,0 +1,121 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package expansion provides functions find and replace $(FOO) style variables in strings. +package expansion + +import ( + "bytes" +) + +const ( + operator = '$' + referenceOpener = '(' + referenceCloser = ')' +) + +// syntaxWrap returns the input string wrapped by the expansion syntax. +func syntaxWrap(input string) string { + return string(operator) + string(referenceOpener) + input + string(referenceCloser) +} + +// MappingFuncFor returns a mapping function for use with Expand that +// implements the expansion semantics defined in the expansion spec; it +// returns the input string wrapped in the expansion syntax if no mapping +// for the input is found. +func MappingFuncFor( + counts map[string]int, + context ...map[string]string) func(string) string { + return func(input string) string { + for _, vars := range context { + val, ok := vars[input] + if ok { + counts[input]++ + return val + } + } + return syntaxWrap(input) + } +} + +// Expand replaces variable references in the input string according to +// the expansion spec using the given mapping function to resolve the +// values of variables. +func Expand(input string, mapping func(string) string) string { + var buf bytes.Buffer + checkpoint := 0 + for cursor := 0; cursor < len(input); cursor++ { + if input[cursor] == operator && cursor+1 < len(input) { + // Copy the portion of the input string since the last + // checkpoint into the buffer + buf.WriteString(input[checkpoint:cursor]) + + // Attempt to read the variable name as defined by the + // syntax from the input string + read, isVar, advance := tryReadVariableName(input[cursor+1:]) + + if isVar { + // We were able to read a variable name correctly; + // apply the mapping to the variable name and copy the + // bytes into the buffer + buf.WriteString(mapping(read)) + } else { + // Not a variable name; copy the read bytes into the buffer + buf.WriteString(read) + } + + // Advance the cursor in the input string to account for + // bytes consumed to read the variable name expression + cursor += advance + + // Advance the checkpoint in the input string + checkpoint = cursor + 1 + } + } + + // Return the buffer and any remaining unwritten bytes in the + // input string. + return buf.String() + input[checkpoint:] +} + +// tryReadVariableName attempts to read a variable name from the input +// string and returns the content read from the input, whether that content +// represents a variable name to perform mapping on, and the number of bytes +// consumed in the input string. +// +// The input string is assumed not to contain the initial operator. +func tryReadVariableName(input string) (string, bool, int) { + switch input[0] { + case operator: + // Escaped operator; return it. + return input[0:1], false, 1 + case referenceOpener: + // Scan to expression closer + for i := 1; i < len(input); i++ { + if input[i] == referenceCloser { + return input[1:i], true, i + 1 + } + } + + // Incomplete reference; return it. + return string(operator) + string(referenceOpener), false, 1 + default: + // Not the beginning of an expression, ie, an operator + // that doesn't begin an expression. Return the operator + // and the first rune in the string. + return string(operator) + string(input[0]), false, 1 + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go new file mode 100644 index 000000000..e71669a87 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/factory/factory.go @@ -0,0 +1,39 @@ +/* +Copyright 2018 The Kubernetes Authors. + Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Package factory provides factories for kustomize. +package factory + +import ( + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" +) + +// KustFactory provides different factories for kustomize +type KustFactory struct { + ResmapF *resmap.Factory + TransformerF transformer.Factory + ValidatorF ifc.Validator + UnstructF ifc.KunstructuredFactory +} + +// NewKustFactory creats a KustFactory instance +func NewKustFactory(u ifc.KunstructuredFactory, v ifc.Validator, t transformer.Factory) *KustFactory { + return &KustFactory{ + ResmapF: resmap.NewFactory(resource.NewFactory(u)), + TransformerF: t, + ValidatorF: v, + UnstructF: u, + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/confirmeddir.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/confirmeddir.go new file mode 100644 index 000000000..5d12bf077 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/confirmeddir.go @@ -0,0 +1,93 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "io/ioutil" + "path/filepath" + "strings" +) + +// ConfirmedDir is a clean, absolute, delinkified path +// that was confirmed to point to an existing directory. +type ConfirmedDir string + +// NewTmpConfirmedDir returns a temporary dir, else error. +// The directory is cleaned, no symlinks, etc. so its +// returned as a ConfirmedDir. +func NewTmpConfirmedDir() (ConfirmedDir, error) { + n, err := ioutil.TempDir("", "kustomize-") + if err != nil { + return "", err + } + + // In MacOs `ioutil.TempDir` creates a directory + // with root in the `/var` folder, which is in turn a symlinked path + // to `/private/var`. + // Function `filepath.EvalSymlinks`is used to + // resolve the real absolute path. + deLinked, err := filepath.EvalSymlinks(n) + return ConfirmedDir(deLinked), err + +} + +// HasPrefix returns true if the directory argument +// is a prefix of self (d) from the point of view of +// a file system. +// +// I.e., it's true if the argument equals or contains +// self (d) in a file path sense. +// +// HasPrefix emulates the semantics of strings.HasPrefix +// such that the following are true: +// +// strings.HasPrefix("foobar", "foobar") +// strings.HasPrefix("foobar", "foo") +// strings.HasPrefix("foobar", "") +// +// d := fSys.ConfirmDir("/foo/bar") +// d.HasPrefix("/foo/bar") +// d.HasPrefix("/foo") +// d.HasPrefix("/") +// +// Not contacting a file system here to check for +// actual path existence. +// +// This is tested on linux, but will have trouble +// on other operating systems. +// TODO(monopole) Refactor when #golang/go/18358 closes. +// See also: +// https://github.com/golang/go/issues/18358 +// https://github.com/golang/dep/issues/296 +// https://github.com/golang/dep/blob/master/internal/fs/fs.go#L33 +// https://codereview.appspot.com/5712045 +func (d ConfirmedDir) HasPrefix(path ConfirmedDir) bool { + if path.String() == string(filepath.Separator) || path == d { + return true + } + return strings.HasPrefix( + string(d), + string(path)+string(filepath.Separator)) +} + +func (d ConfirmedDir) Join(path string) string { + return filepath.Join(string(d), path) +} + +func (d ConfirmedDir) String() string { + return string(d) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go new file mode 100644 index 000000000..64bc55685 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefile.go @@ -0,0 +1,69 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "bytes" + "os" +) + +var _ File = &FakeFile{} + +// FakeFile implements File in-memory for tests. +type FakeFile struct { + name string + content []byte + dir bool + open bool +} + +// makeDir makes a fake directory. +func makeDir(name string) *FakeFile { + return &FakeFile{name: name, dir: true} +} + +// Close marks the fake file closed. +func (f *FakeFile) Close() error { + f.open = false + return nil +} + +// Read never fails, and doesn't mutate p. +func (f *FakeFile) Read(p []byte) (n int, err error) { + return len(p), nil +} + +// Write saves the contents of the argument to memory. +func (f *FakeFile) Write(p []byte) (n int, err error) { + f.content = p + return len(p), nil +} + +// ContentMatches returns true if v matches fake file's content. +func (f *FakeFile) ContentMatches(v []byte) bool { + return bytes.Equal(v, f.content) +} + +// GetContent the content of a fake file. +func (f *FakeFile) GetContent() []byte { + return f.content +} + +// Stat returns nil. +func (f *FakeFile) Stat() (os.FileInfo, error) { + return nil, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go new file mode 100644 index 000000000..6ccca9150 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefileinfo.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "os" + "time" +) + +var _ os.FileInfo = &Fakefileinfo{} + +// Fakefileinfo implements Fakefileinfo using a fake in-memory filesystem. +type Fakefileinfo struct { + *FakeFile +} + +// Name returns the name of the file +func (fi *Fakefileinfo) Name() string { return fi.name } + +// Size returns the size of the file +func (fi *Fakefileinfo) Size() int64 { return int64(len(fi.content)) } + +// Mode returns the file mode +func (fi *Fakefileinfo) Mode() os.FileMode { return 0777 } + +// ModTime returns the modification time +func (fi *Fakefileinfo) ModTime() time.Time { return time.Time{} } + +// IsDir returns if it is a directory +func (fi *Fakefileinfo) IsDir() bool { return fi.dir } + +// Sys should return underlying data source, but it now returns nil +func (fi *Fakefileinfo) Sys() interface{} { return nil } diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go new file mode 100644 index 000000000..59c0966b2 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fakefs.go @@ -0,0 +1,185 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "fmt" + "path/filepath" + "sort" + "strings" + + "sigs.k8s.io/kustomize/pkg/constants" +) + +var _ FileSystem = &fakeFs{} + +// fakeFs implements FileSystem using a fake in-memory filesystem. +type fakeFs struct { + m map[string]*FakeFile +} + +// MakeFakeFS returns an instance of fakeFs with no files in it. +func MakeFakeFS() *fakeFs { + result := &fakeFs{m: map[string]*FakeFile{}} + result.Mkdir("/") + return result +} + +// kustomizationContent is used in tests. +const kustomizationContent = `apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namePrefix: some-prefix +nameSuffix: some-suffix +# Labels to add to all objects and selectors. +# These labels would also be used to form the selector for apply --prune +# Named differently than “labels” to avoid confusion with metadata for this object +commonLabels: + app: helloworld +commonAnnotations: + note: This is an example annotation +resources: [] +#- service.yaml +#- ../some-dir/ +# There could also be configmaps in Base, which would make these overlays +configMapGenerator: [] +# There could be secrets in Base, if just using a fork/rebase workflow +secretGenerator: [] +` + +// Create assures a fake file appears in the in-memory file system. +func (fs *fakeFs) Create(name string) (File, error) { + f := &FakeFile{} + f.open = true + fs.m[name] = f + return fs.m[name], nil +} + +// Mkdir assures a fake directory appears in the in-memory file system. +func (fs *fakeFs) Mkdir(name string) error { + fs.m[name] = makeDir(name) + return nil +} + +// MkdirAll delegates to Mkdir +func (fs *fakeFs) MkdirAll(name string) error { + return fs.Mkdir(name) +} + +// RemoveAll presumably does rm -r on a path. +// There's no error. +func (fs *fakeFs) RemoveAll(name string) error { + var toRemove []string + for k := range fs.m { + if strings.HasPrefix(k, name) { + toRemove = append(toRemove, k) + } + } + for _, k := range toRemove { + delete(fs.m, k) + } + return nil +} + +// Open returns a fake file in the open state. +func (fs *fakeFs) Open(name string) (File, error) { + if _, found := fs.m[name]; !found { + return nil, fmt.Errorf("file %q cannot be opened", name) + } + return fs.m[name], nil +} + +// CleanedAbs cannot fail. +func (fs *fakeFs) CleanedAbs(path string) (ConfirmedDir, string, error) { + if fs.IsDir(path) { + return ConfirmedDir(path), "", nil + } + d := filepath.Dir(path) + if d == path { + return ConfirmedDir(d), "", nil + } + return ConfirmedDir(d), filepath.Base(path), nil +} + +// Exists returns true if file is known. +func (fs *fakeFs) Exists(name string) bool { + _, found := fs.m[name] + return found +} + +// Glob returns the list of matching files +func (fs *fakeFs) Glob(pattern string) ([]string, error) { + var result []string + for p := range fs.m { + if fs.pathMatch(p, pattern) { + result = append(result, p) + } + } + sort.Strings(result) + return result, nil +} + +// IsDir returns true if the file exists and is a directory. +func (fs *fakeFs) IsDir(name string) bool { + f, found := fs.m[name] + if found && f.dir { + return true + } + if !strings.HasSuffix(name, "/") { + name = name + "/" + } + for k := range fs.m { + if strings.HasPrefix(k, name) { + return true + } + } + return false +} + +// ReadFile always returns an empty bytes and error depending on content of m. +func (fs *fakeFs) ReadFile(name string) ([]byte, error) { + if ff, found := fs.m[name]; found { + return ff.content, nil + } + return nil, fmt.Errorf("cannot read file %q", name) +} + +func (fs *fakeFs) ReadTestKustomization() ([]byte, error) { + return fs.ReadFile(constants.KustomizationFileNames[0]) +} + +// WriteFile always succeeds and does nothing. +func (fs *fakeFs) WriteFile(name string, c []byte) error { + ff := &FakeFile{} + ff.Write(c) + fs.m[name] = ff + return nil +} + +// WriteTestKustomization writes a standard test file. +func (fs *fakeFs) WriteTestKustomization() { + fs.WriteTestKustomizationWith([]byte(kustomizationContent)) +} + +// WriteTestKustomizationWith writes a standard test file. +func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) { + fs.WriteFile(constants.KustomizationFileNames[0], bytes) +} + +func (fs *fakeFs) pathMatch(path, pattern string) bool { + match, _ := filepath.Match(pattern, path) + return match +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go new file mode 100644 index 000000000..4b47dba64 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/fs.go @@ -0,0 +1,44 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package fs provides a file system abstraction layer. +package fs + +import ( + "io" + "os" +) + +// FileSystem groups basic os filesystem methods. +type FileSystem interface { + Create(name string) (File, error) + Mkdir(name string) error + MkdirAll(name string) error + RemoveAll(name string) error + Open(name string) (File, error) + IsDir(name string) bool + CleanedAbs(path string) (ConfirmedDir, string, error) + Exists(name string) bool + Glob(pattern string) ([]string, error) + ReadFile(name string) ([]byte, error) + WriteFile(name string, data []byte) error +} + +// File groups the basic os.File methods. +type File interface { + io.ReadWriteCloser + Stat() (os.FileInfo, error) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go new file mode 100644 index 000000000..5bfec55ab --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfile.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "os" +) + +var _ File = &realFile{} + +// realFile implements File using the local filesystem. +type realFile struct { + file *os.File +} + +// Close closes a file. +func (f *realFile) Close() error { return f.file.Close() } + +// Read reads a file's content. +func (f *realFile) Read(p []byte) (n int, err error) { return f.file.Read(p) } + +// Write writes bytes to a file +func (f *realFile) Write(p []byte) (n int, err error) { return f.file.Write(p) } + +// Stat returns an interface which has all the information regarding the file. +func (f *realFile) Stat() (os.FileInfo, error) { return f.file.Stat() } diff --git a/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go new file mode 100644 index 000000000..11e5813b7 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/fs/realfs.go @@ -0,0 +1,122 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fs + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" +) + +var _ FileSystem = realFS{} + +// realFS implements FileSystem using the local filesystem. +type realFS struct{} + +// MakeRealFS makes an instance of realFS. +func MakeRealFS() FileSystem { + return realFS{} +} + +// Create delegates to os.Create. +func (realFS) Create(name string) (File, error) { return os.Create(name) } + +// Mkdir delegates to os.Mkdir. +func (realFS) Mkdir(name string) error { + return os.Mkdir(name, 0777|os.ModeDir) +} + +// MkdirAll delegates to os.MkdirAll. +func (realFS) MkdirAll(name string) error { + return os.MkdirAll(name, 0777|os.ModeDir) +} + +// RemoveAll delegates to os.RemoveAll. +func (realFS) RemoveAll(name string) error { + return os.RemoveAll(name) +} + +// Open delegates to os.Open. +func (realFS) Open(name string) (File, error) { return os.Open(name) } + +// CleanedAbs returns a cleaned, absolute path +// with no symbolic links split into directory +// and file components. If the entire path is +// a directory, the file component is an empty +// string. +func (x realFS) CleanedAbs( + path string) (ConfirmedDir, string, error) { + absRoot, err := filepath.Abs(path) + if err != nil { + return "", "", fmt.Errorf( + "abs path error on '%s' : %v", path, err) + } + deLinked, err := filepath.EvalSymlinks(absRoot) + if err != nil { + return "", "", fmt.Errorf( + "evalsymlink failure on '%s' : %v", path, err) + } + if x.IsDir(deLinked) { + return ConfirmedDir(deLinked), "", nil + } + d := filepath.Dir(deLinked) + if !x.IsDir(d) { + // Programmer/assumption error. + log.Fatalf("first part of '%s' not a directory", deLinked) + } + if d == deLinked { + // Programmer/assumption error. + log.Fatalf("d '%s' should be a subset of deLinked", d) + } + f := filepath.Base(deLinked) + if filepath.Join(d, f) != deLinked { + // Programmer/assumption error. + log.Fatalf("these should be equal: '%s', '%s'", + filepath.Join(d, f), deLinked) + } + return ConfirmedDir(d), f, nil +} + +// Exists returns true if os.Stat succeeds. +func (realFS) Exists(name string) bool { + _, err := os.Stat(name) + return err == nil +} + +// Glob returns the list of matching files +func (realFS) Glob(pattern string) ([]string, error) { + return filepath.Glob(pattern) +} + +// IsDir delegates to os.Stat and FileInfo.IsDir +func (realFS) IsDir(name string) bool { + info, err := os.Stat(name) + if err != nil { + return false + } + return info.IsDir() +} + +// ReadFile delegates to ioutil.ReadFile. +func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) } + +// WriteFile delegates to ioutil.WriteFile with read/write permissions. +func (realFS) WriteFile(name string, c []byte) error { + return ioutil.WriteFile(name, c, 0666) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/git/cloner.go b/vendor/sigs.k8s.io/kustomize/pkg/git/cloner.go new file mode 100644 index 000000000..465fdb1d1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/git/cloner.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package git + +import ( + "bytes" + "os/exec" + + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/fs" +) + +// Cloner is a function that can clone a git repo. +type Cloner func(repoSpec *RepoSpec) error + +// ClonerUsingGitExec uses a local git install, as opposed +// to say, some remote API, to obtain a local clone of +// a remote repo. +func ClonerUsingGitExec(repoSpec *RepoSpec) error { + gitProgram, err := exec.LookPath("git") + if err != nil { + return errors.Wrap(err, "no 'git' program on path") + } + repoSpec.cloneDir, err = fs.NewTmpConfirmedDir() + if err != nil { + return err + } + cmd := exec.Command( + gitProgram, + "clone", + repoSpec.CloneSpec(), + repoSpec.cloneDir.String()) + var out bytes.Buffer + cmd.Stdout = &out + err = cmd.Run() + if err != nil { + return errors.Wrapf(err, "trouble cloning %s", repoSpec.raw) + } + if repoSpec.ref == "" { + return nil + } + cmd = exec.Command(gitProgram, "checkout", repoSpec.ref) + cmd.Dir = repoSpec.cloneDir.String() + err = cmd.Run() + if err != nil { + return errors.Wrapf( + err, "trouble checking out href %s", repoSpec.ref) + } + return nil +} + +// DoNothingCloner returns a cloner that only sets +// cloneDir field in the repoSpec. It's assumed that +// the cloneDir is associated with some fake filesystem +// used in a test. +func DoNothingCloner(dir fs.ConfirmedDir) Cloner { + return func(rs *RepoSpec) error { + rs.cloneDir = dir + return nil + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/git/repospec.go b/vendor/sigs.k8s.io/kustomize/pkg/git/repospec.go new file mode 100644 index 000000000..b3251f653 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/git/repospec.go @@ -0,0 +1,214 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package git + +import ( + "fmt" + "path/filepath" + "strings" + + "sigs.k8s.io/kustomize/pkg/fs" +) + +// Used as a temporary non-empty occupant of the cloneDir +// field, as something distinguishable from the empty string +// in various outputs (especially tests). Not using an +// actual directory name here, as that's a temporary directory +// with a unique name that isn't created until clone time. +const notCloned = fs.ConfirmedDir("/notCloned") + +// RepoSpec specifies a git repository and a branch and path therein. +type RepoSpec struct { + // Raw, original spec, used to look for cycles. + // TODO(monopole): Drop raw, use processed fields instead. + raw string + + // Host, e.g. github.com + host string + + // orgRepo name (organization/repoName), + // e.g. kubernetes-sigs/kustomize + orgRepo string + + // ConfirmedDir where the orgRepo is cloned to. + cloneDir fs.ConfirmedDir + + // Relative path in the repository, and in the cloneDir, + // to a Kustomization. + path string + + // Branch or tag reference. + ref string +} + +// CloneSpec returns a string suitable for "git clone {spec}". +func (x *RepoSpec) CloneSpec() string { + if isAzureHost(x.host) || isAWSHost(x.host) { + return x.host + x.orgRepo + } + return x.host + x.orgRepo + gitSuffix +} + +func (x *RepoSpec) CloneDir() fs.ConfirmedDir { + return x.cloneDir +} + +func (x *RepoSpec) Raw() string { + return x.raw +} + +func (x *RepoSpec) AbsPath() string { + return x.cloneDir.Join(x.path) +} + +func (x *RepoSpec) Cleaner(fSys fs.FileSystem) func() error { + return func() error { return fSys.RemoveAll(x.cloneDir.String()) } +} + +// From strings like git@github.com:someOrg/someRepo.git or +// https://github.com/someOrg/someRepo?ref=someHash, extract +// the parts. +func NewRepoSpecFromUrl(n string) (*RepoSpec, error) { + if filepath.IsAbs(n) { + return nil, fmt.Errorf("uri looks like abs path: %s", n) + } + host, orgRepo, path, gitRef := parseGithubUrl(n) + if orgRepo == "" { + return nil, fmt.Errorf("url lacks orgRepo: %s", n) + } + if host == "" { + return nil, fmt.Errorf("url lacks host: %s", n) + } + return &RepoSpec{ + raw: n, host: host, orgRepo: orgRepo, + cloneDir: notCloned, path: path, ref: gitRef}, nil +} + +const ( + refQuery = "?ref=" + gitSuffix = ".git" +) + +// From strings like git@github.com:someOrg/someRepo.git or +// https://github.com/someOrg/someRepo?ref=someHash, extract +// the parts. +func parseGithubUrl(n string) ( + host string, orgRepo string, path string, gitRef string) { + host, n = parseHostSpec(n) + + if strings.Contains(n, gitSuffix) { + index := strings.Index(n, gitSuffix) + orgRepo = n[0:index] + n = n[index+len(gitSuffix):] + path, gitRef = peelQuery(n) + return + } + + i := strings.Index(n, "/") + if i < 1 { + return "", "", "", "" + } + j := strings.Index(n[i+1:], "/") + if j >= 0 { + j += i + 1 + orgRepo = n[:j] + path, gitRef = peelQuery(n[j+1:]) + } else { + path = "" + orgRepo, gitRef = peelQuery(n) + } + return +} + +func peelQuery(arg string) (string, string) { + j := strings.Index(arg, refQuery) + if j >= 0 { + return arg[:j], arg[j+len(refQuery):] + } + return arg, "" +} + +func parseHostSpec(n string) (string, string) { + var host string + // Start accumulating the host part. + for _, p := range []string{ + // Order matters here. + "git::", "gh:", "ssh://", "https://", "http://", + "git@", "github.com:", "github.com/"} { + if len(p) < len(n) && strings.ToLower(n[:len(p)]) == p { + n = n[len(p):] + host += p + } + } + if host == "git@" { + i := strings.Index(n, "/") + if i > -1 { + host += n[:i+1] + n = n[i+1:] + } else { + i = strings.Index(n, ":") + if i > -1 { + host += n[:i+1] + n = n[i+1:] + } + } + return host, n + } + + // If host is a http(s) or ssh URL, grab the domain part. + for _, p := range []string{ + "ssh://", "https://", "http://"} { + if strings.HasSuffix(host, p) { + i := strings.Index(n, "/") + if i > -1 { + host = host + n[0:i+1] + n = n[i+1:] + } + break + } + } + + return normalizeGitHostSpec(host), n +} + +func normalizeGitHostSpec(host string) string { + s := strings.ToLower(host) + if strings.Contains(s, "github.com") { + if strings.Contains(s, "git@") || strings.Contains(s, "ssh:") { + host = "git@github.com:" + } else { + host = "https://github.com/" + } + } + if strings.HasPrefix(s, "git::") { + host = strings.TrimLeft(s, "git::") + } + return host +} + +// The format of Azure repo URL is documented +// https://docs.microsoft.com/en-us/azure/devops/repos/git/clone?view=vsts&tabs=visual-studio#clone_url +func isAzureHost(host string) bool { + return strings.Contains(host, "dev.azure.com") || + strings.Contains(host, "visualstudio.com") +} + +// The format of AWS repo URL is documented +// https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html +func isAWSHost(host string) bool { + return strings.Contains(host, "amazonaws.com") +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go b/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go new file mode 100644 index 000000000..890c8e8b5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/gvk/gvk.go @@ -0,0 +1,180 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gvk + +import ( + "strings" +) + +// Gvk identifies a Kubernetes API type. +// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md +type Gvk struct { + Group string `json:"group,omitempty" yaml:"group,omitempty"` + Version string `json:"version,omitempty" yaml:"version,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` +} + +// FromKind makes a Gvk with only the kind specified. +func FromKind(k string) Gvk { + return Gvk{ + Kind: k, + } +} + +// Values that are brief but meaningful in logs. +const ( + noGroup = "~G" + noVersion = "~V" + noKind = "~K" + separator = "_" +) + +// String returns a string representation of the GVK. +func (x Gvk) String() string { + g := x.Group + if g == "" { + g = noGroup + } + v := x.Version + if v == "" { + v = noVersion + } + k := x.Kind + if k == "" { + k = noKind + } + return strings.Join([]string{g, v, k}, separator) +} + +// Equals returns true if the Gvk's have equal fields. +func (x Gvk) Equals(o Gvk) bool { + return x.Group == o.Group && x.Version == o.Version && x.Kind == o.Kind +} + +// An attempt to order things to help k8s, e.g. +// a Service should come before things that refer to it. +// Namespace should be first. +// In some cases order just specified to provide determinism. +var order = []string{ + "Namespace", + "StorageClass", + "CustomResourceDefinition", + "MutatingWebhookConfiguration", + "ValidatingWebhookConfiguration", + "ServiceAccount", + "Role", + "ClusterRole", + "RoleBinding", + "ClusterRoleBinding", + "ConfigMap", + "Secret", + "Service", + "Deployment", + "StatefulSet", + "CronJob", + "PodDisruptionBudget", +} +var typeOrders = func() map[string]int { + m := map[string]int{} + for i, n := range order { + m[n] = i + } + return m +}() + +// IsLessThan returns true if self is less than the argument. +func (x Gvk) IsLessThan(o Gvk) bool { + indexI, foundI := typeOrders[x.Kind] + indexJ, foundJ := typeOrders[o.Kind] + if foundI && foundJ { + if indexI != indexJ { + return indexI < indexJ + } + } + if foundI && !foundJ { + return true + } + if !foundI && foundJ { + return false + } + return x.String() < o.String() +} + +// IsSelected returns true if `selector` selects `x`; otherwise, false. +// If `selector` and `x` are the same, return true. +// If `selector` is nil, it is considered a wildcard match, returning true. +// If selector fields are empty, they are considered wildcards matching +// anything in the corresponding fields, e.g. +// +// this item: +// +// +// is selected by +// +// +// but rejected by +// +// +func (x Gvk) IsSelected(selector *Gvk) bool { + if selector == nil { + return true + } + if len(selector.Group) > 0 { + if x.Group != selector.Group { + return false + } + } + if len(selector.Version) > 0 { + if x.Version != selector.Version { + return false + } + } + if len(selector.Kind) > 0 { + if x.Kind != selector.Kind { + return false + } + } + return true +} + +var clusterLevelKinds = []string{ + "APIService", + "ClusterRoleBinding", + "ClusterRole", + "CustomResourceDefinition", + "Namespace", + "PersistentVolume", +} + +// IsClusterKind returns true if x is a cluster-level Gvk +func (x Gvk) IsClusterKind() bool { + for _, k := range clusterLevelKinds { + if k == x.Kind { + return true + } + } + return false +} + +// ClusterLevelGvks returns a slice of cluster-level Gvks +func ClusterLevelGvks() []Gvk { + var result []Gvk + for _, k := range clusterLevelKinds { + result = append(result, Gvk{Kind: k}) + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go b/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go new file mode 100644 index 000000000..e6267cae2 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/ifc.go @@ -0,0 +1,73 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package ifc holds miscellaneous interfaces used by kustomize. +package ifc + +import ( + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Validator provides functions to validate annotations and labels +type Validator interface { + MakeAnnotationValidator() func(map[string]string) error + MakeLabelValidator() func(map[string]string) error + ValidateNamespace(string) []string +} + +// Loader interface exposes methods to read bytes. +type Loader interface { + // Root returns the root location for this Loader. + Root() string + // New returns Loader located at newRoot. + New(newRoot string) (Loader, error) + // Load returns the bytes read from the location or an error. + Load(location string) ([]byte, error) + // Cleanup cleans the loader + Cleanup() error +} + +// Kunstructured allows manipulation of k8s objects +// that do not have Golang structs. +type Kunstructured interface { + Map() map[string]interface{} + SetMap(map[string]interface{}) + Copy() Kunstructured + GetFieldValue(string) (string, error) + MarshalJSON() ([]byte, error) + UnmarshalJSON([]byte) error + GetGvk() gvk.Gvk + GetKind() string + GetName() string + SetName(string) + GetLabels() map[string]string + SetLabels(map[string]string) + GetAnnotations() map[string]string + SetAnnotations(map[string]string) +} + +// KunstructuredFactory makes instances of Kunstructured. +type KunstructuredFactory interface { + SliceFromBytes([]byte) ([]Kunstructured, error) + FromMap(m map[string]interface{}) Kunstructured + MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (Kunstructured, error) + MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (Kunstructured, error) + Set(ldr Loader) +} + +// See core.v1.SecretTypeOpaque +const SecretTypeOpaque = "Opaque" diff --git a/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go new file mode 100644 index 000000000..0a74c2809 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer/factory.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package patch holds miscellaneous interfaces used by kustomize. +package transformer + +import ( + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// Factory makes transformers +type Factory interface { + MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) + MakeHashTransformer() transformers.Transformer +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/image/deprecatedimage.go b/vendor/sigs.k8s.io/kustomize/pkg/image/deprecatedimage.go new file mode 100644 index 000000000..65db4051b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/image/deprecatedimage.go @@ -0,0 +1,32 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package image + +// DeprecatedImage contains an image and a new tag, +// which will replace the original tag. +// Deprecated, instead use Image. +type DeprecatedImage struct { + // Name is a tag-less image name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // NewTag is the value to use in replacing the original tag. + NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` + + // Digest is the value used to replace the original image tag. + // If digest is present NewTag value is ignored. + Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/image/image.go b/vendor/sigs.k8s.io/kustomize/pkg/image/image.go new file mode 100644 index 000000000..dbe3b8b17 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/image/image.go @@ -0,0 +1,36 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package image provides struct definitions and libraries +// for image overwriting of names, tags and digest. +package image + +// Image contains an image name, a new name, a new tag or digest, +// which will replace the original name and tag. +type Image struct { + // Name is a tag-less image name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // NewName is the value used to replace the original name. + NewName string `json:"newName,omitempty" yaml:"newName,omitempty"` + + // NewTag is the value used to replace the original tag. + NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` + + // Digest is the value used to replace the original image tag. + // If digest is present NewTag value is ignored. + Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go new file mode 100644 index 000000000..1d60d78a2 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/configmaperror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package error has contextual error types. +package error + +import "fmt" + +// ConfigmapError represents error with a configmap. +type ConfigmapError struct { + Path string + ErrorMsg string +} + +func (e ConfigmapError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a configmap error: %s\n", e.Path, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go new file mode 100644 index 000000000..0d53ca9b8 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/kustomizationerror.go @@ -0,0 +1,61 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import ( + "fmt" +) + +// KustomizationError represents an error with a kustomization. +type KustomizationError struct { + KustomizationPath string + ErrorMsg string +} + +func (ke KustomizationError) Error() string { + return fmt.Sprintf("Kustomization File [%s]: %s\n", ke.KustomizationPath, ke.ErrorMsg) +} + +// KustomizationErrors collects all errors. +type KustomizationErrors struct { + kErrors []error +} + +func (ke *KustomizationErrors) Error() string { + errormsg := "" + for _, e := range ke.kErrors { + errormsg += e.Error() + "\n" + } + return errormsg +} + +// Append adds error to a collection of errors. +func (ke *KustomizationErrors) Append(e error) { + ke.kErrors = append(ke.kErrors, e) +} + +// Get returns all collected errors. +func (ke *KustomizationErrors) Get() []error { + return ke.kErrors +} + +// BatchAppend adds all errors from another KustomizationErrors +func (ke *KustomizationErrors) BatchAppend(e KustomizationErrors) { + for _, err := range e.Get() { + ke.kErrors = append(ke.kErrors, err) + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go new file mode 100644 index 000000000..60c9f80e5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/patcherror.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import ( + "fmt" +) + +// PatchError represents error during Patch. +type PatchError struct { + KustomizationPath string + PatchFilepath string + ErrorMsg string +} + +func (e PatchError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a patch error for [%s]: %s\n", e.KustomizationPath, e.PatchFilepath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go new file mode 100644 index 000000000..ef3566dd1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/resourceerror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import "fmt" + +// ResourceError represents error in a resource. +type ResourceError struct { + KustomizationPath string + ResourceFilepath string + ErrorMsg string +} + +func (e ResourceError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a resource error for [%s]: %s\n", e.KustomizationPath, e.ResourceFilepath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go new file mode 100644 index 000000000..cd72759ce --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/secreterror.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package error + +import "fmt" + +// SecretError represents error with a secret. +type SecretError struct { + KustomizationPath string + // ErrorMsg is an error message + ErrorMsg string +} + +func (e SecretError) Error() string { + return fmt.Sprintf("Kustomization file [%s] encounters a secret error: %s\n", e.KustomizationPath, e.ErrorMsg) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go new file mode 100644 index 000000000..4c27d30d7 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/internal/error/yamlformaterror.go @@ -0,0 +1,48 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package error has contextual error types. +package error + +import ( + "fmt" + "strings" +) + +// YamlFormatError represents error with yaml file name where json/yaml format error happens. +type YamlFormatError struct { + Path string + ErrorMsg string +} + +func (e YamlFormatError) Error() string { + return fmt.Sprintf("YAML file [%s] encounters a format error.\n%s\n", e.Path, e.ErrorMsg) +} + +// Handler handles YamlFormatError +func Handler(e error, path string) error { + if isYAMLSyntaxError(e) { + return YamlFormatError{ + Path: path, + ErrorMsg: e.Error(), + } + } + return e +} + +func isYAMLSyntaxError(e error) bool { + return strings.Contains(e.Error(), "error converting YAML to JSON") || strings.Contains(e.Error(), "error unmarshaling JSON") +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go b/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go new file mode 100644 index 000000000..4fa5dca67 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/fileloader.go @@ -0,0 +1,312 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package loader + +import ( + "fmt" + "log" + "path/filepath" + "strings" + + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/git" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// fileLoader is a kustomization's interface to files. +// +// The directory in which a kustomization file sits +// is referred to below as the kustomization's root. +// +// An instance of fileLoader has an immutable root, +// and offers a `New` method returning a new loader +// with a new root. +// +// A kustomization file refers to two kinds of files: +// +// * supplemental data paths +// +// `Load` is used to visit these paths. +// +// They must terminate in or below the root. +// +// They hold things like resources, patches, +// data for ConfigMaps, etc. +// +// * bases; other kustomizations +// +// `New` is used to load bases. +// +// A base can be either a remote git repo URL, or +// a directory specified relative to the current +// root. In the former case, the repo is locally +// cloned, and the new loader is rooted on a path +// in that clone. +// +// As loaders create new loaders, a root history +// is established, and used to disallow: +// +// - A base that is a repository that, in turn, +// specifies a base repository seen previously +// in the loading stack (a cycle). +// +// - An overlay depending on a base positioned at +// or above it. I.e. '../foo' is OK, but '.', +// '..', '../..', etc. are disallowed. Allowing +// such a base has no advantages and encourages +// cycles, particularly if some future change +// were to introduce globbing to file +// specifications in the kustomization file. +// +// These restrictions assure that kustomizations +// are self-contained and relocatable, and impose +// some safety when relying on remote kustomizations, +// e.g. a ConfigMap generator specified to read +// from /etc/passwd will fail. +// +type fileLoader struct { + // Loader that spawned this loader. + // Used to avoid cycles. + referrer *fileLoader + // An absolute, cleaned path to a directory. + // The Load function reads from this directory, + // or directories below it. + root fs.ConfirmedDir + // If this is non-nil, the files were + // obtained from the given repository. + repoSpec *git.RepoSpec + // File system utilities. + fSys fs.FileSystem + // Used to clone repositories. + cloner git.Cloner + // Used to clean up, as needed. + cleaner func() error +} + +// NewFileLoaderAtCwd returns a loader that loads from ".". +func NewFileLoaderAtCwd(fSys fs.FileSystem) *fileLoader { + return newLoaderOrDie(fSys, ".") +} + +// NewFileLoaderAtRoot returns a loader that loads from "/". +func NewFileLoaderAtRoot(fSys fs.FileSystem) *fileLoader { + return newLoaderOrDie(fSys, string(filepath.Separator)) +} + +// Root returns the absolute path that is prepended to any +// relative paths used in Load. +func (l *fileLoader) Root() string { + return l.root.String() +} + +func newLoaderOrDie(fSys fs.FileSystem, path string) *fileLoader { + root, err := demandDirectoryRoot(fSys, path) + if err != nil { + log.Fatalf("unable to make loader at '%s'; %v", path, err) + } + return newLoaderAtConfirmedDir( + root, fSys, nil, git.ClonerUsingGitExec) +} + +// newLoaderAtConfirmedDir returns a new fileLoader with given root. +func newLoaderAtConfirmedDir( + root fs.ConfirmedDir, fSys fs.FileSystem, + referrer *fileLoader, cloner git.Cloner) *fileLoader { + return &fileLoader{ + root: root, + referrer: referrer, + fSys: fSys, + cloner: cloner, + cleaner: func() error { return nil }, + } +} + +// Assure that the given path is in fact a directory. +func demandDirectoryRoot( + fSys fs.FileSystem, path string) (fs.ConfirmedDir, error) { + if path == "" { + return "", fmt.Errorf( + "loader root cannot be empty") + } + d, f, err := fSys.CleanedAbs(path) + if err != nil { + return "", fmt.Errorf( + "absolute path error in '%s' : %v", path, err) + } + if f != "" { + return "", fmt.Errorf( + "got file '%s', but '%s' must be a directory to be a root", + f, path) + } + return d, nil +} + +// New returns a new Loader, rooted relative to current loader, +// or rooted in a temp directory holding a git repo clone. +func (l *fileLoader) New(path string) (ifc.Loader, error) { + if path == "" { + return nil, fmt.Errorf("new root cannot be empty") + } + repoSpec, err := git.NewRepoSpecFromUrl(path) + if err == nil { + // Treat this as git repo clone request. + if err := l.errIfRepoCycle(repoSpec); err != nil { + return nil, err + } + return newLoaderAtGitClone(repoSpec, l.fSys, l.referrer, l.cloner) + } + if filepath.IsAbs(path) { + return nil, fmt.Errorf("new root '%s' cannot be absolute", path) + } + root, err := demandDirectoryRoot(l.fSys, l.root.Join(path)) + if err != nil { + return nil, err + } + if err := l.errIfGitContainmentViolation(root); err != nil { + return nil, err + } + if err := l.errIfArgEqualOrHigher(root); err != nil { + return nil, err + } + return newLoaderAtConfirmedDir( + root, l.fSys, l, l.cloner), nil +} + +// newLoaderAtGitClone returns a new Loader pinned to a temporary +// directory holding a cloned git repo. +func newLoaderAtGitClone( + repoSpec *git.RepoSpec, fSys fs.FileSystem, + referrer *fileLoader, cloner git.Cloner) (ifc.Loader, error) { + err := cloner(repoSpec) + if err != nil { + return nil, err + } + root, f, err := fSys.CleanedAbs(repoSpec.AbsPath()) + if err != nil { + return nil, err + } + // We don't know that the path requested in repoSpec + // is a directory until we actually clone it and look + // inside. That just happened, hence the error check + // is here. + if f != "" { + return nil, fmt.Errorf( + "'%s' refers to file '%s'; expecting directory", + repoSpec.AbsPath(), f) + } + return &fileLoader{ + root: root, + referrer: referrer, + repoSpec: repoSpec, + fSys: fSys, + cloner: cloner, + cleaner: repoSpec.Cleaner(fSys), + }, nil +} + +func (l *fileLoader) errIfGitContainmentViolation( + base fs.ConfirmedDir) error { + containingRepo := l.containingRepo() + if containingRepo == nil { + return nil + } + if !base.HasPrefix(containingRepo.CloneDir()) { + return fmt.Errorf( + "security; bases in kustomizations found in "+ + "cloned git repos must be within the repo, "+ + "but base '%s' is outside '%s'", + base, containingRepo.CloneDir()) + } + return nil +} + +// Looks back through referrers for a git repo, returning nil +// if none found. +func (l *fileLoader) containingRepo() *git.RepoSpec { + if l.repoSpec != nil { + return l.repoSpec + } + if l.referrer == nil { + return nil + } + return l.referrer.containingRepo() +} + +// errIfArgEqualOrHigher tests whether the argument, +// is equal to or above the root of any ancestor. +func (l *fileLoader) errIfArgEqualOrHigher( + candidateRoot fs.ConfirmedDir) error { + if l.root.HasPrefix(candidateRoot) { + return fmt.Errorf( + "cycle detected: candidate root '%s' contains visited root '%s'", + candidateRoot, l.root) + } + if l.referrer == nil { + return nil + } + return l.referrer.errIfArgEqualOrHigher(candidateRoot) +} + +// TODO(monopole): Distinguish branches? +// I.e. Allow a distinction between git URI with +// path foo and tag bar and a git URI with the same +// path but a different tag? +func (l *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error { + // TODO(monopole): Use parsed data instead of Raw(). + if l.repoSpec != nil && + strings.HasPrefix(l.repoSpec.Raw(), newRepoSpec.Raw()) { + return fmt.Errorf( + "cycle detected: URI '%s' referenced by previous URI '%s'", + newRepoSpec.Raw(), l.repoSpec.Raw()) + } + if l.referrer == nil { + return nil + } + return l.referrer.errIfRepoCycle(newRepoSpec) +} + +// Load returns content of file at the given relative path, +// else an error. The path must refer to a file in or +// below the current root. +func (l *fileLoader) Load(path string) ([]byte, error) { + if filepath.IsAbs(path) { + return nil, l.loadOutOfBounds(path) + } + d, f, err := l.fSys.CleanedAbs(l.root.Join(path)) + if err != nil { + return nil, err + } + if f == "" { + return nil, fmt.Errorf( + "'%s' must be a file (got d='%s')", path, d) + } + if !d.HasPrefix(l.root) { + return nil, l.loadOutOfBounds(path) + } + return l.fSys.ReadFile(d.Join(f)) +} + +func (l *fileLoader) loadOutOfBounds(path string) error { + return fmt.Errorf( + "security; file '%s' is not in or below '%s'", + path, l.root) +} + +// Cleanup runs the cleaner. +func (l *fileLoader) Cleanup() error { + return l.cleaner() +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go b/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go new file mode 100644 index 000000000..53de6553a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/loader/loader.go @@ -0,0 +1,39 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package loader has a data loading interface and various implementations. +package loader + +import ( + "sigs.k8s.io/kustomize/pkg/fs" + "sigs.k8s.io/kustomize/pkg/git" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// NewLoader returns a Loader. +func NewLoader(path string, fSys fs.FileSystem) (ifc.Loader, error) { + repoSpec, err := git.NewRepoSpecFromUrl(path) + if err == nil { + return newLoaderAtGitClone( + repoSpec, fSys, nil, git.ClonerUsingGitExec) + } + root, err := demandDirectoryRoot(fSys, path) + if err != nil { + return nil, err + } + return newLoaderAtConfirmedDir( + root, fSys, nil, git.ClonerUsingGitExec), nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go new file mode 100644 index 000000000..9ddb1faa1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/json6902.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +import "sigs.k8s.io/kustomize/pkg/gvk" + +// Json6902 represents a json patch for an object +// with format documented https://tools.ietf.org/html/rfc6902. +type Json6902 struct { + // Target refers to a Kubernetes object that the json patch will be + // applied to. It must refer to a Kubernetes resource under the + // purview of this kustomization. Target should use the + // raw name of the object (the name specified in its YAML, + // before addition of a namePrefix and a nameSuffix). + Target *Target `json:"target" yaml:"target"` + + // relative file path for a json patch file inside a kustomization + Path string `json:"path,omitempty" yaml:"path,omitempty"` +} + +// Target represents the kubernetes object that the patch is applied to +type Target struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + Name string `json:"name" yaml:"name"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go new file mode 100644 index 000000000..596cc346d --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/strategicmerge.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patch + +// StrategicMerge represents a relative path to a +// stategic merge patch with the format +// https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md +type StrategicMerge string + +// Append appends a slice of patch paths to a StrategicMerge slice +func Append(patches []StrategicMerge, paths ...string) []StrategicMerge { + for _, p := range paths { + patches = append(patches, StrategicMerge(p)) + } + return patches +} + +// Exist determines if a patch path exists in a slice of StrategicMerge +func Exist(patches []StrategicMerge, path string) bool { + for _, p := range patches { + if p == StrategicMerge(path) { + return true + } + } + return false +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go new file mode 100644 index 000000000..b373dfb72 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/factory.go @@ -0,0 +1,83 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformer + +import ( + "fmt" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/patch" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// PatchJson6902Factory makes Json6902 transformers +type PatchJson6902Factory struct { + loader ifc.Loader +} + +// NewPatchJson6902Factory returns a new PatchJson6902Factory. +func NewPatchJson6902Factory(l ifc.Loader) PatchJson6902Factory { + return PatchJson6902Factory{loader: l} +} + +// MakePatchJson6902Transformer returns a transformer for applying Json6902 patch +func (f PatchJson6902Factory) MakePatchJson6902Transformer(patches []patch.Json6902) (transformers.Transformer, error) { + var ts []transformers.Transformer + for _, p := range patches { + t, err := f.makeOnePatchJson6902Transformer(p) + if err != nil { + return nil, err + } + if t != nil { + ts = append(ts, t) + } + } + return transformers.NewMultiTransformerWithConflictCheck(ts), nil +} + +func (f PatchJson6902Factory) makeOnePatchJson6902Transformer(p patch.Json6902) (transformers.Transformer, error) { + if p.Target == nil { + return nil, fmt.Errorf("must specify the target field in patchesJson6902") + } + if p.Path == "" { + return nil, fmt.Errorf("must specify the path for a json patch file") + } + + targetId := resid.NewResIdWithPrefixNamespace( + gvk.Gvk{ + Group: p.Target.Group, + Version: p.Target.Version, + Kind: p.Target.Kind, + }, + p.Target.Name, + "", + p.Target.Namespace, + ) + + rawOp, err := f.loader.Load(p.Path) + if err != nil { + return nil, err + } + + return newPatchJson6902JSONTransformer(targetId, rawOp) +} + +func isJsonFormat(data []byte) bool { + return data[0] == '[' +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go new file mode 100644 index 000000000..1f09939d1 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/patch/transformer/patchjson6902json.go @@ -0,0 +1,108 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformer + +import ( + "fmt" + + "github.com/evanphx/json-patch" + "github.com/ghodss/yaml" + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" +) + +// patchJson6902JSONTransformer applies patches. +type patchJson6902JSONTransformer struct { + target resid.ResId + patch jsonpatch.Patch + rawOp []byte +} + +var _ transformers.Transformer = &patchJson6902JSONTransformer{} + +// newPatchJson6902JSONTransformer constructs a PatchJson6902 transformer. +func newPatchJson6902JSONTransformer( + id resid.ResId, rawOp []byte) (transformers.Transformer, error) { + op := rawOp + var err error + if !isJsonFormat(op) { + // if it isn't JSON, try to parse it as YAML + op, err = yaml.YAMLToJSON(rawOp) + if err != nil { + return nil, err + } + } + decodedPatch, err := jsonpatch.DecodePatch(op) + if err != nil { + return nil, err + } + if len(decodedPatch) == 0 { + return transformers.NewNoOpTransformer(), nil + } + return &patchJson6902JSONTransformer{target: id, patch: decodedPatch, rawOp: rawOp}, nil +} + +// Transform apply the json patches on top of the base resources. +func (t *patchJson6902JSONTransformer) Transform(m resmap.ResMap) error { + obj, err := t.findTargetObj(m) + if err != nil { + return err + } + rawObj, err := obj.MarshalJSON() + if err != nil { + return err + } + modifiedObj, err := t.patch.Apply(rawObj) + if err != nil { + return errors.Wrapf(err, "failed to apply json patch '%s'", string(t.rawOp)) + } + err = obj.UnmarshalJSON(modifiedObj) + if err != nil { + return err + } + return nil +} + +func (t *patchJson6902JSONTransformer) findTargetObj( + m resmap.ResMap) (*resource.Resource, error) { + var matched []resid.ResId + // TODO(monopole): namespace bug in json patch? + // Since introduction in PR #300 + // (see pkg/patch/transformer/util.go), + // this code has treated an empty namespace like a wildcard + // rather than like an additional restriction to match + // only the empty namespace. No test coverage to confirm. + // Not sure if desired, keeping it for now. + if t.target.Namespace() != "" { + matched = m.GetMatchingIds(t.target.NsGvknEquals) + } else { + matched = m.GetMatchingIds(t.target.GvknEquals) + } + if len(matched) == 0 { + return nil, fmt.Errorf( + "couldn't find target %v for json patch", t.target) + } + if len(matched) > 1 { + return nil, fmt.Errorf( + "found multiple targets %v matching %v for json patch", + matched, t.target) + } + return m[matched[0]], nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go b/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go new file mode 100644 index 000000000..dbf9a3e92 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resid/resid.go @@ -0,0 +1,207 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resid + +import ( + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// ResId is an immutable identifier of a k8s resource object. +type ResId struct { + // Gvk of the resource. + gvKind gvk.Gvk + + // name of the resource before transformation. + name string + + // namePrefix of the resource. + // An untransformed resource has no prefix. + // A fully transformed resource has an arbitrary + // number of prefixes concatenated together. + prefix string + + // nameSuffix of the resource. + // An untransformed resource has no suffix. + // A fully transformed resource has an arbitrary + // number of suffixes concatenated together. + suffix string + + // Namespace the resource belongs to. + // An untransformed resource has no namespace. + // A fully transformed resource has the namespace + // from the top most overlay. + namespace string +} + +// NewResIdWithPrefixSuffixNamespace creates new resource identifier with a prefix, suffix and a namespace +func NewResIdWithPrefixSuffixNamespace(k gvk.Gvk, n, p, s, ns string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s, namespace: ns} +} + +// NewResIdWithPrefixNamespace creates new resource identifier with a prefix and a namespace +func NewResIdWithPrefixNamespace(k gvk.Gvk, n, p, ns string) ResId { + return ResId{gvKind: k, name: n, prefix: p, namespace: ns} +} + +// NewResIdWithSuffixNamespace creates new resource identifier with a suffix and a namespace +func NewResIdWithSuffixNamespace(k gvk.Gvk, n, s, ns string) ResId { + return ResId{gvKind: k, name: n, suffix: s, namespace: ns} +} + +// NewResIdWithPrefixSuffix creates new resource identifier with a prefix and suffix +func NewResIdWithPrefixSuffix(k gvk.Gvk, n, p, s string) ResId { + return ResId{gvKind: k, name: n, prefix: p, suffix: s} +} + +// NewResId creates new resource identifier +func NewResId(k gvk.Gvk, n string) ResId { + return ResId{gvKind: k, name: n} +} + +// NewResIdKindOnly creates new resource identifier +func NewResIdKindOnly(k string, n string) ResId { + return ResId{gvKind: gvk.FromKind(k), name: n} +} + +const ( + noNamespace = "~X" + noPrefix = "~P" + noName = "~N" + noSuffix = "~S" + separator = "|" +) + +// String of ResId based on GVK, name and prefix +func (n ResId) String() string { + ns := n.namespace + if ns == "" { + ns = noNamespace + } + p := n.prefix + if p == "" { + p = noPrefix + } + nm := n.name + if nm == "" { + nm = noName + } + s := n.suffix + if s == "" { + s = noSuffix + } + + return strings.Join( + []string{n.gvKind.String(), ns, p, nm, s}, separator) +} + +// GvknString of ResId based on GVK and name +func (n ResId) GvknString() string { + return n.gvKind.String() + separator + n.name +} + +// GvknEquals returns true if the other id matches +// Group/Version/Kind/name. +func (n ResId) GvknEquals(id ResId) bool { + return n.name == id.name && n.gvKind.Equals(id.gvKind) +} + +// NsGvknEquals returns true if the other id matches +// namespace/Group/Version/Kind/name. +func (n ResId) NsGvknEquals(id ResId) bool { + return n.namespace == id.namespace && n.GvknEquals(id) +} + +// Gvk returns Group/Version/Kind of the resource. +func (n ResId) Gvk() gvk.Gvk { + return n.gvKind +} + +// Name returns resource name. +func (n ResId) Name() string { + return n.name +} + +// Namespace returns resource namespace. +func (n ResId) Namespace() string { + return n.namespace +} + +// CopyWithNewPrefixSuffix make a new copy from current ResId +// and append a new prefix and suffix +func (n ResId) CopyWithNewPrefixSuffix(p, s string) ResId { + result := n + if p != "" { + result.prefix = n.concatPrefix(p) + } + if s != "" { + result.suffix = n.concatSuffix(s) + } + return result +} + +// CopyWithNewNamespace make a new copy from current ResId and set a new namespace +func (n ResId) CopyWithNewNamespace(ns string) ResId { + result := n + result.namespace = ns + return result +} + +// HasSameLeftmostPrefix check if two ResIds have the same +// left most prefix. +func (n ResId) HasSameLeftmostPrefix(id ResId) bool { + prefixes1 := n.prefixList() + prefixes2 := id.prefixList() + return prefixes1[0] == prefixes2[0] +} + +// HasSameRightmostSuffix check if two ResIds have the same +// right most suffix. +func (n ResId) HasSameRightmostSuffix(id ResId) bool { + suffixes1 := n.suffixList() + suffixes2 := id.suffixList() + return suffixes1[len(suffixes1)-1] == suffixes2[len(suffixes2)-1] +} + +func (n ResId) concatPrefix(p string) string { + if p == "" { + return n.prefix + } + if n.prefix == "" { + return p + } + return p + ":" + n.prefix +} + +func (n ResId) concatSuffix(s string) string { + if s == "" { + return n.suffix + } + if n.suffix == "" { + return s + } + return n.suffix + ":" + s +} + +func (n ResId) prefixList() []string { + return strings.Split(n.prefix, ":") +} + +func (n ResId) suffixList() []string { + return strings.Split(n.suffix, ":") +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go new file mode 100644 index 000000000..923cde232 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/factory.go @@ -0,0 +1,123 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resmap + +import ( + "fmt" + + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Factory makes instances of ResMap. +type Factory struct { + resF *resource.Factory +} + +// NewFactory returns a new resmap.Factory. +func NewFactory(rf *resource.Factory) *Factory { + return &Factory{resF: rf} +} + +// RF returns a resource.Factory. +func (rmF *Factory) RF() *resource.Factory { + return rmF.resF +} + +// FromFiles returns a ResMap given a resource path slice. +func (rmF *Factory) FromFiles( + loader ifc.Loader, paths []string) (ResMap, error) { + var result []ResMap + for _, path := range paths { + content, err := loader.Load(path) + if err != nil { + return nil, errors.Wrap(err, "Load from path "+path+" failed") + } + res, err := rmF.NewResMapFromBytes(content) + if err != nil { + return nil, internal.Handler(err, path) + } + result = append(result, res) + } + return MergeWithErrorOnIdCollision(result...) +} + +// newResMapFromBytes decodes a list of objects in byte array format. +func (rmF *Factory) NewResMapFromBytes(b []byte) (ResMap, error) { + resources, err := rmF.resF.SliceFromBytes(b) + if err != nil { + return nil, err + } + + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id) + } + result[id] = res + } + return result, nil +} + +// NewResMapFromConfigMapArgs returns a Resource slice given +// a configmap metadata slice from kustomization file. +func (rmF *Factory) NewResMapFromConfigMapArgs(argList []types.ConfigMapArgs, options *types.GeneratorOptions) (ResMap, error) { + var resources []*resource.Resource + for _, args := range argList { + res, err := rmF.resF.MakeConfigMap(&args, options) + if err != nil { + return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs") + } + resources = append(resources, res) + } + return newResMapFromResourceSlice(resources) +} + +// NewResMapFromSecretArgs takes a SecretArgs slice, generates +// secrets from each entry, and accumulates them in a ResMap. +func (rmF *Factory) NewResMapFromSecretArgs(argsList []types.SecretArgs, options *types.GeneratorOptions) (ResMap, error) { + var resources []*resource.Resource + for _, args := range argsList { + res, err := rmF.resF.MakeSecret(&args, options) + if err != nil { + return nil, errors.Wrap(err, "NewResMapFromSecretArgs") + } + resources = append(resources, res) + } + return newResMapFromResourceSlice(resources) +} + +// Set sets the loader for the underlying factory +func (rmF *Factory) Set(ldr ifc.Loader) { + rmF.resF.Set(ldr) +} + +func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) { + result := ResMap{} + for _, res := range resources { + id := res.Id() + if _, found := result[id]; found { + return nil, fmt.Errorf("duplicated %#v is not allowed", id) + } + result[id] = res + } + return result, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go new file mode 100644 index 000000000..cdf759203 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/idslice.go @@ -0,0 +1,37 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resmap + +import ( + "sort" + + "sigs.k8s.io/kustomize/pkg/resid" +) + +// IdSlice implements the sort interface. +type IdSlice []resid.ResId + +var _ sort.Interface = IdSlice{} + +func (a IdSlice) Len() int { return len(a) } +func (a IdSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a IdSlice) Less(i, j int) bool { + if !a[i].Gvk().Equals(a[j].Gvk()) { + return a[i].Gvk().IsLessThan(a[j].Gvk()) + } + return a[i].String() < a[j].String() +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go b/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go new file mode 100644 index 000000000..ca1e72398 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resmap/resmap.go @@ -0,0 +1,200 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resmap implements a map from ResId to Resource that tracks all resources in a kustomization. +package resmap + +import ( + "bytes" + "fmt" + "reflect" + "sort" + + "github.com/ghodss/yaml" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/types" +) + +// ResMap is a map from ResId to Resource. +type ResMap map[resid.ResId]*resource.Resource + +type IdMatcher func(resid.ResId) bool + +// GetMatchingIds returns a slice of ResId keys from the map +// that all satisfy the given matcher function. +func (m ResMap) GetMatchingIds(matches IdMatcher) []resid.ResId { + var result []resid.ResId + for id := range m { + if matches(id) { + result = append(result, id) + } + } + return result +} + +// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`. +func (m ResMap) EncodeAsYaml() ([]byte, error) { + var ids []resid.ResId + for id := range m { + ids = append(ids, id) + } + sort.Sort(IdSlice(ids)) + + firstObj := true + var b []byte + buf := bytes.NewBuffer(b) + for _, id := range ids { + obj := m[id] + out, err := yaml.Marshal(obj.Map()) + if err != nil { + return nil, err + } + if firstObj { + firstObj = false + } else { + _, err = buf.WriteString("---\n") + if err != nil { + return nil, err + } + } + _, err = buf.Write(out) + if err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} + +// ErrorIfNotEqual returns error if maps are not equal. +func (m ResMap) ErrorIfNotEqual(m2 ResMap) error { + if len(m) != len(m2) { + var keySet1 []resid.ResId + var keySet2 []resid.ResId + for id := range m { + keySet1 = append(keySet1, id) + } + for id := range m2 { + keySet2 = append(keySet2, id) + } + return fmt.Errorf("maps has different number of entries: %#v doesn't equals %#v", keySet1, keySet2) + } + for id, obj1 := range m { + obj2, found := m2[id] + if !found { + return fmt.Errorf("%#v doesn't exist in %#v", id, m2) + } + if !reflect.DeepEqual(obj1, obj2) { + return fmt.Errorf("%#v doesn't deep equal %#v", obj1, obj2) + } + } + return nil +} + +// DeepCopy clone the resmap into a new one +func (m ResMap) DeepCopy(rf *resource.Factory) ResMap { + mcopy := make(ResMap) + for id, obj := range m { + mcopy[id] = obj.DeepCopy() + } + return mcopy +} + +// FilterBy returns a subset ResMap containing ResIds with +// the same namespace and leftmost name prefix and rightmost name +// as the inputId. If inputId is a cluster level resource, this +// returns the original ResMap. +func (m ResMap) FilterBy(inputId resid.ResId) ResMap { + if inputId.Gvk().IsClusterKind() { + return m + } + result := ResMap{} + for id, res := range m { + if id.Gvk().IsClusterKind() || id.Namespace() == inputId.Namespace() && + id.HasSameLeftmostPrefix(inputId) && + id.HasSameRightmostSuffix(inputId) { + result[id] = res + } + } + return result +} + +// MergeWithErrorOnIdCollision combines multiple ResMap instances, failing on +// key collision and skipping nil maps. +// If all of the maps are nil, an empty ResMap is returned. +func MergeWithErrorOnIdCollision(maps ...ResMap) (ResMap, error) { + result := ResMap{} + for _, m := range maps { + if m == nil { + continue + } + for id, res := range m { + if _, found := result[id]; found { + return nil, fmt.Errorf("id '%q' already used", id) + } + result[id] = res + } + } + return result, nil +} + +// MergeWithOverride combines multiple ResMap instances, allowing and sometimes +// demanding certain collisions and skipping nil maps. +// A collision would be demanded, say, when a generated ConfigMap has the +// "replace" option in its generation instructions, meaning it is supposed +// to replace something from the raw resources list. +// If all of the maps are nil, an empty ResMap is returned. +// When looping over the instances to combine them, if a resource id for +// resource X is found to be already in the combined map, then the behavior +// field for X must be BehaviorMerge or BehaviorReplace. If X is not in the +// map, then it's behavior cannot be merge or replace. +func MergeWithOverride(maps ...ResMap) (ResMap, error) { + result := maps[0] + if result == nil { + result = ResMap{} + } + for _, m := range maps[1:] { + if m == nil { + continue + } + for id, r := range m { + matchedId := result.GetMatchingIds(id.GvknEquals) + if len(matchedId) == 1 { + id = matchedId[0] + switch r.Behavior() { + case types.BehaviorReplace: + r.Replace(result[id]) + result[id] = r + case types.BehaviorMerge: + r.Merge(result[id]) + result[id] = r + default: + return nil, fmt.Errorf("id %#v exists; must merge or replace", id) + } + } else if len(matchedId) == 0 { + switch r.Behavior() { + case types.BehaviorMerge, types.BehaviorReplace: + return nil, fmt.Errorf("id %#v does not exist; cannot merge or replace", id) + default: + result[id] = r + } + } else { + return nil, fmt.Errorf("merge conflict, found multiple objects %v the Resmap %v can merge into", matchedId, id) + } + } + } + return result, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go new file mode 100644 index 000000000..148323dd6 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resource/factory.go @@ -0,0 +1,148 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +import ( + "encoding/json" + "fmt" + "log" + "strings" + + "sigs.k8s.io/kustomize/pkg/ifc" + internal "sigs.k8s.io/kustomize/pkg/internal/error" + "sigs.k8s.io/kustomize/pkg/patch" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Factory makes instances of Resource. +type Factory struct { + kf ifc.KunstructuredFactory +} + +// NewFactory makes an instance of Factory. +func NewFactory(kf ifc.KunstructuredFactory) *Factory { + return &Factory{kf: kf} +} + +// FromMap returns a new instance of Resource. +func (rf *Factory) FromMap(m map[string]interface{}) *Resource { + return &Resource{ + Kunstructured: rf.kf.FromMap(m), + options: types.NewGenArgs(nil, nil), + } +} + +// FromMapAndOption returns a new instance of Resource with given options. +func (rf *Factory) FromMapAndOption(m map[string]interface{}, args *types.GeneratorArgs, option *types.GeneratorOptions) *Resource { + return &Resource{ + Kunstructured: rf.kf.FromMap(m), + options: types.NewGenArgs(args, option), + } +} + +// FromKunstructured returns a new instance of Resource. +func (rf *Factory) FromKunstructured( + u ifc.Kunstructured) *Resource { + if u == nil { + log.Fatal("unstruct ifc must not be null") + } + return &Resource{ + Kunstructured: u, + options: types.NewGenArgs(nil, nil), + } +} + +// SliceFromPatches returns a slice of resources given a patch path +// slice from a kustomization file. +func (rf *Factory) SliceFromPatches( + ldr ifc.Loader, paths []patch.StrategicMerge) ([]*Resource, error) { + var result []*Resource + for _, path := range paths { + content, err := ldr.Load(string(path)) + if err != nil { + return nil, err + } + res, err := rf.SliceFromBytes(content) + if err != nil { + return nil, internal.Handler(err, string(path)) + } + result = append(result, res...) + } + return result, nil +} + +// SliceFromBytes unmarshalls bytes into a Resource slice. +func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) { + kunStructs, err := rf.kf.SliceFromBytes(in) + if err != nil { + return nil, err + } + var result []*Resource + for len(kunStructs) > 0 { + u := kunStructs[0] + kunStructs = kunStructs[1:] + if strings.HasSuffix(u.GetKind(), "List") { + items := u.Map()["items"] + itemsSlice, ok := items.([]interface{}) + if !ok { + if items == nil { + // an empty list + continue + } + return nil, fmt.Errorf("items in List is type %T, expected array", items) + } + for _, item := range itemsSlice { + itemJSON, err := json.Marshal(item) + if err != nil { + return nil, err + } + innerU, err := rf.kf.SliceFromBytes(itemJSON) + if err != nil { + return nil, err + } + // append innerU to kunStructs so nested Lists can be handled + kunStructs = append(kunStructs, innerU...) + } + } else { + result = append(result, rf.FromKunstructured(u)) + } + } + return result, nil +} + +// Set sets the loader for the underlying factory +func (rf *Factory) Set(ldr ifc.Loader) { + rf.kf.Set(ldr) +} + +// MakeConfigMap makes an instance of Resource for ConfigMap +func (rf *Factory) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (*Resource, error) { + u, err := rf.kf.MakeConfigMap(args, options) + if err != nil { + return nil, err + } + return &Resource{Kunstructured: u, options: types.NewGenArgs(&types.GeneratorArgs{Behavior: args.Behavior}, options)}, nil +} + +// MakeSecret makes an instance of Resource for Secret +func (rf *Factory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*Resource, error) { + u, err := rf.kf.MakeSecret(args, options) + if err != nil { + return nil, err + } + return &Resource{Kunstructured: u, options: types.NewGenArgs(&types.GeneratorArgs{Behavior: args.Behavior}, options)}, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go b/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go new file mode 100644 index 000000000..1e0e3764b --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/resource/resource.go @@ -0,0 +1,107 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package resource implements representations of k8s API resources as "unstructured" objects. +package resource + +import ( + "strings" + + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/types" +) + +// Resource is map representation of a Kubernetes API resource object +// paired with a GenerationBehavior. +type Resource struct { + ifc.Kunstructured + options *types.GenArgs +} + +// String returns resource as JSON. +func (r *Resource) String() string { + bs, err := r.MarshalJSON() + if err != nil { + return "<" + err.Error() + ">" + } + return strings.TrimSpace(string(bs)) + r.options.String() +} + +// DeepCopy returns a new copy of resource +func (r *Resource) DeepCopy() *Resource { + return &Resource{ + Kunstructured: r.Kunstructured.Copy(), + options: r.options, + } +} + +// Behavior returns the behavior for the resource. +func (r *Resource) Behavior() types.GenerationBehavior { + return r.options.Behavior() +} + +// NeedAppendHash checks if the resource need a hash suffix +func (r *Resource) NeedHashSuffix() bool { + return r.options != nil && r.options.NeedsHashSuffix() +} + +// Id returns the ResId for the resource. +func (r *Resource) Id() resid.ResId { + namespace, _ := r.GetFieldValue("metadata.namespace") + return resid.NewResIdWithPrefixNamespace(r.GetGvk(), r.GetName(), "", namespace) +} + +// Merge performs merge with other resource. +func (r *Resource) Merge(other *Resource) { + r.Replace(other) + mergeConfigmap(r.Map(), other.Map(), r.Map()) +} + +// Replace performs replace with other resource. +func (r *Resource) Replace(other *Resource) { + r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) + r.SetAnnotations( + mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) + r.SetName(other.GetName()) + r.options = other.options +} + +// TODO: Add BinaryData once we sync to new k8s.io/api +func mergeConfigmap( + mergedTo map[string]interface{}, + maps ...map[string]interface{}) { + mergedMap := map[string]interface{}{} + for _, m := range maps { + datamap, ok := m["data"].(map[string]interface{}) + if ok { + for key, value := range datamap { + mergedMap[key] = value + } + } + } + mergedTo["data"] = mergedMap +} + +func mergeStringMaps(maps ...map[string]string) map[string]string { + result := map[string]string{} + for _, m := range maps { + for key, value := range m { + result[key] = value + } + } + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go b/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go new file mode 100644 index 000000000..f136b2683 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/target/kusttarget.go @@ -0,0 +1,315 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package target implements state for the set of all resources to customize. +package target + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + + "github.com/ghodss/yaml" + "github.com/pkg/errors" + "sigs.k8s.io/kustomize/pkg/constants" + "sigs.k8s.io/kustomize/pkg/ifc" + "sigs.k8s.io/kustomize/pkg/ifc/transformer" + interror "sigs.k8s.io/kustomize/pkg/internal/error" + patchtransformer "sigs.k8s.io/kustomize/pkg/patch/transformer" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/resource" + "sigs.k8s.io/kustomize/pkg/transformers" + "sigs.k8s.io/kustomize/pkg/transformers/config" + "sigs.k8s.io/kustomize/pkg/types" +) + +// KustTarget encapsulates the entirety of a kustomization build. +type KustTarget struct { + kustomization *types.Kustomization + ldr ifc.Loader + rFactory *resmap.Factory + tFactory transformer.Factory +} + +// NewKustTarget returns a new instance of KustTarget primed with a Loader. +func NewKustTarget( + ldr ifc.Loader, + rFactory *resmap.Factory, + tFactory transformer.Factory) (*KustTarget, error) { + content, err := loadKustFile(ldr) + if err != nil { + return nil, err + } + content = types.DealWithDeprecatedFields(content) + var k types.Kustomization + err = unmarshal(content, &k) + if err != nil { + return nil, err + } + errs := k.EnforceFields() + if len(errs) > 0 { + return nil, fmt.Errorf("Failed to read kustomization file under %s:\n"+strings.Join(errs, "\n"), ldr.Root()) + } + return &KustTarget{ + kustomization: &k, + ldr: ldr, + rFactory: rFactory, + tFactory: tFactory, + }, nil +} + +func quoted(l []string) []string { + r := make([]string, len(l)) + for i, v := range l { + r[i] = "'" + v + "'" + } + return r +} + +func commaOr(q []string) string { + return strings.Join(q[:len(q)-1], ", ") + " or " + q[len(q)-1] +} + +func loadKustFile(ldr ifc.Loader) ([]byte, error) { + var content []byte + match := 0 + for _, kf := range constants.KustomizationFileNames { + c, err := ldr.Load(kf) + if err == nil { + match += 1 + content = c + } + } + switch match { + case 0: + return nil, fmt.Errorf( + "unable to find one of %v in directory '%s'", + commaOr(quoted(constants.KustomizationFileNames)), ldr.Root()) + case 1: + return content, nil + default: + return nil, fmt.Errorf("Found multiple kustomization files under: %s\n", ldr.Root()) + } +} + +func unmarshal(y []byte, o interface{}) error { + j, err := yaml.YAMLToJSON(y) + if err != nil { + return err + } + dec := json.NewDecoder(bytes.NewReader(j)) + dec.DisallowUnknownFields() + return dec.Decode(o) +} + +// MakeCustomizedResMap creates a ResMap per kustomization instructions. +// The Resources in the returned ResMap are fully customized. +func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) { + ra, err := kt.AccumulateTarget() + if err != nil { + return nil, err + } + err = ra.Transform(kt.tFactory.MakeHashTransformer()) + if err != nil { + return nil, err + } + // Given that names have changed (prefixs/suffixes added), + // fix all the back references to those names. + err = ra.FixBackReferences() + if err != nil { + return nil, err + } + // With all the back references fixed, it's OK to resolve Vars. + err = ra.ResolveVars() + return ra.ResMap(), err +} + +func (kt *KustTarget) shouldAddHashSuffixesToGeneratedResources() bool { + return kt.kustomization.GeneratorOptions == nil || + !kt.kustomization.GeneratorOptions.DisableNameSuffixHash +} + +// AccumulateTarget returns a new ResAccumulator, +// holding customized resources and the data/rules used +// to do so. The name back references and vars are +// not yet fixed. +func (kt *KustTarget) AccumulateTarget() ( + ra *ResAccumulator, err error) { + // TODO(monopole): Get rid of the KustomizationErrors accumulator. + // It's not consistently used, and complicates tests. + errs := &interror.KustomizationErrors{} + ra, errs = kt.accumulateBases() + resources, err := kt.rFactory.FromFiles( + kt.ldr, kt.kustomization.Resources) + if err != nil { + errs.Append(errors.Wrap(err, "rawResources failed to read Resources")) + } + if len(errs.Get()) > 0 { + return ra, errs + } + err = ra.MergeResourcesWithErrorOnIdCollision(resources) + if err != nil { + errs.Append(errors.Wrap(err, "MergeResourcesWithErrorOnIdCollision")) + } + tConfig, err := config.MakeTransformerConfig( + kt.ldr, kt.kustomization.Configurations) + if err != nil { + return nil, err + } + err = ra.MergeConfig(tConfig) + if err != nil { + errs.Append(errors.Wrap(err, "MergeConfig")) + } + err = ra.MergeVars(kt.kustomization.Vars) + if err != nil { + errs.Append(errors.Wrap(err, "MergeVars")) + } + crdTc, err := config.LoadConfigFromCRDs(kt.ldr, kt.kustomization.Crds) + if err != nil { + errs.Append(errors.Wrap(err, "LoadCRDs")) + } + err = ra.MergeConfig(crdTc) + if err != nil { + errs.Append(errors.Wrap(err, "merge CRDs")) + } + resMap, err := kt.generateConfigMapsAndSecrets(errs) + if err != nil { + errs.Append(errors.Wrap(err, "generateConfigMapsAndSecrets")) + } + err = ra.MergeResourcesWithOverride(resMap) + if err != nil { + return nil, err + } + patches, err := kt.rFactory.RF().SliceFromPatches( + kt.ldr, kt.kustomization.PatchesStrategicMerge) + if err != nil { + errs.Append(errors.Wrap(err, "SliceFromPatches")) + } + if len(errs.Get()) > 0 { + return nil, errs + } + t, err := kt.newTransformer(patches, ra.tConfig) + if err != nil { + return nil, err + } + err = ra.Transform(t) + if err != nil { + return nil, err + } + return ra, nil +} + +func (kt *KustTarget) generateConfigMapsAndSecrets( + errs *interror.KustomizationErrors) (resmap.ResMap, error) { + kt.rFactory.Set(kt.ldr) + cms, err := kt.rFactory.NewResMapFromConfigMapArgs( + kt.kustomization.ConfigMapGenerator, kt.kustomization.GeneratorOptions) + if err != nil { + errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs")) + } + secrets, err := kt.rFactory.NewResMapFromSecretArgs( + kt.kustomization.SecretGenerator, kt.kustomization.GeneratorOptions) + if err != nil { + errs.Append(errors.Wrap(err, "NewResMapFromSecretArgs")) + } + return resmap.MergeWithErrorOnIdCollision(cms, secrets) +} + +// accumulateBases returns a new ResAccumulator +// holding customized resources and the data/rules +// used to customized them from only the _bases_ +// of this KustTarget. +func (kt *KustTarget) accumulateBases() ( + ra *ResAccumulator, errs *interror.KustomizationErrors) { + errs = &interror.KustomizationErrors{} + ra = MakeEmptyAccumulator() + + for _, path := range kt.kustomization.Bases { + ldr, err := kt.ldr.New(path) + if err != nil { + errs.Append(errors.Wrap(err, "couldn't make loader for "+path)) + continue + } + subKt, err := NewKustTarget( + ldr, kt.rFactory, kt.tFactory) + if err != nil { + errs.Append(errors.Wrap(err, "couldn't make target for "+path)) + ldr.Cleanup() + continue + } + subRa, err := subKt.AccumulateTarget() + if err != nil { + errs.Append(errors.Wrap(err, "AccumulateTarget")) + ldr.Cleanup() + continue + } + err = ra.MergeAccumulator(subRa) + if err != nil { + errs.Append(errors.Wrap(err, path)) + } + ldr.Cleanup() + } + return ra, errs +} + +// newTransformer makes a Transformer that does a collection +// of object transformations. +func (kt *KustTarget) newTransformer( + patches []*resource.Resource, tConfig *config.TransformerConfig) ( + transformers.Transformer, error) { + var r []transformers.Transformer + t, err := kt.tFactory.MakePatchTransformer(patches, kt.rFactory.RF()) + if err != nil { + return nil, err + } + r = append(r, t) + r = append(r, transformers.NewNamespaceTransformer( + string(kt.kustomization.Namespace), tConfig.NameSpace)) + t, err = transformers.NewNamePrefixSuffixTransformer( + string(kt.kustomization.NamePrefix), + string(kt.kustomization.NameSuffix), + tConfig.NamePrefix, + ) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewLabelsMapTransformer( + kt.kustomization.CommonLabels, tConfig.CommonLabels) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewAnnotationsMapTransformer( + kt.kustomization.CommonAnnotations, tConfig.CommonAnnotations) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = patchtransformer.NewPatchJson6902Factory(kt.ldr). + MakePatchJson6902Transformer(kt.kustomization.PatchesJson6902) + if err != nil { + return nil, err + } + r = append(r, t) + t, err = transformers.NewImageTransformer(kt.kustomization.Images) + if err != nil { + return nil, err + } + r = append(r, t) + return transformers.NewMultiTransformer(r), nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/target/resaccumulator.go b/vendor/sigs.k8s.io/kustomize/pkg/target/resaccumulator.go new file mode 100644 index 000000000..b8c45015a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/target/resaccumulator.go @@ -0,0 +1,161 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package target + +import ( + "fmt" + "log" + "strings" + + "sigs.k8s.io/kustomize/pkg/resid" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers" + "sigs.k8s.io/kustomize/pkg/transformers/config" + "sigs.k8s.io/kustomize/pkg/types" +) + +// ResAccumulator accumulates resources and the rules +// used to customize those resources. +// TODO(monopole): Move to "accumulator" package and make members private. +// This will make a better separation between KustTarget, which should +// be mainly concerned with data loading, and this class, which could +// become the home of all transformation data and logic. +type ResAccumulator struct { + resMap resmap.ResMap + tConfig *config.TransformerConfig + varSet types.VarSet +} + +func MakeEmptyAccumulator() *ResAccumulator { + ra := &ResAccumulator{} + ra.resMap = make(resmap.ResMap) + ra.tConfig = &config.TransformerConfig{} + ra.varSet = types.VarSet{} + return ra +} + +// ResMap returns a copy of the internal resMap. +func (ra *ResAccumulator) ResMap() resmap.ResMap { + result := make(resmap.ResMap) + for k, v := range ra.resMap { + result[k] = v + } + return result +} + +// Vars returns a copy of underlying vars. +func (ra *ResAccumulator) Vars() []types.Var { + return ra.varSet.Set() +} + +func (ra *ResAccumulator) MergeResourcesWithErrorOnIdCollision( + resources resmap.ResMap) (err error) { + ra.resMap, err = resmap.MergeWithErrorOnIdCollision( + resources, ra.resMap) + return err +} + +func (ra *ResAccumulator) MergeResourcesWithOverride( + resources resmap.ResMap) (err error) { + ra.resMap, err = resmap.MergeWithOverride( + ra.resMap, resources) + return err +} + +func (ra *ResAccumulator) MergeConfig( + tConfig *config.TransformerConfig) (err error) { + ra.tConfig, err = ra.tConfig.Merge(tConfig) + return err +} + +func (ra *ResAccumulator) MergeVars(incoming []types.Var) error { + return ra.varSet.MergeSlice(incoming) +} + +func (ra *ResAccumulator) MergeAccumulator(other *ResAccumulator) (err error) { + err = ra.MergeResourcesWithErrorOnIdCollision(other.resMap) + if err != nil { + return err + } + err = ra.MergeConfig(other.tConfig) + if err != nil { + return err + } + return ra.varSet.MergeSet(&other.varSet) +} + +// makeVarReplacementMap returns a map of Var names to +// their final values. The values are strings intended +// for substitution wherever the $(var.Name) occurs. +func (ra *ResAccumulator) makeVarReplacementMap() (map[string]string, error) { + result := map[string]string{} + for _, v := range ra.Vars() { + matched := ra.resMap.GetMatchingIds( + resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name).GvknEquals) + if len(matched) > 1 { + return nil, fmt.Errorf( + "found %d resId matches for var %s "+ + "(unable to disambiguate)", + len(matched), v) + } + if len(matched) == 1 { + s, err := ra.resMap[matched[0]].GetFieldValue(v.FieldRef.FieldPath) + if err != nil { + return nil, fmt.Errorf( + "field specified in var '%v' "+ + "not found in corresponding resource", v) + } + result[v.Name] = s + } else { + return nil, fmt.Errorf( + "var '%v' cannot be mapped to a field "+ + "in the set of known resources", v) + } + } + return result, nil +} + +func (ra *ResAccumulator) Transform(t transformers.Transformer) error { + return t.Transform(ra.resMap) +} + +func (ra *ResAccumulator) ResolveVars() error { + replacementMap, err := ra.makeVarReplacementMap() + if err != nil { + return err + } + if len(replacementMap) == 0 { + return nil + } + t := transformers.NewRefVarTransformer( + replacementMap, ra.tConfig.VarReference) + err = ra.Transform(t) + if len(t.UnusedVars()) > 0 { + log.Printf( + "well-defined vars that were never replaced: %s\n", + strings.Join(t.UnusedVars(), ",")) + } + return err +} + +func (ra *ResAccumulator) FixBackReferences() (err error) { + if ra.tConfig.NameReference == nil { + return nil + } + return ra.Transform(transformers.NewNameReferenceTransformer( + ra.tConfig.NameReference)) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go new file mode 100644 index 000000000..275455904 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonannotations.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const commonAnnotationFieldSpecs = ` +commonAnnotations: +- path: metadata/annotations + create: true + +- path: spec/template/metadata/annotations + create: true + version: v1 + kind: ReplicationController + +- path: spec/template/metadata/annotations + create: true + kind: Deployment + +- path: spec/template/metadata/annotations + create: true + kind: ReplicaSet + +- path: spec/template/metadata/annotations + create: true + kind: DaemonSet + +- path: spec/template/metadata/annotations + create: true + kind: StatefulSet + +- path: spec/template/metadata/annotations + create: true + group: batch + kind: Job + +- path: spec/jobTemplate/metadata/annotations + create: true + group: batch + kind: CronJob + +- path: spec/jobTemplate/spec/template/metadata/annotations + create: true + group: batch + kind: CronJob + +` diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go new file mode 100644 index 000000000..66943c1ed --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/commonlabels.go @@ -0,0 +1,162 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const commonLabelFieldSpecs = ` +commonLabels: +- path: metadata/labels + create: true + +- path: spec/selector + create: true + version: v1 + kind: Service + +- path: spec/selector + create: true + version: v1 + kind: ReplicationController + +- path: spec/template/metadata/labels + create: true + version: v1 + kind: ReplicationController + +- path: spec/selector/matchLabels + create: true + kind: Deployment + +- path: spec/template/metadata/labels + create: true + kind: Deployment + +- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: Deployment + +- path: spec/selector/matchLabels + create: true + kind: ReplicaSet + +- path: spec/template/metadata/labels + create: true + kind: ReplicaSet + +- path: spec/selector/matchLabels + create: true + kind: DaemonSet + +- path: spec/template/metadata/labels + create: true + kind: DaemonSet + +- path: spec/selector/matchLabels + create: true + group: apps + kind: StatefulSet + +- path: spec/template/metadata/labels + create: true + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels + create: false + group: apps + kind: StatefulSet + +- path: spec/volumeClaimTemplates/metadata/labels + create: true + group: apps + kind: StatefulSet + +- path: spec/selector/matchLabels + create: false + group: batch + kind: Job + +- path: spec/template/metadata/labels + create: true + group: batch + kind: Job + +- path: spec/jobTemplate/spec/selector/matchLabels + create: false + group: batch + kind: CronJob + +- path: spec/jobTemplate/metadata/labels + create: true + group: batch + kind: CronJob + +- path: spec/jobTemplate/spec/template/metadata/labels + create: true + group: batch + kind: CronJob + +- path: spec/selector/matchLabels + create: false + group: policy + kind: PodDisruptionBudget + +- path: spec/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy + +- path: spec/ingress/from/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy + +- path: spec/egress/to/podSelector/matchLabels + create: false + group: networking.k8s.io + kind: NetworkPolicy +` diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go new file mode 100644 index 000000000..d96639a8a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/defaultconfig.go @@ -0,0 +1,49 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package defaultconfig provides the default +// transformer configurations +package defaultconfig + +import ( + "bytes" +) + +// GetDefaultFieldSpecs returns default fieldSpecs. +func GetDefaultFieldSpecs() []byte { + configData := [][]byte{ + []byte(namePrefixFieldSpecs), + []byte(commonLabelFieldSpecs), + []byte(commonAnnotationFieldSpecs), + []byte(namespaceFieldSpecs), + []byte(varReferenceFieldSpecs), + []byte(nameReferenceFieldSpecs), + } + return bytes.Join(configData, []byte("\n")) +} + +// GetDefaultFieldSpecsAsMap returns default fieldSpecs +// as a string->string map. +func GetDefaultFieldSpecsAsMap() map[string]string { + result := make(map[string]string) + result["nameprefix"] = namePrefixFieldSpecs + result["commonlabels"] = commonLabelFieldSpecs + result["commonannotations"] = commonAnnotationFieldSpecs + result["namespace"] = namespaceFieldSpecs + result["varreference"] = varReferenceFieldSpecs + result["namereference"] = nameReferenceFieldSpecs + return result +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go new file mode 100644 index 000000000..94fe07a48 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/nameprefix.go @@ -0,0 +1,24 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + namePrefixFieldSpecs = ` +namePrefix: +- path: metadata/name +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go new file mode 100644 index 000000000..35d4b7de0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namereference.go @@ -0,0 +1,317 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + nameReferenceFieldSpecs = ` +nameReference: +- kind: Deployment + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ReplicationController + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ReplicaSet + fieldSpecs: + - path: spec/scaleTargetRef/name + kind: HorizontalPodAutoscaler + +- kind: ConfigMap + version: v1 + fieldSpecs: + - path: spec/volumes/configMap/name + version: v1 + kind: Pod + - path: spec/containers/env/valueFrom/configMapKeyRef/name + version: v1 + kind: Pod + - path: spec/initContainers/env/valueFrom/configMapKeyRef/name + version: v1 + kind: Pod + - path: spec/containers/envFrom/configMapRef/name + version: v1 + kind: Pod + - path: spec/initContainers/envFrom/configMapRef/name + version: v1 + kind: Pod + - path: spec/template/spec/volumes/configMap/name + kind: Deployment + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: Deployment + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: Deployment + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: Deployment + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: Deployment + - path: spec/template/spec/volumes/projected/sources/configMap/name + kind: Deployment + - path: spec/template/spec/volumes/configMap/name + kind: ReplicaSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: ReplicaSet + - path: spec/template/spec/volumes/configMap/name + kind: DaemonSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: DaemonSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: DaemonSet + - path: spec/template/spec/volumes/configMap/name + kind: StatefulSet + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: StatefulSet + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: StatefulSet + - path: spec/template/spec/volumes/projected/sources/configMap/name + kind: StatefulSet + - path: spec/template/spec/volumes/configMap/name + kind: Job + - path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: Job + - path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: Job + - path: spec/template/spec/containers/envFrom/configMapRef/name + kind: Job + - path: spec/template/spec/initContainers/envFrom/configMapRef/name + kind: Job + - path: spec/jobTemplate/spec/template/spec/volumes/configMap/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/configMapKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/envFrom/configMapRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/configmapRef/name + kind: CronJob + +- kind: Secret + version: v1 + fieldSpecs: + - path: spec/volumes/secret/secretName + version: v1 + kind: Pod + - path: spec/containers/env/valueFrom/secretKeyRef/name + version: v1 + kind: Pod + - path: spec/initContainers/env/valueFrom/secretKeyRef/name + version: v1 + kind: Pod + - path: spec/containers/envFrom/secretRef/name + version: v1 + kind: Pod + - path: spec/initContainers/envFrom/secretRef/name + version: v1 + kind: Pod + - path: spec/imagePullSecrets/name + version: v1 + kind: Pod + - path: spec/template/spec/volumes/secret/secretName + kind: Deployment + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: Deployment + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: Deployment + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: Deployment + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: Deployment + - path: spec/template/spec/imagePullSecrets/name + kind: Deployment + - path: spec/template/spec/volumes/projected/sources/secret/name + kind: Deployment + - path: spec/template/spec/volumes/secret/secretName + kind: ReplicaSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: ReplicaSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: ReplicaSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: ReplicaSet + - path: spec/template/spec/imagePullSecrets/name + kind: ReplicaSet + - path: spec/template/spec/volumes/secret/secretName + kind: DaemonSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: DaemonSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: DaemonSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: DaemonSet + - path: spec/template/spec/imagePullSecrets/name + kind: DaemonSet + - path: spec/template/spec/volumes/secret/secretName + kind: StatefulSet + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: StatefulSet + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: StatefulSet + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: StatefulSet + - path: spec/template/spec/imagePullSecrets/name + kind: StatefulSet + - path: spec/template/spec/volumes/projected/sources/secret/name + kind: StatefulSet + - path: spec/template/spec/volumes/secret/secretName + kind: Job + - path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: Job + - path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: Job + - path: spec/template/spec/containers/envFrom/secretRef/name + kind: Job + - path: spec/template/spec/initContainers/envFrom/secretRef/name + kind: Job + - path: spec/template/spec/imagePullSecrets/name + kind: Job + - path: spec/jobTemplate/spec/template/spec/volumes/secret/secretName + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/secretKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/containers/envFrom/secretRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/secretRef/name + kind: CronJob + - path: spec/jobTemplate/spec/template/spec/imagePullSecrets/name + kind: CronJob + - path: spec/tls/secretName + kind: Ingress + - path: metadata/annotations/ingress.kubernetes.io\/auth-secret + kind: Ingress + - path: metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret + kind: Ingress + - path: imagePullSecrets/name + kind: ServiceAccount + - path: parameters/secretName + kind: StorageClass + - path: parameters/adminSecretName + kind: StorageClass + - path: parameters/userSecretName + kind: StorageClass + - path: parameters/secretRef + kind: StorageClass + - path: rules/resourceNames + kind: Role + - path: rules/resourceNames + kind: ClusterRole + +- kind: Service + version: v1 + fieldSpecs: + - path: spec/serviceName + kind: StatefulSet + group: apps + - path: spec/rules/http/paths/backend/serviceName + kind: Ingress + - path: spec/backend/serviceName + kind: Ingress + - path: spec/service/name + kind: APIService + group: apiregistration.k8s.io + +- kind: Role + group: rbac.authorization.k8s.io + fieldSpecs: + - path: roleRef/name + kind: RoleBinding + group: rbac.authorization.k8s.io + +- kind: ClusterRole + group: rbac.authorization.k8s.io + fieldSpecs: + - path: roleRef/name + kind: RoleBinding + group: rbac.authorization.k8s.io + - path: roleRef/name + kind: ClusterRoleBinding + group: rbac.authorization.k8s.io + +- kind: ServiceAccount + version: v1 + fieldSpecs: + - path: subjects/name + kind: RoleBinding + group: rbac.authorization.k8s.io + - path: subjects/name + kind: ClusterRoleBinding + group: rbac.authorization.k8s.io + - path: spec/serviceAccountName + kind: Pod + - path: spec/template/spec/serviceAccountName + kind: StatefulSet + - path: spec/template/spec/serviceAccountName + kind: Deployment + - path: spec/template/spec/serviceAccountName + kind: ReplicationController + - path: spec/jobTemplate/spec/template/spec/serviceAccountName + kind: CronJob + - path: spec/template/spec/serviceAccountName + kind: job + - path: spec/template/spec/serviceAccountName + kind: DaemonSet + +- kind: PersistentVolumeClaim + version: v1 + fieldSpecs: + - path: spec/volumes/persistentVolumeClaim/claimName + kind: Pod + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: StatefulSet + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: Deployment + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: ReplicationController + - path: spec/jobTemplate/spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: CronJob + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: Job + - path: spec/template/spec/volumes/persistentVolumeClaim/claimName + kind: DaemonSet + +- kind: PersistentVolume + version: v1 + fieldSpecs: + - path: spec/volumeName + kind: PersistentVolumeClaim +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go new file mode 100644 index 000000000..431eb0769 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/namespace.go @@ -0,0 +1,25 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + namespaceFieldSpecs = ` +namespace: +- path: metadata/namespace + create: true +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go new file mode 100644 index 000000000..71953f576 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig/varreference.go @@ -0,0 +1,162 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package defaultconfig + +const ( + varReferenceFieldSpecs = ` +varReference: +- path: spec/template/spec/initContainers/command + kind: StatefulSet + +- path: spec/template/spec/containers/command + kind: StatefulSet + +- path: spec/template/spec/initContainers/command + kind: Deployment + +- path: spec/template/spec/containers/command + kind: Deployment + +- path: spec/template/spec/initContainers/command + kind: DaemonSet + +- path: spec/template/spec/containers/command + kind: DaemonSet + +- path: spec/template/spec/containers/command + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/command + kind: CronJob + +- path: spec/template/spec/initContainers/args + kind: StatefulSet + +- path: spec/template/spec/containers/args + kind: StatefulSet + +- path: spec/template/spec/initContainers/args + kind: Deployment + +- path: spec/template/spec/containers/args + kind: Deployment + +- path: spec/template/spec/initContainers/args + kind: DaemonSet + +- path: spec/template/spec/containers/args + kind: DaemonSet + +- path: spec/template/spec/containers/args + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/args + kind: CronJob + +- path: spec/template/spec/initContainers/env/value + kind: StatefulSet + +- path: spec/template/spec/containers/env/value + kind: StatefulSet + +- path: spec/template/spec/initContainers/env/value + kind: Deployment + +- path: spec/template/spec/containers/env/value + kind: Deployment + +- path: spec/template/spec/initContainers/env/value + kind: DaemonSet + +- path: spec/template/spec/containers/env/value + kind: DaemonSet + +- path: spec/template/spec/containers/env/value + kind: Job + +- path: spec/jobTemplate/spec/template/spec/containers/env/value + kind: CronJob + +- path: spec/containers/command + kind: Pod + +- path: spec/containers/args + kind: Pod + +- path: spec/containers/env/value + kind: Pod + +- path: spec/initContainers/command + kind: Pod + +- path: spec/initContainers/args + kind: Pod + +- path: spec/initContainers/env/value + kind: Pod + +- path: spec/rules/host + kind: Ingress + +- path: spec/tls/hosts + kind: Ingress + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: StatefulSet + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: StatefulSet + +- path: spec/containers/volumeMounts/mountPath + kind: Pod + +- path: spec/initContainers/volumeMounts/mountPath + kind: Pod + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: ReplicaSet + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: ReplicaSet + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: Job + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: Job + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: CronJob + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: CronJob + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: DaemonSet + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: DaemonSet + +- path: spec/template/spec/containers/volumeMounts/mountPath + kind: Deployment + +- path: spec/template/spec/initContainers/volumeMounts/mountPath + kind: Deployment + +- path: metadata/labels +` +) diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go new file mode 100644 index 000000000..d0ea0d1dd --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factory.go @@ -0,0 +1,87 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "log" + + "github.com/ghodss/yaml" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +// Factory makes instances of TransformerConfig. +type Factory struct { + ldr ifc.Loader +} + +// MakeTransformerConfig returns a merger of custom config, +// if any, with default config. +func MakeTransformerConfig( + ldr ifc.Loader, paths []string) (*TransformerConfig, error) { + t1 := MakeDefaultConfig() + if len(paths) == 0 { + return t1, nil + } + t2, err := NewFactory(ldr).FromFiles(paths) + if err != nil { + return nil, err + } + return t1.Merge(t2) +} + +func NewFactory(l ifc.Loader) *Factory { + return &Factory{ldr: l} +} + +func (tf *Factory) loader() ifc.Loader { + if tf.ldr.(ifc.Loader) == nil { + log.Fatal("no loader") + } + return tf.ldr +} + +// FromFiles returns a TranformerConfig object from a list of files +func (tf *Factory) FromFiles( + paths []string) (*TransformerConfig, error) { + result := &TransformerConfig{} + for _, path := range paths { + data, err := tf.loader().Load(path) + if err != nil { + return nil, err + } + t, err := makeTransformerConfigFromBytes(data) + if err != nil { + return nil, err + } + result, err = result.Merge(t) + if err != nil { + return nil, err + } + } + return result, nil +} + +// makeTransformerConfigFromBytes returns a TransformerConfig object from bytes +func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) { + var t TransformerConfig + err := yaml.Unmarshal(data, &t) + if err != nil { + return nil, err + } + t.sortFields() + return &t, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go new file mode 100644 index 000000000..66a24dc86 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/factorycrd.go @@ -0,0 +1,201 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "encoding/json" + "strings" + + "github.com/ghodss/yaml" + "github.com/go-openapi/spec" + "github.com/pkg/errors" + "k8s.io/kube-openapi/pkg/common" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +type myProperties map[string]spec.Schema +type nameToApiMap map[string]common.OpenAPIDefinition + +// LoadConfigFromCRDs parse CRD schemas from paths into a TransformerConfig +func LoadConfigFromCRDs( + ldr ifc.Loader, paths []string) (*TransformerConfig, error) { + tc := MakeEmptyConfig() + for _, path := range paths { + content, err := ldr.Load(path) + if err != nil { + return nil, err + } + m, err := makeNameToApiMap(content) + if err != nil { + return nil, errors.Wrapf(err, "unable to parse open API definition from '%s'", path) + } + otherTc, err := makeConfigFromApiMap(m) + if err != nil { + return nil, err + } + tc, err = tc.Merge(otherTc) + if err != nil { + return nil, err + } + } + return tc, nil +} + +func makeNameToApiMap(content []byte) (result nameToApiMap, err error) { + if content[0] == '{' { + err = json.Unmarshal(content, &result) + } else { + err = yaml.Unmarshal(content, &result) + } + return +} + +func makeConfigFromApiMap(m nameToApiMap) (*TransformerConfig, error) { + result := MakeEmptyConfig() + for name, api := range m { + if !looksLikeAk8sType(api.Schema.SchemaProps.Properties) { + continue + } + tc := MakeEmptyConfig() + err := loadCrdIntoConfig( + tc, makeGvkFromTypeName(name), m, name, []string{}) + if err != nil { + return result, err + } + result, err = result.Merge(tc) + if err != nil { + return result, err + } + } + return result, nil +} + +// TODO: Get Group and Version for CRD from the +// openAPI definition once +// "x-kubernetes-group-version-kind" is available in CRD +func makeGvkFromTypeName(n string) gvk.Gvk { + names := strings.Split(n, ".") + kind := names[len(names)-1] + return gvk.Gvk{Kind: kind} +} + +func looksLikeAk8sType(properties myProperties) bool { + _, ok := properties["kind"] + if !ok { + return false + } + _, ok = properties["apiVersion"] + if !ok { + return false + } + _, ok = properties["metadata"] + if !ok { + return false + } + return true +} + +const ( + // "x-kubernetes-annotation": "" + xAnnotation = "x-kubernetes-annotation" + + // "x-kubernetes-label-selector": "" + xLabelSelector = "x-kubernetes-label-selector" + + // "x-kubernetes-identity": "" + xIdentity = "x-kubernetes-identity" + + // "x-kubernetes-object-ref-api-version": + xVersion = "x-kubernetes-object-ref-api-version" + + // "x-kubernetes-object-ref-kind": + xKind = "x-kubernetes-object-ref-kind" + + // "x-kubernetes-object-ref-name-key": "name" + // default is "name" + xNameKey = "x-kubernetes-object-ref-name-key" +) + +// loadCrdIntoConfig loads a CRD spec into a TransformerConfig +func loadCrdIntoConfig( + theConfig *TransformerConfig, theGvk gvk.Gvk, theMap nameToApiMap, + typeName string, path []string) (err error) { + api, ok := theMap[typeName] + if !ok { + return nil + } + for propName, property := range api.Schema.SchemaProps.Properties { + _, annotate := property.Extensions.GetString(xAnnotation) + if annotate { + err = theConfig.AddAnnotationFieldSpec( + makeFs(theGvk, append(path, propName))) + if err != nil { + return + } + } + _, label := property.Extensions.GetString(xLabelSelector) + if label { + err = theConfig.AddLabelFieldSpec( + makeFs(theGvk, append(path, propName))) + if err != nil { + return + } + } + _, identity := property.Extensions.GetString(xIdentity) + if identity { + err = theConfig.AddPrefixFieldSpec( + makeFs(theGvk, append(path, propName))) + if err != nil { + return + } + } + version, ok := property.Extensions.GetString(xVersion) + if ok { + kind, ok := property.Extensions.GetString(xKind) + if ok { + nameKey, ok := property.Extensions.GetString(xNameKey) + if !ok { + nameKey = "name" + } + err = theConfig.AddNamereferenceFieldSpec( + NameBackReferences{ + Gvk: gvk.Gvk{Kind: kind, Version: version}, + FieldSpecs: []FieldSpec{ + makeFs(theGvk, append(path, propName, nameKey))}, + }) + if err != nil { + return + } + } + } + if property.Ref.GetURL() != nil { + loadCrdIntoConfig( + theConfig, theGvk, theMap, + property.Ref.String(), append(path, propName)) + } + } + return nil +} + +func makeFs(in gvk.Gvk, path []string) FieldSpec { + return FieldSpec{ + CreateIfNotPresent: false, + Gvk: in, + Path: strings.Join(path, "/"), + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go new file mode 100644 index 000000000..5b0f6ee33 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/fieldspec.go @@ -0,0 +1,139 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "fmt" + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// FieldSpec completely specifies a kustomizable field in +// an unstructured representation of a k8s API object. +// It helps define the operands of transformations. +// +// For example, a directive to add a common label to objects +// will need to know that a 'Deployment' object (in API group +// 'apps', any version) can have labels at field path +// 'spec/template/metadata/labels', and further that it is OK +// (or not OK) to add that field path to the object if the +// field path doesn't exist already. +// +// This would look like +// { +// group: apps +// kind: Deployment +// path: spec/template/metadata/labels +// create: true +// } +type FieldSpec struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Path string `json:"path,omitempty" yaml:"path,omitempty"` + CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"` +} + +const ( + escapedForwardSlash = "\\/" + tempSlashReplacement = "???" +) + +func (fs FieldSpec) String() string { + return fmt.Sprintf( + "%s:%v:%s", fs.Gvk.String(), fs.CreateIfNotPresent, fs.Path) +} + +// If true, the primary key is the same, but other fields might not be. +func (fs FieldSpec) effectivelyEquals(other FieldSpec) bool { + return fs.IsSelected(&other.Gvk) && fs.Path == other.Path +} + +// PathSlice converts the path string to a slice of strings, +// separated by a '/'. Forward slash can be contained in a +// fieldname. such as ingress.kubernetes.io/auth-secret in +// Ingress annotations. To deal with this special case, the +// path to this field should be formatted as +// +// metadata/annotations/ingress.kubernetes.io\/auth-secret +// +// Then PathSlice will return +// +// []string{ +// "metadata", +// "annotations", +// "ingress.auth-secretkubernetes.io/auth-secret" +// } +func (fs FieldSpec) PathSlice() []string { + if !strings.Contains(fs.Path, escapedForwardSlash) { + return strings.Split(fs.Path, "/") + } + s := strings.Replace(fs.Path, escapedForwardSlash, tempSlashReplacement, -1) + paths := strings.Split(s, "/") + var result []string + for _, path := range paths { + result = append(result, strings.Replace(path, tempSlashReplacement, "/", -1)) + } + return result +} + +type fsSlice []FieldSpec + +func (s fsSlice) Len() int { return len(s) } +func (s fsSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s fsSlice) Less(i, j int) bool { + return s[i].Gvk.IsLessThan(s[j].Gvk) +} + +// mergeAll merges the argument into this, returning the result. +// Items already present are ignored. +// Items that conflict (primary key matches, but remain data differs) +// result in an error. +func (s fsSlice) mergeAll(incoming fsSlice) (result fsSlice, err error) { + result = s + for _, x := range incoming { + result, err = result.mergeOne(x) + if err != nil { + return nil, err + } + } + return result, nil +} + +// mergeOne merges the argument into this, returning the result. +// If the item's primary key is already present, and there are no +// conflicts, it is ignored (we don't want duplicates). +// If there is a conflict, the merge fails. +func (s fsSlice) mergeOne(x FieldSpec) (fsSlice, error) { + i := s.index(x) + if i > -1 { + // It's already there. + if s[i].CreateIfNotPresent != x.CreateIfNotPresent { + return nil, fmt.Errorf("conflicting fieldspecs") + } + return s, nil + } + return append(s, x), nil +} + +func (s fsSlice) index(fs FieldSpec) int { + for i, x := range s { + if x.effectivelyEquals(fs) { + return i + } + } + return -1 +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go new file mode 100644 index 000000000..172e4b3ca --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/namebackreferences.go @@ -0,0 +1,105 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +// NameBackReferences is an association between a gvk.GVK and a list +// of FieldSpec instances that could refer to it. +// +// It is used to handle name changes, and can be thought of as a +// a contact list. If you change your own contact info (name, +// phone number, etc.), you must tell your contacts or they won't +// know about the change. +// +// For example, ConfigMaps can be used by Pods and everything that +// contains a Pod; Deployment, Job, StatefulSet, etc. To change +// the name of a ConfigMap instance from 'alice' to 'bob', one +// must visit all objects that could refer to the ConfigMap, see if +// they mention 'alice', and if so, change the reference to 'bob'. +// +// The NameBackReferences instance to aid in this could look like +// { +// kind: ConfigMap +// version: v1 +// FieldSpecs: +// - kind: Pod +// version: v1 +// path: spec/volumes/configMap/name +// - kind: Deployment +// path: spec/template/spec/volumes/configMap/name +// - kind: Job +// path: spec/template/spec/volumes/configMap/name +// (etc.) +// } +type NameBackReferences struct { + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + FieldSpecs fsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"` +} + +func (n NameBackReferences) String() string { + var r []string + for _, f := range n.FieldSpecs { + r = append(r, f.String()) + } + return n.Gvk.String() + ": (\n" + + strings.Join(r, "\n") + "\n)" +} + +type nbrSlice []NameBackReferences + +func (s nbrSlice) Len() int { return len(s) } +func (s nbrSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s nbrSlice) Less(i, j int) bool { + return s[i].Gvk.IsLessThan(s[j].Gvk) +} + +func (s nbrSlice) mergeAll(o nbrSlice) (result nbrSlice, err error) { + result = s + for _, r := range o { + result, err = result.mergeOne(r) + if err != nil { + return nil, err + } + } + return result, nil +} + +func (s nbrSlice) mergeOne(other NameBackReferences) (nbrSlice, error) { + var result nbrSlice + var err error + found := false + for _, c := range s { + if c.Gvk.Equals(other.Gvk) { + c.FieldSpecs, err = c.FieldSpecs.mergeAll(other.FieldSpecs) + if err != nil { + return nil, err + } + found = true + } + result = append(result, c) + } + + if !found { + result = append(result, other) + } + return result, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go new file mode 100644 index 000000000..556f0b814 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/config/transformerconfig.go @@ -0,0 +1,134 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package config provides the functions to load default or user provided configurations +// for different transformers +package config + +import ( + "log" + "sort" + + "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig" +) + +// TransformerConfig holds the data needed to perform transformations. +type TransformerConfig struct { + NamePrefix fsSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` + NameSuffix fsSlice `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"` + NameSpace fsSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"` + CommonLabels fsSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` + CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` + NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"` + VarReference fsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"` +} + +// MakeEmptyConfig returns an empty TransformerConfig object +func MakeEmptyConfig() *TransformerConfig { + return &TransformerConfig{} +} + +// MakeDefaultConfig returns a default TransformerConfig. +func MakeDefaultConfig() *TransformerConfig { + c, err := makeTransformerConfigFromBytes( + defaultconfig.GetDefaultFieldSpecs()) + if err != nil { + log.Fatalf("Unable to make default transformconfig: %v", err) + } + return c +} + +// sortFields provides determinism in logging, tests, etc. +func (t *TransformerConfig) sortFields() { + sort.Sort(t.NamePrefix) + sort.Sort(t.NameSpace) + sort.Sort(t.CommonLabels) + sort.Sort(t.CommonAnnotations) + sort.Sort(t.NameReference) + sort.Sort(t.VarReference) +} + +// AddPrefixFieldSpec adds a FieldSpec to NamePrefix +func (t *TransformerConfig) AddPrefixFieldSpec(fs FieldSpec) (err error) { + t.NamePrefix, err = t.NamePrefix.mergeOne(fs) + return err +} + +// AddSuffixFieldSpec adds a FieldSpec to NameSuffix +func (t *TransformerConfig) AddSuffixFieldSpec(fs FieldSpec) (err error) { + t.NameSuffix, err = t.NameSuffix.mergeOne(fs) + return err +} + +// AddLabelFieldSpec adds a FieldSpec to CommonLabels +func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) (err error) { + t.CommonLabels, err = t.CommonLabels.mergeOne(fs) + return err +} + +// AddAnnotationFieldSpec adds a FieldSpec to CommonAnnotations +func (t *TransformerConfig) AddAnnotationFieldSpec(fs FieldSpec) (err error) { + t.CommonAnnotations, err = t.CommonAnnotations.mergeOne(fs) + return err +} + +// AddNamereferenceFieldSpec adds a NameBackReferences to NameReference +func (t *TransformerConfig) AddNamereferenceFieldSpec( + nbrs NameBackReferences) (err error) { + t.NameReference, err = t.NameReference.mergeOne(nbrs) + return err +} + +// Merge merges two TransformerConfigs objects into +// a new TransformerConfig object +func (t *TransformerConfig) Merge(input *TransformerConfig) ( + merged *TransformerConfig, err error) { + if input == nil { + return t, nil + } + merged = &TransformerConfig{} + merged.NamePrefix, err = t.NamePrefix.mergeAll(input.NamePrefix) + if err != nil { + return nil, err + } + merged.NameSuffix, err = t.NameSuffix.mergeAll(input.NameSuffix) + if err != nil { + return nil, err + } + merged.NameSpace, err = t.NameSpace.mergeAll(input.NameSpace) + if err != nil { + return nil, err + } + merged.CommonAnnotations, err = t.CommonAnnotations.mergeAll( + input.CommonAnnotations) + if err != nil { + return nil, err + } + merged.CommonLabels, err = t.CommonLabels.mergeAll(input.CommonLabels) + if err != nil { + return nil, err + } + merged.VarReference, err = t.VarReference.mergeAll(input.VarReference) + if err != nil { + return nil, err + } + merged.NameReference, err = t.NameReference.mergeAll(input.NameReference) + if err != nil { + return nil, err + } + merged.sortFields() + return merged, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/image.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/image.go new file mode 100644 index 000000000..2e0797694 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/image.go @@ -0,0 +1,171 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" + "regexp" + "strings" + + "sigs.k8s.io/kustomize/pkg/image" + "sigs.k8s.io/kustomize/pkg/resmap" +) + +// imageTransformer replace image names and tags +type imageTransformer struct { + images []image.Image +} + +var _ Transformer = &imageTransformer{} + +// NewImageTransformer constructs an imageTransformer. +func NewImageTransformer(slice []image.Image) (Transformer, error) { + return &imageTransformer{slice}, nil +} + +// Transform finds the matching images and replaces name, tag and/or digest +func (pt *imageTransformer) Transform(resources resmap.ResMap) error { + if len(pt.images) == 0 { + return nil + } + for _, res := range resources { + err := pt.findAndReplaceImage(res.Map()) + if err != nil { + return err + } + } + return nil +} + +/* + findAndReplaceImage replaces the image name and tags inside one object + It searches the object for container session + then loops though all images inside containers session, + finds matched ones and update the image name and tag name +*/ +func (pt *imageTransformer) findAndReplaceImage(obj map[string]interface{}) error { + paths := []string{"containers", "initContainers"} + found := false + for _, path := range paths { + _, found = obj[path] + if found { + err := pt.updateContainers(obj, path) + if err != nil { + return err + } + } + } + if !found { + return pt.findContainers(obj) + } + return nil +} + +func (pt *imageTransformer) updateContainers(obj map[string]interface{}, path string) error { + containers, ok := obj[path].([]interface{}) + if !ok { + return fmt.Errorf("containers path is not of type []interface{} but %T", obj[path]) + } + for i := range containers { + container := containers[i].(map[string]interface{}) + containerImage, found := container["image"] + if !found { + continue + } + + imageName := containerImage.(string) + for _, img := range pt.images { + if !isImageMatched(imageName, img.Name) { + continue + } + name, tag := split(imageName) + if img.NewName != "" { + name = img.NewName + } + if img.NewTag != "" { + tag = ":" + img.NewTag + } + if img.Digest != "" { + tag = "@" + img.Digest + } + container["image"] = name + tag + break + } + } + return nil +} + +func (pt *imageTransformer) findContainers(obj map[string]interface{}) error { + for key := range obj { + switch typedV := obj[key].(type) { + case map[string]interface{}: + err := pt.findAndReplaceImage(typedV) + if err != nil { + return err + } + case []interface{}: + for i := range typedV { + item := typedV[i] + typedItem, ok := item.(map[string]interface{}) + if ok { + err := pt.findAndReplaceImage(typedItem) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func isImageMatched(s, t string) bool { + // Tag values are limited to [a-zA-Z0-9_.-]. + pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$") + return pattern.MatchString(s) +} + +// split separates and returns the name and tag parts +// from the image string using either colon `:` or at `@` separators. +// Note that the returned tag keeps its separator. +func split(imageName string) (name string, tag string) { + // check if image name contains a domain + // if domain is present, ignore domain and check for `:` + ic := -1 + if slashIndex := strings.Index(imageName, "/"); slashIndex < 0 { + ic = strings.LastIndex(imageName, ":") + } else { + lastIc := strings.LastIndex(imageName[slashIndex:], ":") + // set ic only if `:` is present + if lastIc > 0 { + ic = slashIndex + lastIc + } + } + ia := strings.LastIndex(imageName, "@") + if ic < 0 && ia < 0 { + return imageName, "" + } + + i := ic + if ic < 0 { + i = ia + } + + name = imageName[:i] + tag = imageName[i:] + return +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go new file mode 100644 index 000000000..836abcaa4 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/labelsandannotations.go @@ -0,0 +1,86 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +// mapTransformer applies a string->string map to fieldSpecs. +type mapTransformer struct { + m map[string]string + fieldSpecs []config.FieldSpec +} + +var _ Transformer = &mapTransformer{} + +// NewLabelsMapTransformer constructs a mapTransformer. +func NewLabelsMapTransformer( + m map[string]string, fs []config.FieldSpec) (Transformer, error) { + return NewMapTransformer(fs, m) +} + +// NewAnnotationsMapTransformer construct a mapTransformer. +func NewAnnotationsMapTransformer( + m map[string]string, fs []config.FieldSpec) (Transformer, error) { + return NewMapTransformer(fs, m) +} + +// NewMapTransformer construct a mapTransformer. +func NewMapTransformer( + pc []config.FieldSpec, m map[string]string) (Transformer, error) { + if m == nil { + return NewNoOpTransformer(), nil + } + if pc == nil { + return nil, errors.New("fieldSpecs is not expected to be nil") + } + return &mapTransformer{fieldSpecs: pc, m: m}, nil +} + +// Transform apply each pair in the mapTransformer to the +// fields specified in mapTransformer. +func (o *mapTransformer) Transform(m resmap.ResMap) error { + for id := range m { + objMap := m[id].Map() + for _, path := range o.fieldSpecs { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, o.addMap) + if err != nil { + return err + } + } + } + return nil +} + +func (o *mapTransformer) addMap(in interface{}) (interface{}, error) { + m, ok := in.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, m) + } + for k, v := range o.m { + m[k] = v + } + return m, nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go new file mode 100644 index 000000000..d5921d1a9 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/multitransformer.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" + "sigs.k8s.io/kustomize/pkg/resource" + + "sigs.k8s.io/kustomize/pkg/resmap" +) + +// multiTransformer contains a list of transformers. +type multiTransformer struct { + transformers []Transformer + checkConflictEnabled bool + rf *resource.Factory +} + +var _ Transformer = &multiTransformer{} + +// NewMultiTransformer constructs a multiTransformer. +func NewMultiTransformer(t []Transformer) Transformer { + r := &multiTransformer{ + transformers: make([]Transformer, len(t)), + checkConflictEnabled: false} + copy(r.transformers, t) + return r +} + +// NewMultiTransformerWithConflictCheck constructs a multiTransformer with checking of conflicts. +func NewMultiTransformerWithConflictCheck(t []Transformer) Transformer { + r := &multiTransformer{ + transformers: make([]Transformer, len(t)), + checkConflictEnabled: true} + copy(r.transformers, t) + return r +} + +// Transform prepends the name prefix. +func (o *multiTransformer) Transform(m resmap.ResMap) error { + if o.checkConflictEnabled { + return o.transformWithCheckConflict(m) + } + return o.transform(m) +} +func (o *multiTransformer) transform(m resmap.ResMap) error { + for _, t := range o.transformers { + err := t.Transform(m) + if err != nil { + return err + } + } + return nil +} + +// Of the len(o.transformers)! possible transformer orderings, compare to a reversed order. +// A spot check to perform when the transformations are supposed to be commutative. +// Fail if there's a difference in the result. +func (o *multiTransformer) transformWithCheckConflict(m resmap.ResMap) error { + mcopy := m.DeepCopy(o.rf) + err := o.transform(m) + if err != nil { + return err + } + o.reverseTransformers() + err = o.transform(mcopy) + if err != nil { + return err + } + err = m.ErrorIfNotEqual(mcopy) + if err != nil { + return fmt.Errorf("found conflict between different patches\n%v", err) + } + return nil +} + +func (o *multiTransformer) reverseTransformers() { + for i, j := 0, len(o.transformers)-1; i < j; i, j = i+1, j-1 { + o.transformers[i], o.transformers[j] = o.transformers[j], o.transformers[i] + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/mutatefield.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/mutatefield.go new file mode 100644 index 000000000..eddfeee20 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/mutatefield.go @@ -0,0 +1,81 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" + "log" + "strings" +) + +type mutateFunc func(interface{}) (interface{}, error) + +func mutateField( + m map[string]interface{}, + pathToField []string, + createIfNotPresent bool, + fns ...mutateFunc) error { + if len(pathToField) == 0 { + return nil + } + + _, found := m[pathToField[0]] + if !found { + if !createIfNotPresent { + return nil + } + m[pathToField[0]] = map[string]interface{}{} + } + + if len(pathToField) == 1 { + var err error + for _, fn := range fns { + m[pathToField[0]], err = fn(m[pathToField[0]]) + if err != nil { + return err + } + } + return nil + } + + v := m[pathToField[0]] + newPathToField := pathToField[1:] + switch typedV := v.(type) { + case nil: + log.Printf( + "nil value at `%s` ignored in mutation attempt", + strings.Join(pathToField, ".")) + return nil + case map[string]interface{}: + return mutateField(typedV, newPathToField, createIfNotPresent, fns...) + case []interface{}: + for i := range typedV { + item := typedV[i] + typedItem, ok := item.(map[string]interface{}) + if !ok { + return fmt.Errorf("%#v is expected to be %T", item, typedItem) + } + err := mutateField(typedItem, newPathToField, createIfNotPresent, fns...) + if err != nil { + return err + } + } + return nil + default: + return fmt.Errorf("%#v is not expected to be a primitive type", typedV) + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go new file mode 100644 index 000000000..a4e8a7f8e --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namereference.go @@ -0,0 +1,144 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "fmt" + "log" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type nameReferenceTransformer struct { + backRefs []config.NameBackReferences +} + +var _ Transformer = &nameReferenceTransformer{} + +// NewNameReferenceTransformer constructs a nameReferenceTransformer +// with a given slice of NameBackReferences. +func NewNameReferenceTransformer(br []config.NameBackReferences) Transformer { + if br == nil { + log.Fatal("backrefs not expected to be nil") + } + return &nameReferenceTransformer{backRefs: br} +} + +// Transform updates name references in resource A that refer to resource B, +// given that B's name may have changed. +// +// For example, a HorizontalPodAutoscaler (HPA) necessarily refers to a +// Deployment (the thing that the HPA scales). The Deployment name might change +// (e.g. prefix added), and the reference in the HPA has to be fixed. +// +// In the outer loop below, we encounter an HPA. In scanning backrefs, we +// find that HPA refers to a Deployment. So we find all resources in the same +// namespace as the HPA (and with the same prefix and suffix), and look through +// them to find all the Deployments with a resId that has a Name matching the +// field in HPA. For each match, we overwrite the HPA name field with the value +// found in the Deployment's name field (the name in the raw object - the +// modified name - not the unmodified name in the resId). +// +// This assumes that the name stored in a ResId (the ResMap key) isn't modified +// by name transformers. Name transformers should only modify the name in the +// body of the resource object (the value in the ResMap). +func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error { + // TODO: Too much looping. + // Even more hidden loops in FilterBy, + // updateNameReference and FindByGVKN. + for id := range m { + for _, backRef := range o.backRefs { + for _, fSpec := range backRef.FieldSpecs { + if id.Gvk().IsSelected(&fSpec.Gvk) { + err := mutateField( + m[id].Map(), fSpec.PathSlice(), + fSpec.CreateIfNotPresent, + o.updateNameReference( + backRef.Gvk, m.FilterBy(id))) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func (o *nameReferenceTransformer) updateNameReference( + backRef gvk.Gvk, m resmap.ResMap) func(in interface{}) (interface{}, error) { + return func(in interface{}) (interface{}, error) { + switch in.(type) { + case string: + s, _ := in.(string) + for id, res := range m { + if id.Gvk().IsSelected(&backRef) && id.Name() == s { + matchedIds := m.GetMatchingIds(id.GvknEquals) + // If there's more than one match, there's no way + // to know which one to pick, so emit error. + if len(matchedIds) > 1 { + return nil, fmt.Errorf( + "Multiple matches for name %s:\n %v", id, matchedIds) + } + // Return transformed name of the object, + // complete with prefixes, hashes, etc. + return res.GetName(), nil + } + } + return in, nil + case []interface{}: + l, _ := in.([]interface{}) + var names []string + for _, item := range l { + name, ok := item.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", item, name) + } + names = append(names, name) + } + for id, res := range m { + indexes := indexOf(id.Name(), names) + if id.Gvk().IsSelected(&backRef) && len(indexes) > 0 { + matchedIds := m.GetMatchingIds(id.GvknEquals) + if len(matchedIds) > 1 { + return nil, fmt.Errorf( + "Multiple matches for name %s:\n %v", id, matchedIds) + } + for _, index := range indexes { + l[index] = res.GetName() + } + return l, nil + } + } + return in, nil + default: + return nil, fmt.Errorf("%#v is expected to be either a string or a []interface{}", in) + } + } +} + +func indexOf(s string, slice []string) []int { + var index []int + for i, item := range slice { + if item == s { + index = append(index, i) + } + } + return index +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go new file mode 100644 index 000000000..5f0c06482 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/namespace.go @@ -0,0 +1,121 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type namespaceTransformer struct { + namespace string + fieldSpecsToUse []config.FieldSpec + fieldSpecsToSkip []config.FieldSpec +} + +var _ Transformer = &namespaceTransformer{} + +// NewNamespaceTransformer construct a namespaceTransformer. +func NewNamespaceTransformer(ns string, cf []config.FieldSpec) Transformer { + if len(ns) == 0 { + return NewNoOpTransformer() + } + var skip []config.FieldSpec + for _, g := range gvk.ClusterLevelGvks() { + skip = append(skip, config.FieldSpec{Gvk: g}) + } + return &namespaceTransformer{ + namespace: ns, + fieldSpecsToUse: cf, + fieldSpecsToSkip: skip, + } +} + +// Transform adds the namespace. +func (o *namespaceTransformer) Transform(m resmap.ResMap) error { + mf := resmap.ResMap{} + + for id := range m { + found := false + for _, path := range o.fieldSpecsToSkip { + if id.Gvk().IsSelected(&path.Gvk) { + found = true + break + } + } + if !found { + mf[id] = m[id] + delete(m, id) + } + } + + for id := range mf { + objMap := mf[id].Map() + for _, path := range o.fieldSpecsToUse { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + + err := mutateField(objMap, path.PathSlice(), path.CreateIfNotPresent, func(_ interface{}) (interface{}, error) { + return o.namespace, nil + }) + if err != nil { + return err + } + newid := id.CopyWithNewNamespace(o.namespace) + m[newid] = mf[id] + } + + } + o.updateClusterRoleBinding(m) + return nil +} + +func (o *namespaceTransformer) updateClusterRoleBinding(m resmap.ResMap) { + saMap := map[string]bool{} + for id := range m { + if id.Gvk().Equals(gvk.Gvk{Version: "v1", Kind: "ServiceAccount"}) { + saMap[id.Name()] = true + } + } + + for id := range m { + if id.Gvk().Kind != "ClusterRoleBinding" && id.Gvk().Kind != "RoleBinding" { + continue + } + objMap := m[id].Map() + subjects := objMap["subjects"].([]interface{}) + for i := range subjects { + subject := subjects[i].(map[string]interface{}) + kind, foundk := subject["kind"] + name, foundn := subject["name"] + if !foundk || !foundn || kind.(string) != "ServiceAccount" { + continue + } + // a ServiceAccount named “default” exists in every active namespace + if name.(string) == "default" || saMap[name.(string)] { + subject := subjects[i].(map[string]interface{}) + mutateField(subject, []string{"namespace"}, true, func(_ interface{}) (interface{}, error) { + return o.namespace, nil + }) + subjects[i] = subject + } + } + objMap["subjects"] = subjects + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go new file mode 100644 index 000000000..c07389b31 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/nooptransformer.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import "sigs.k8s.io/kustomize/pkg/resmap" + +// noOpTransformer contains a no-op transformer. +type noOpTransformer struct{} + +var _ Transformer = &noOpTransformer{} + +// NewNoOpTransformer constructs a noOpTransformer. +func NewNoOpTransformer() Transformer { + return &noOpTransformer{} +} + +// Transform does nothing. +func (o *noOpTransformer) Transform(_ resmap.ResMap) error { + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go new file mode 100644 index 000000000..c4ca85f53 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/prefixsuffixname.go @@ -0,0 +1,109 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package transformers + +import ( + "errors" + "fmt" + + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +// namePrefixSuffixTransformer contains the prefix, suffix, and the FieldSpecs +// for each field needing a name prefix and suffix. +type namePrefixSuffixTransformer struct { + prefix string + suffix string + fieldSpecsToUse []config.FieldSpec + fieldSpecsToSkip []config.FieldSpec +} + +var _ Transformer = &namePrefixSuffixTransformer{} + +var prefixSuffixFieldSpecsToSkip = []config.FieldSpec{ + { + Gvk: gvk.Gvk{Kind: "CustomResourceDefinition"}, + }, +} + +// NewNamePrefixSuffixTransformer makes a namePrefixSuffixTransformer. +func NewNamePrefixSuffixTransformer( + np, ns string, fieldSpecs []config.FieldSpec) (Transformer, error) { + if len(np) == 0 && len(ns) == 0 { + return NewNoOpTransformer(), nil + } + if fieldSpecs == nil { + return nil, errors.New("fieldSpecs is not expected to be nil") + } + return &namePrefixSuffixTransformer{ + prefix: np, + suffix: ns, + fieldSpecsToUse: fieldSpecs, + fieldSpecsToSkip: prefixSuffixFieldSpecsToSkip}, nil +} + +// Transform prepends the name prefix and appends the name suffix. +func (o *namePrefixSuffixTransformer) Transform(m resmap.ResMap) error { + // Fill map "mf" with entries subject to name modification, and + // delete these entries from "m", so that for now m retains only + // the entries whose names will not be modified. + mf := resmap.ResMap{} + for id := range m { + found := false + for _, path := range o.fieldSpecsToSkip { + if id.Gvk().IsSelected(&path.Gvk) { + found = true + break + } + } + if !found { + mf[id] = m[id] + delete(m, id) + } + } + + for id := range mf { + objMap := mf[id].Map() + for _, path := range o.fieldSpecsToUse { + if !id.Gvk().IsSelected(&path.Gvk) { + continue + } + err := mutateField( + objMap, + path.PathSlice(), + path.CreateIfNotPresent, + o.addPrefixSuffix) + if err != nil { + return err + } + newId := id.CopyWithNewPrefixSuffix(o.prefix, o.suffix) + m[newId] = mf[id] + } + } + return nil +} + +func (o *namePrefixSuffixTransformer) addPrefixSuffix( + in interface{}) (interface{}, error) { + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, s) + } + return fmt.Sprintf("%s%s%s", o.prefix, s, o.suffix), nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go new file mode 100644 index 000000000..b31ec6e7a --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/refvars.go @@ -0,0 +1,94 @@ +package transformers + +import ( + "fmt" + "sigs.k8s.io/kustomize/pkg/expansion" + "sigs.k8s.io/kustomize/pkg/resmap" + "sigs.k8s.io/kustomize/pkg/transformers/config" +) + +type RefVarTransformer struct { + varMap map[string]string + replacementCounts map[string]int + fieldSpecs []config.FieldSpec + mappingFunc func(string) string +} + +// NewRefVarTransformer returns a new RefVarTransformer +// that replaces $(VAR) style variables with values. +// The fieldSpecs are the places to look for occurrences of $(VAR). +func NewRefVarTransformer( + varMap map[string]string, fs []config.FieldSpec) *RefVarTransformer { + return &RefVarTransformer{ + varMap: varMap, + fieldSpecs: fs, + } +} + +// replaceVars accepts as 'in' a string, or string array, which can have +// embedded instances of $VAR style variables, e.g. a container command string. +// The function returns the string with the variables expanded to their final +// values. +func (rv *RefVarTransformer) replaceVars(in interface{}) (interface{}, error) { + switch vt := in.(type) { + case []interface{}: + var xs []string + for _, a := range in.([]interface{}) { + xs = append(xs, expansion.Expand(a.(string), rv.mappingFunc)) + } + return xs, nil + case map[string]interface{}: + inMap := in.(map[string]interface{}) + xs := make(map[string]interface{}, len(inMap)) + for k, v := range inMap { + s, ok := v.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", v, s) + } + xs[k] = expansion.Expand(s, rv.mappingFunc) + } + return xs, nil + case interface{}: + s, ok := in.(string) + if !ok { + return nil, fmt.Errorf("%#v is expected to be %T", in, s) + } + return expansion.Expand(s, rv.mappingFunc), nil + case nil: + return nil, nil + default: + return "", fmt.Errorf("invalid type encountered %T", vt) + } +} + +// UnusedVars returns slice of Var names that were unused +// after a Transform run. +func (rv *RefVarTransformer) UnusedVars() []string { + var unused []string + for k := range rv.varMap { + _, ok := rv.replacementCounts[k] + if !ok { + unused = append(unused, k) + } + } + return unused +} + +// Transform replaces $(VAR) style variables with values. +func (rv *RefVarTransformer) Transform(m resmap.ResMap) error { + rv.replacementCounts = make(map[string]int) + rv.mappingFunc = expansion.MappingFuncFor( + rv.replacementCounts, rv.varMap) + for id, res := range m { + for _, fieldSpec := range rv.fieldSpecs { + if id.Gvk().IsSelected(&fieldSpec.Gvk) { + if err := mutateField( + res.Map(), fieldSpec.PathSlice(), + false, rv.replaceVars); err != nil { + return err + } + } + } + } + return nil +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go b/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go new file mode 100644 index 000000000..dc6f8807c --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/transformers/transformer.go @@ -0,0 +1,26 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package transformers has implementations of resmap.ResMap transformers. +package transformers + +import "sigs.k8s.io/kustomize/pkg/resmap" + +// A Transformer modifies an instance of resmap.ResMap. +type Transformer interface { + // Transform modifies data in the argument, e.g. adding labels to resources that can be labelled. + Transform(m resmap.ResMap) error +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/genargs.go b/vendor/sigs.k8s.io/kustomize/pkg/types/genargs.go new file mode 100644 index 000000000..bef093d35 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/genargs.go @@ -0,0 +1,64 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "strconv" + "strings" +) + +// GenArgs contains both generator args and options +type GenArgs struct { + args *GeneratorArgs + opts *GeneratorOptions +} + +// NewGenArgs returns a new object of GenArgs +func NewGenArgs(args *GeneratorArgs, opts *GeneratorOptions) *GenArgs { + return &GenArgs{ + args: args, + opts: opts, + } +} + +func (g *GenArgs) String() string { + if g == nil { + return "{nilGenArgs}" + } + return "{" + + strings.Join([]string{ + "nsfx:" + strconv.FormatBool(g.NeedsHashSuffix()), + "beh:" + g.Behavior().String()}, + ",") + + "}" +} + +// NeedHashSuffix returns true if the hash suffix is needed. +// It is needed when the two conditions are both met +// 1) GenArgs is not nil +// 2) DisableNameSuffixHash in GeneratorOptions is not set to true +func (g *GenArgs) NeedsHashSuffix() bool { + return g.args != nil && (g.opts == nil || g.opts.DisableNameSuffixHash == false) +} + +// Behavior returns Behavior field of GeneratorArgs +func (g *GenArgs) Behavior() GenerationBehavior { + if g.args == nil { + return BehaviorUnspecified + } + return NewGenerationBehavior(g.args.Behavior) +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/generationbehavior.go b/vendor/sigs.k8s.io/kustomize/pkg/types/generationbehavior.go new file mode 100644 index 000000000..67ba8a0b5 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/generationbehavior.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +// GenerationBehavior specifies generation behavior of configmaps, secrets and maybe other resources. +type GenerationBehavior int + +const ( + // BehaviorUnspecified is an Unspecified behavior; typically treated as a Create. + BehaviorUnspecified GenerationBehavior = iota + // BehaviorCreate makes a new resource. + BehaviorCreate + // BehaviorReplace replaces a resource. + BehaviorReplace + // BehaviorMerge attempts to merge a new resource with an existing resource. + BehaviorMerge +) + +// String converts a GenerationBehavior to a string. +func (b GenerationBehavior) String() string { + switch b { + case BehaviorReplace: + return "replace" + case BehaviorMerge: + return "merge" + case BehaviorCreate: + return "create" + default: + return "unspecified" + } +} + +// NewGenerationBehavior converts a string to a GenerationBehavior. +func NewGenerationBehavior(s string) GenerationBehavior { + switch s { + case "replace": + return BehaviorReplace + case "merge": + return BehaviorMerge + case "create": + return BehaviorCreate + default: + return BehaviorUnspecified + } +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go b/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go new file mode 100644 index 000000000..12d09820f --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/kustomization.go @@ -0,0 +1,250 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package types holds struct definitions that should find a better home. +package types + +import ( + "regexp" + + "sigs.k8s.io/kustomize/pkg/image" + "sigs.k8s.io/kustomize/pkg/patch" +) + +const ( + KustomizationVersion = "kustomize.config.k8s.io/v1beta1" + KustomizationKind = "Kustomization" +) + +// TypeMeta copies apimachinery/pkg/apis/meta/v1.TypeMeta +type TypeMeta struct { + // Kind copies apimachinery/pkg/apis/meta/v1.Typemeta.Kind + Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"` + + // APIVersion copies apimachinery/pkg/apis/meta/v1.Typemeta.APIVersion + APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"` +} + +// Kustomization holds the information needed to generate customized k8s api resources. +type Kustomization struct { + TypeMeta `json:",inline" yaml:",inline"` + + // + // Operators - what kustomize can do. + // + + // NamePrefix will prefix the names of all resources mentioned in the kustomization + // file including generated configmaps and secrets. + NamePrefix string `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"` + + // NameSuffix will suffix the names of all resources mentioned in the kustomization + // file including generated configmaps and secrets. + NameSuffix string `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"` + + // Namespace to add to all objects. + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + + // CommonLabels to add to all objects and selectors. + CommonLabels map[string]string `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` + + // CommonAnnotations to add to all objects. + CommonAnnotations map[string]string `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` + + // PatchesStrategicMerge specifies the relative path to a file + // containing a strategic merge patch. Format documented at + // https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md + // URLs and globs are not supported. + PatchesStrategicMerge []patch.StrategicMerge `json:"patchesStrategicMerge,omitempty" yaml:"patchesStrategicMerge,omitempty"` + + // JSONPatches is a list of JSONPatch for applying JSON patch. + // Format documented at https://tools.ietf.org/html/rfc6902 + // and http://jsonpatch.com + PatchesJson6902 []patch.Json6902 `json:"patchesJson6902,omitempty" yaml:"patchesJson6902,omitempty"` + + // Images is a list of (image name, new name, new tag or digest) + // for changing image names, tags or digests. This can also be achieved with a + // patch, but this operator is simpler to specify. + Images []image.Image `json:"images,omitempty" yaml:"images,omitempty"` + + // Vars allow things modified by kustomize to be injected into a + // container specification. A var is a name (e.g. FOO) associated + // with a field in a specific resource instance. The field must + // contain a value of type string, and defaults to the name field + // of the instance. Any appearance of "$(FOO)" in the container + // spec will be replaced at kustomize build time, after the final + // value of the specified field has been determined. + Vars []Var `json:"vars,omitempty" yaml:"vars,omitempty"` + + // + // Operands - what kustomize operates on. + // + + // Resources specifies relative paths to files holding YAML representations + // of kubernetes API objects. URLs and globs not supported. + Resources []string `json:"resources,omitempty" yaml:"resources,omitempty"` + + // Crds specifies relative paths to Custom Resource Definition files. + // This allows custom resources to be recognized as operands, making + // it possible to add them to the Resources list. + // CRDs themselves are not modified. + Crds []string `json:"crds,omitempty" yaml:"crds,omitempty"` + + // Bases are relative paths or github repository URLs specifying a + // directory containing a kustomization.yaml file. + // URL format: https://github.com/hashicorp/go-getter#url-format + Bases []string `json:"bases,omitempty" yaml:"bases,omitempty"` + + // + // Generators (operators that create operands) + // + + // ConfigMapGenerator is a list of configmaps to generate from + // local data (one configMap per list item). + // The resulting resource is a normal operand, subject to + // name prefixing, patching, etc. By default, the name of + // the map will have a suffix hash generated from its contents. + ConfigMapGenerator []ConfigMapArgs `json:"configMapGenerator,omitempty" yaml:"configMapGenerator,omitempty"` + + // SecretGenerator is a list of secrets to generate from + // local data (one secret per list item). + // The resulting resource is a normal operand, subject to + // name prefixing, patching, etc. By default, the name of + // the map will have a suffix hash generated from its contents. + SecretGenerator []SecretArgs `json:"secretGenerator,omitempty" yaml:"secretGenerator,omitempty"` + + // GeneratorOptions modify behavior of all ConfigMap and Secret generators. + GeneratorOptions *GeneratorOptions `json:"generatorOptions,omitempty" yaml:"generatorOptions,omitempty"` + + // Configurations is a list of transformer configuration files + Configurations []string `json:"configurations,omitempty" yaml:"configurations,omitempty"` +} + +// DealWithMissingFields fills the missing fields +func (k *Kustomization) DealWithMissingFields() []string { + var msgs []string + if k.APIVersion == "" { + k.APIVersion = KustomizationVersion + msgs = append(msgs, "Fixed the missing field by adding apiVersion: "+KustomizationVersion) + } + if k.Kind == "" { + k.Kind = KustomizationKind + msgs = append(msgs, "Fixed the missing field by adding kind: "+KustomizationKind) + } + return msgs +} + +func (k *Kustomization) EnforceFields() []string { + var errs []string + if k.APIVersion != "" && k.APIVersion != KustomizationVersion { + errs = append(errs, "apiVersion should be "+KustomizationVersion) + } + if k.Kind != "" && k.Kind != KustomizationKind { + errs = append(errs, "kind should be "+KustomizationKind) + } + return errs +} + +// DealWithDeprecatedFields should be called immediately after +// loading from storage. +func DealWithDeprecatedFields(data []byte) []byte { + deprecateFieldsMap := map[string]string{ + "patches:": "patchesStrategicMerge:", + "imageTags:": "images:", + } + for oldname, newname := range deprecateFieldsMap { + pattern := regexp.MustCompile(oldname) + data = pattern.ReplaceAll(data, []byte(newname)) + } + return data +} + +// GeneratorArgs contains arguments common to generators. +type GeneratorArgs struct { + // Namespace for the configmap, optional + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` + + // Name - actually the partial name - of the generated resource. + // The full name ends up being something like + // NamePrefix + this.Name + hash(content of generated resource). + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // Behavior of generated resource, must be one of: + // 'create': create a new one + // 'replace': replace the existing one + // 'merge': merge with the existing one + Behavior string `json:"behavior,omitempty" yaml:"behavior,omitempty"` + + // DataSources for the generator. + DataSources `json:",inline,omitempty" yaml:",inline,omitempty"` +} + +// ConfigMapArgs contains the metadata of how to generate a configmap. +type ConfigMapArgs struct { + // GeneratorArgs for the configmap. + GeneratorArgs `json:",inline,omitempty" yaml:",inline,omitempty"` +} + +// SecretArgs contains the metadata of how to generate a secret. +type SecretArgs struct { + // GeneratorArgs for the secret. + GeneratorArgs `json:",inline,omitempty" yaml:",inline,omitempty"` + + // Type of the secret. + // + // This is the same field as the secret type field in v1/Secret: + // It can be "Opaque" (default), or "kubernetes.io/tls". + // + // If type is "kubernetes.io/tls", then "literals" or "files" must have exactly two + // keys: "tls.key" and "tls.crt" + Type string `json:"type,omitempty" yaml:"type,omitempty"` +} + +// DataSources contains some generic sources for configmaps. +type DataSources struct { + // LiteralSources is a list of literal sources. + // Each literal source should be a key and literal value, + // e.g. `somekey=somevalue` + // It will be similar to kubectl create configmap|secret --from-literal + LiteralSources []string `json:"literals,omitempty" yaml:"literals,omitempty"` + + // FileSources is a list of file sources. + // Each file source can be specified using its file path, in which case file + // basename will be used as configmap key, or optionally with a key and file + // path, in which case the given key will be used. + // Specifying a directory will iterate each named file in the directory + // whose basename is a valid configmap key. + // It will be similar to kubectl create configmap|secret --from-file + FileSources []string `json:"files,omitempty" yaml:"files,omitempty"` + + // EnvSource format should be a path to a file to read lines of key=val + // pairs to create a configmap. + // i.e. a Docker .env file or a .ini file. + EnvSource string `json:"env,omitempty" yaml:"env,omitempty"` +} + +// GeneratorOptions modify behavior of all ConfigMap and Secret generators. +type GeneratorOptions struct { + // Labels to add to all generated resources. + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + + // Annotations to add to all generated resources. + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + + // DisableNameSuffixHash if true disables the default behavior of adding a + // suffix to the names of generated resources that is a hash of the + // resource contents. + DisableNameSuffixHash bool `json:"disableNameSuffixHash,omitempty" yaml:"disableNameSuffixHash,omitempty"` +} diff --git a/vendor/sigs.k8s.io/kustomize/pkg/types/var.go b/vendor/sigs.k8s.io/kustomize/pkg/types/var.go new file mode 100644 index 000000000..6a48032a0 --- /dev/null +++ b/vendor/sigs.k8s.io/kustomize/pkg/types/var.go @@ -0,0 +1,145 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "fmt" + "sort" + "strings" + + "sigs.k8s.io/kustomize/pkg/gvk" +) + +const defaultFieldPath = "metadata.name" + +// Var represents a variable whose value will be sourced +// from a field in a Kubernetes object. +type Var struct { + // Value of identifier name e.g. FOO used in container args, annotations + // Appears in pod template as $(FOO) + Name string `json:"name" yaml:"name"` + + // ObjRef must refer to a Kubernetes resource under the + // purview of this kustomization. ObjRef should use the + // raw name of the object (the name specified in its YAML, + // before addition of a namePrefix and a nameSuffix). + ObjRef Target `json:"objref" yaml:"objref"` + + // FieldRef refers to the field of the object referred to by + // ObjRef whose value will be extracted for use in + // replacing $(FOO). + // If unspecified, this defaults to fieldPath: $defaultFieldPath + FieldRef FieldSelector `json:"fieldref,omitempty" yaml:"fieldref,omitempty"` +} + +// Target refers to a kubernetes object by Group, Version, Kind and Name +// gvk.Gvk contains Group, Version and Kind +// APIVersion is added to keep the backward compatibility of using ObjectReference +// for Var.ObjRef +type Target struct { + APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"` + Name string `json:"name" yaml:"name"` +} + +// FieldSelector contains the fieldPath to an object field. +// This struct is added to keep the backward compatibility of using ObjectFieldSelector +// for Var.FieldRef +type FieldSelector struct { + FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"` +} + +// defaulting sets reference to field used by default. +func (v *Var) defaulting() { + if v.FieldRef.FieldPath == "" { + v.FieldRef.FieldPath = defaultFieldPath + } +} + +// VarSet is a slice of Vars where no var.Name is repeated. +type VarSet struct { + set []Var +} + +// Set returns a copy of the var set. +func (vs *VarSet) Set() []Var { + s := make([]Var, len(vs.set)) + copy(s, vs.set) + return s +} + +// MergeSet absorbs other vars with error on name collision. +func (vs *VarSet) MergeSet(incoming *VarSet) error { + return vs.MergeSlice(incoming.set) +} + +// MergeSlice absorbs other vars with error on name collision. +// Empty fields in incoming vars are defaulted. +func (vs *VarSet) MergeSlice(incoming []Var) error { + for _, v := range incoming { + if vs.Contains(v) { + return fmt.Errorf( + "var %s already encountered", v.Name) + } + v.defaulting() + vs.insert(v) + } + return nil +} + +func (vs *VarSet) insert(v Var) { + index := sort.Search( + len(vs.set), + func(i int) bool { return vs.set[i].Name > v.Name }) + // make room + vs.set = append(vs.set, Var{}) + // shift right at index. + // copy will not increase size of destination. + copy(vs.set[index+1:], vs.set[index:]) + vs.set[index] = v +} + +// Contains is true if the set has the other var. +func (vs *VarSet) Contains(other Var) bool { + return vs.Get(other.Name) != nil +} + +// Get returns the var with the given name, else nil. +func (vs *VarSet) Get(name string) *Var { + for _, v := range vs.set { + if v.Name == name { + return &v + } + } + return nil +} + +// GVK returns the Gvk object in Target +func (t *Target) GVK() gvk.Gvk { + if t.APIVersion == "" { + return t.Gvk + } + versions := strings.Split(t.APIVersion, "/") + if len(versions) == 2 { + t.Group = versions[0] + t.Version = versions[1] + } + if len(versions) == 1 { + t.Version = versions[0] + } + return t.Gvk +} diff --git a/vendor/vbom.ml/util/LICENSE b/vendor/vbom.ml/util/LICENSE new file mode 100644 index 000000000..5c695fb59 --- /dev/null +++ b/vendor/vbom.ml/util/LICENSE @@ -0,0 +1,17 @@ +The MIT License (MIT) +Copyright (c) 2015 Frits van Bommel +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/vbom.ml/util/sortorder/README.md b/vendor/vbom.ml/util/sortorder/README.md new file mode 100644 index 000000000..ed8da0e29 --- /dev/null +++ b/vendor/vbom.ml/util/sortorder/README.md @@ -0,0 +1,5 @@ +## sortorder [![GoDoc](https://godoc.org/vbom.ml/util/sortorder?status.svg)](https://godoc.org/vbom.ml/util/sortorder) + + import "vbom.ml/util/sortorder" + +Sort orders and comparison functions. diff --git a/vendor/vbom.ml/util/sortorder/doc.go b/vendor/vbom.ml/util/sortorder/doc.go new file mode 100644 index 000000000..61b37a937 --- /dev/null +++ b/vendor/vbom.ml/util/sortorder/doc.go @@ -0,0 +1,5 @@ +// Package sortorder implements sort orders and comparison functions. +// +// Currently, it only implements so-called "natural order", where integers +// embedded in strings are compared by value. +package sortorder // import "vbom.ml/util/sortorder" diff --git a/vendor/vbom.ml/util/sortorder/natsort.go b/vendor/vbom.ml/util/sortorder/natsort.go new file mode 100644 index 000000000..1af08c1bd --- /dev/null +++ b/vendor/vbom.ml/util/sortorder/natsort.go @@ -0,0 +1,76 @@ +package sortorder + +// Natural implements sort.Interface to sort strings in natural order. This +// means that e.g. "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +type Natural []string + +func (n Natural) Len() int { return len(n) } +func (n Natural) Swap(i, j int) { n[i], n[j] = n[j], n[i] } +func (n Natural) Less(i, j int) bool { return NaturalLess(n[i], n[j]) } + +func isdigit(b byte) bool { return '0' <= b && b <= '9' } + +// NaturalLess compares two strings using natural ordering. This means that e.g. +// "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +func NaturalLess(str1, str2 string) bool { + idx1, idx2 := 0, 0 + for idx1 < len(str1) && idx2 < len(str2) { + c1, c2 := str1[idx1], str2[idx2] + dig1, dig2 := isdigit(c1), isdigit(c2) + switch { + case dig1 != dig2: // Digits before other characters. + return dig1 // True if LHS is a digit, false if the RHS is one. + case !dig1: // && !dig2, because dig1 == dig2 + // UTF-8 compares bytewise-lexicographically, no need to decode + // codepoints. + if c1 != c2 { + return c1 < c2 + } + idx1++ + idx2++ + default: // Digits + // Eat zeros. + for ; idx1 < len(str1) && str1[idx1] == '0'; idx1++ { + } + for ; idx2 < len(str2) && str2[idx2] == '0'; idx2++ { + } + // Eat all digits. + nonZero1, nonZero2 := idx1, idx2 + for ; idx1 < len(str1) && isdigit(str1[idx1]); idx1++ { + } + for ; idx2 < len(str2) && isdigit(str2[idx2]); idx2++ { + } + // If lengths of numbers with non-zero prefix differ, the shorter + // one is less. + if len1, len2 := idx1-nonZero1, idx2-nonZero2; len1 != len2 { + return len1 < len2 + } + // If they're not equal, string comparison is correct. + if nr1, nr2 := str1[nonZero1:idx1], str2[nonZero2:idx2]; nr1 != nr2 { + return nr1 < nr2 + } + // Otherwise, the one with less zeros is less. + // Because everything up to the number is equal, comparing the index + // after the zeros is sufficient. + if nonZero1 != nonZero2 { + return nonZero1 < nonZero2 + } + } + // They're identical so far, so continue comparing. + } + // So far they are identical. At least one is ended. If the other continues, + // it sorts last. + return len(str1) < len(str2) +}