From 16f7aaab66f0bbbdab5f57fb90f111ed162d2392 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 9 May 2019 15:03:45 -0700 Subject: [PATCH 1/4] Update vendor --- {types => pkg}/apis/k3s.cattle.io/v1/types.go | 9 +- {types => pkg}/codegen/cleanup/main.go | 0 {types => pkg}/codegen/main.go | 0 trash.lock | 16 +- .../v1/zz_generated_daemon_set_controller.go | 441 ------------ ..._generated_daemon_set_lifecycle_adapter.go | 63 -- types/apis/apps/v1/zz_generated_deepcopy.go | 72 -- .../v1/zz_generated_deployment_controller.go | 441 ------------ ..._generated_deployment_lifecycle_adapter.go | 63 -- types/apis/apps/v1/zz_generated_k8s_client.go | 139 ---- types/apis/apps/v1/zz_generated_scheme.go | 40 -- types/apis/batch/v1/zz_generated_deepcopy.go | 39 -- .../batch/v1/zz_generated_job_controller.go | 441 ------------ .../v1/zz_generated_job_lifecycle_adapter.go | 63 -- .../apis/batch/v1/zz_generated_k8s_client.go | 119 ---- types/apis/batch/v1/zz_generated_scheme.go | 39 -- .../v1/zz_generated_config_map_controller.go | 441 ------------ ..._generated_config_map_lifecycle_adapter.go | 63 -- types/apis/core/v1/zz_generated_deepcopy.go | 204 ------ .../v1/zz_generated_endpoints_controller.go | 441 ------------ ...z_generated_endpoints_lifecycle_adapter.go | 63 -- types/apis/core/v1/zz_generated_k8s_client.go | 219 ------ .../core/v1/zz_generated_node_controller.go | 440 ------------ .../v1/zz_generated_node_lifecycle_adapter.go | 63 -- .../core/v1/zz_generated_pod_controller.go | 441 ------------ .../v1/zz_generated_pod_lifecycle_adapter.go | 63 -- types/apis/core/v1/zz_generated_scheme.go | 44 -- ...zz_generated_service_account_controller.go | 441 ------------ ...rated_service_account_lifecycle_adapter.go | 63 -- .../v1/zz_generated_service_controller.go | 441 ------------ .../zz_generated_service_lifecycle_adapter.go | 63 -- types/apis/k3s.cattle.io/v1/schema.go | 19 - .../v1/zz_generated_addon_controller.go | 440 ------------ .../zz_generated_addon_lifecycle_adapter.go | 62 -- .../k3s.cattle.io/v1/zz_generated_deepcopy.go | 268 -------- .../v1/zz_generated_helm_chart_controller.go | 440 ------------ ..._generated_helm_chart_lifecycle_adapter.go | 62 -- .../v1/zz_generated_k8s_client.go | 159 ----- ...zz_generated_listener_config_controller.go | 440 ------------ ...rated_listener_config_lifecycle_adapter.go | 62 -- .../k3s.cattle.io/v1/zz_generated_scheme.go | 44 -- ...nerated_cluster_role_binding_controller.go | 440 ------------ ..._cluster_role_binding_lifecycle_adapter.go | 63 -- .../v1/zz_generated_deepcopy.go | 39 -- .../v1/zz_generated_k8s_client.go | 119 ---- .../v1/zz_generated_scheme.go | 39 -- vendor.conf | 8 +- vendor/github.com/matryer/moq/.gitignore | 25 + vendor/github.com/matryer/moq/.travis.yml | 19 + vendor/github.com/matryer/moq/LICENSE | 21 + vendor/github.com/matryer/moq/README.md | 108 +++ .../github.com/matryer/moq/moq-logo-small.png | Bin 0 -> 32570 bytes vendor/github.com/matryer/moq/moq-logo.png | Bin 0 -> 29562 bytes vendor/github.com/matryer/moq/pkg/moq/moq.go | 379 +++++++++++ .../matryer/moq/pkg/moq/template.go | 107 +++ vendor/github.com/matryer/moq/preview.png | Bin 0 -> 743543 bytes .../rancher/dynamiclistener/LICENSE | 178 +++++ .../pkg => dynamiclistener}/cert/cert.go | 0 .../pkg => dynamiclistener}/cert/csr.go | 0 .../pkg => dynamiclistener}/cert/io.go | 0 .../pkg => dynamiclistener}/cert/pem.go | 0 .../github.com/rancher/dynamiclistener/go.mod | 14 + .../github.com/rancher/dynamiclistener/go.sum | 38 ++ .../{norman/pkg => }/dynamiclistener/read.go | 0 .../pkg => }/dynamiclistener/server.go | 11 +- .../{norman/pkg => }/dynamiclistener/types.go | 12 +- .../{norman => helm-controller}/.dockerignore | 5 +- .../rancher/helm-controller/.drone.yml | 221 ++++++ .../rancher/helm-controller/.gitignore | 6 + .../rancher/helm-controller/Dockerfile.dapper | 26 + .../Dockerfile.dapper479579668 | 26 + .../{norman => helm-controller}/LICENSE | 0 .../rancher/helm-controller/Makefile | 23 + .../rancher/helm-controller/README.md | 50 ++ .../github.com/rancher/helm-controller/go.mod | 17 + .../github.com/rancher/helm-controller/go.sum | 230 +++++++ .../pkg/apis/helm.cattle.io/v1/doc.go} | 19 +- .../pkg/apis/helm.cattle.io/v1/types.go | 30 + .../v1/zz_generated_deepcopy.go | 126 ++++ .../v1/zz_generated_list_types.go | 42 ++ .../v1/zz_generated_register.go | 56 ++ .../helm.cattle.io/zz_generated_register.go | 24 + .../clientset/versioned/clientset.go | 90 +++ .../pkg/generated/clientset/versioned/doc.go | 20 + .../clientset/versioned/scheme/doc.go | 20 + .../clientset/versioned/scheme/register.go | 56 ++ .../versioned/typed/helm.cattle.io/v1/doc.go | 20 + .../helm.cattle.io/v1/generated_expansion.go | 21 + .../v1/helm.cattle.io_client.go | 90 +++ .../typed/helm.cattle.io/v1/helmchart.go | 191 ++++++ .../controllers/helm.cattle.io/factory.go | 101 +++ .../controllers/helm.cattle.io/interface.go | 50 ++ .../helm.cattle.io/v1/helmchart.go | 242 +++++++ .../helm.cattle.io/v1/interface.go | 49 ++ .../informers/externalversions/factory.go | 180 +++++ .../informers/externalversions/generic.go | 62 ++ .../helm.cattle.io/interface.go | 46 ++ .../helm.cattle.io/v1/helmchart.go | 89 +++ .../helm.cattle.io/v1/interface.go | 45 ++ .../internalinterfaces/factory_interfaces.go | 40 ++ .../helm.cattle.io/v1/expansion_generated.go | 27 + .../listers/helm.cattle.io/v1/helmchart.go | 94 +++ .../helm-controller/pkg}/helm/controller.go | 129 ++-- .../rancher/helm-controller/vendor.conf | 5 + vendor/github.com/rancher/norman/.drone.yml | 9 - vendor/github.com/rancher/norman/.gitignore | 7 - .../rancher/norman/Dockerfile.dapper | 16 - .../rancher/norman/api/access/list.go | 87 --- .../rancher/norman/api/builtin/api_root.go | 81 --- .../rancher/norman/api/builtin/schema.go | 136 ---- .../rancher/norman/api/handler/create.go | 30 - .../rancher/norman/api/handler/delete.go | 27 - .../rancher/norman/api/handler/list.go | 43 -- .../rancher/norman/api/handler/query.go | 121 ---- .../rancher/norman/api/handler/update.go | 28 - .../rancher/norman/api/handler/validate.go | 59 -- .../github.com/rancher/norman/api/server.go | 277 -------- vendor/github.com/rancher/norman/api/types.go | 7 - .../github.com/rancher/norman/api/validate.go | 83 --- .../rancher/norman/api/writer/headers.go | 30 - .../rancher/norman/api/writer/html.go | 74 -- .../rancher/norman/api/writer/json.go | 234 ------- .../rancher/norman/authorization/all.go | 62 -- vendor/github.com/rancher/norman/build.go | 244 ------- .../norman/controller/cluster_check.go | 73 -- .../rancher/norman/controller/error.go | 10 - .../norman/controller/generic_controller.go | 361 ---------- .../norman/generator/client_template.go | 31 - .../norman/generator/controller_template.go | 448 ------------- .../rancher/norman/generator/default.go | 66 -- .../rancher/norman/generator/funcs.go | 50 -- .../rancher/norman/generator/generator.go | 533 --------------- .../norman/generator/k8s_client_template.go | 124 ---- .../norman/generator/lifecycle_template.go | 67 -- .../norman/generator/scheme_template.go | 42 -- .../rancher/norman/generator/type_template.go | 166 ----- .../rancher/norman/httperror/error.go | 114 ---- .../norman/httperror/handler/handler.go | 47 -- .../rancher/norman/lifecycle/object.go | 267 -------- .../norman/metrics/generic_controller.go | 58 -- vendor/github.com/rancher/norman/name/name.go | 27 - .../norman/objectclient/dynamic/content.go | 58 -- .../norman/objectclient/object_client.go | 311 --------- .../rancher/norman/parse/browser.go | 18 - .../rancher/norman/parse/builder/builder.go | 502 -------------- .../rancher/norman/parse/collection.go | 112 ---- .../github.com/rancher/norman/parse/parse.go | 310 --------- .../rancher/norman/parse/read_input.go | 45 -- .../rancher/norman/parse/subcontext.go | 50 -- .../rancher/norman/parse/validate.go | 45 -- .../norman/pkg/broadcast/broadcaster.go | 126 ---- .../rancher/norman/pkg/changeset/changeset.go | 74 -- .../norman/pkg/clientaccess/clientaccess.go | 277 -------- .../norman/pkg/objectset/desiredset.go | 55 -- .../pkg/objectset/desiredset_process.go | 279 -------- .../norman/pkg/objectset/injectors/marshal.go | 55 -- .../rancher/norman/pkg/objectset/template.go | 95 --- .../rancher/norman/pkg/proxy/proxy_server.go | 65 -- .../rancher/norman/restwatch/rest.go | 43 -- .../rancher/norman/signal/sigterm.go | 28 - .../rancher/norman/store/crd/init.go | 224 ------- .../rancher/norman/store/empty/empty_store.go | 36 - .../norman/store/proxy/error_wrapper.go | 52 -- .../rancher/norman/store/proxy/proxy_store.go | 506 -------------- .../rancher/norman/store/proxy/share_watch.go | 28 - .../norman/store/schema/schema_store.go | 140 ---- .../rancher/norman/store/wrapper/wrapper.go | 115 ---- vendor/github.com/rancher/norman/types.go | 62 -- .../rancher/norman/types/condition.go | 121 ---- .../rancher/norman/types/convert/convert.go | 278 -------- .../norman/types/convert/merge/merge.go | 156 ----- .../rancher/norman/types/convert/ref.go | 11 - .../rancher/norman/types/convert/transform.go | 45 -- .../norman/types/convert/value_set_string.go | 18 - .../norman/types/definition/definition.go | 45 -- .../rancher/norman/types/encoder.go | 32 - .../rancher/norman/types/factory/schemas.go | 23 - vendor/github.com/rancher/norman/types/id.go | 19 - .../github.com/rancher/norman/types/mapper.go | 178 ----- .../rancher/norman/types/mapper/access.go | 38 -- .../norman/types/mapper/annotation_field.go | 58 -- .../rancher/norman/types/mapper/apigroup.go | 35 - .../rancher/norman/types/mapper/base64.go | 63 -- .../rancher/norman/types/mapper/batchmove.go | 48 -- .../rancher/norman/types/mapper/changetype.go | 28 - .../rancher/norman/types/mapper/check.go | 15 - .../rancher/norman/types/mapper/condition.go | 28 - .../rancher/norman/types/mapper/copy.go | 44 -- .../norman/types/mapper/display_name.go | 29 - .../rancher/norman/types/mapper/drop.go | 31 - .../rancher/norman/types/mapper/embed.go | 106 --- .../rancher/norman/types/mapper/enum.go | 29 - .../norman/types/mapper/json_encode.go | 52 -- .../norman/types/mapper/label_field.go | 29 - .../rancher/norman/types/mapper/log.go | 7 - .../rancher/norman/types/mapper/metadata.go | 29 - .../rancher/norman/types/mapper/move.go | 89 --- .../rancher/norman/types/mapper/object.go | 30 - .../norman/types/mapper/pendingstatus.go | 35 - .../rancher/norman/types/mapper/read_only.go | 57 -- .../norman/types/mapper/rename_reference.go | 57 -- .../rancher/norman/types/mapper/required.go | 30 - .../rancher/norman/types/mapper/root.go | 31 - .../rancher/norman/types/mapper/scope.go | 38 -- .../rancher/norman/types/mapper/set_value.go | 71 -- .../norman/types/mapper/slice_merge.go | 48 -- .../norman/types/mapper/slice_to_map.go | 75 --- .../norman/types/mapper/union_embed.go | 69 -- .../norman/types/mapper/untyped_move.go | 38 -- .../rancher/norman/types/reflection.go | 507 -------------- .../rancher/norman/types/schema_funcs.go | 73 -- .../rancher/norman/types/schemas.go | 392 ----------- .../rancher/norman/types/server_types.go | 226 ------- .../github.com/rancher/norman/types/types.go | 168 ----- .../rancher/norman/types/values/values.go | 111 --- .../rancher/norman/urlbuilder/url.go | 273 -------- vendor/github.com/rancher/norman/vendor.conf | 9 - .../github.com/rancher/remotedialer/LICENSE | 178 +++++ .../github.com/rancher/remotedialer/README.md | 10 + .../{norman/pkg => }/remotedialer/client.go | 0 .../pkg => }/remotedialer/client_dialer.go | 0 .../pkg => }/remotedialer/connection.go | 0 .../{norman/pkg => }/remotedialer/dialer.go | 0 .../{norman/pkg => }/remotedialer/message.go | 0 .../{norman/pkg => }/remotedialer/peer.go | 0 .../{norman/pkg => }/remotedialer/server.go | 0 .../{norman/pkg => }/remotedialer/session.go | 0 .../pkg => }/remotedialer/session_manager.go | 0 .../pkg => }/remotedialer/session_windows.go | 0 .../{norman/pkg => }/remotedialer/types.go | 0 .../{norman/pkg => }/remotedialer/wsconn.go | 0 .../rancher/wrangler-api/.dockerignore | 3 + .../rancher/wrangler-api/.drone.yml | 221 ++++++ .../rancher/wrangler-api/.gitignore | 6 + .../rancher/wrangler-api/.golangci.json | 19 + .../rancher/wrangler-api/Dockerfile.dapper | 28 + .../github.com/rancher/wrangler-api/LICENSE | 177 +++++ .../rancher/{norman => wrangler-api}/Makefile | 2 +- .../{norman => wrangler-api}/README.md | 11 +- vendor/github.com/rancher/wrangler-api/go.mod | 22 + vendor/github.com/rancher/wrangler-api/go.sum | 173 +++++ .../pkg/generated/controllers/apps/factory.go | 101 +++ .../generated/controllers/apps/interface.go | 50 ++ .../controllers/apps/v1/daemonset.go | 242 +++++++ .../controllers/apps/v1/deployment.go | 242 +++++++ .../controllers/apps/v1/interface.go | 53 ++ .../generated/controllers/batch/factory.go | 101 +++ .../generated/controllers/batch/interface.go | 50 ++ .../controllers/batch/v1/interface.go | 49 ++ .../pkg/generated/controllers/batch/v1/job.go | 242 +++++++ .../pkg/generated/controllers/core/factory.go | 101 +++ .../generated/controllers/core/interface.go | 50 ++ .../controllers/core/v1/configmap.go | 238 +++++++ .../controllers/core/v1/endpoints.go | 238 +++++++ .../controllers/core/v1/interface.go | 81 +++ .../controllers/core/v1/namespace.go | 242 +++++++ .../pkg/generated/controllers/core/v1/node.go | 242 +++++++ .../core/v1/persistentvolumeclaim.go | 242 +++++++ .../pkg/generated/controllers/core/v1/pod.go | 242 +++++++ .../generated/controllers/core/v1/secret.go | 238 +++++++ .../generated/controllers/core/v1/service.go | 242 +++++++ .../controllers/core/v1/serviceaccount.go | 238 +++++++ .../pkg/generated/controllers/rbac/factory.go | 101 +++ .../generated/controllers/rbac/interface.go | 50 ++ .../controllers/rbac/v1/clusterrole.go | 238 +++++++ .../controllers/rbac/v1/clusterrolebinding.go | 238 +++++++ .../controllers/rbac/v1/interface.go | 61 ++ .../pkg/generated/controllers/rbac/v1/role.go | 238 +++++++ .../controllers/rbac/v1/rolebinding.go | 238 +++++++ vendor/github.com/rancher/wrangler/LICENSE | 178 +++++ vendor/github.com/rancher/wrangler/README.md | 77 +++ vendor/github.com/rancher/wrangler/go.mod | 38 ++ vendor/github.com/rancher/wrangler/go.sum | 316 +++++++++ .../rancher/wrangler/pkg/apply/apply.go | 170 +++++ .../wrangler/pkg/apply/client_factory.go | 22 + .../rancher/wrangler/pkg/apply/desiredset.go | 115 ++++ .../pkg/apply}/desiredset_apply.go | 130 ++-- .../pkg/apply}/desiredset_compare.go | 64 +- .../wrangler/pkg/apply/desiredset_crud.go | 66 ++ .../wrangler/pkg/apply/desiredset_process.go | 238 +++++++ .../pkg/apply}/injectors/registry.go | 0 .../pkg}/cleanup/cleanup.go | 0 .../pkg}/condition/condition.go | 258 +++---- .../wrangler/pkg/controller-gen/OWNERS | 10 + .../wrangler/pkg/controller-gen/README.md | 4 + .../wrangler/pkg/controller-gen/args/args.go | 28 + .../pkg/controller-gen/args/groupversion.go | 60 ++ .../generators/client_generator.go | 243 +++++++ .../controller-gen/generators/factory_go.go | 132 ++++ .../generators/group_interface_go.go | 106 +++ .../generators/group_version_interface_go.go | 115 ++++ .../controller-gen/generators/list_type_go.go | 70 ++ .../pkg/controller-gen/generators/pkg.go | 22 + .../generators/register_group_go.go | 34 + .../generators/register_group_version_go.go | 110 +++ .../pkg/controller-gen/generators/type_go.go | 298 +++++++++ .../pkg/controller-gen/generators/util.go | 30 + .../wrangler/pkg/controller-gen/main.go | 299 +++++++++ .../rancher/wrangler/pkg/crd/init.go | 253 +++++++ .../rancher/wrangler/pkg/generic/change.go | 40 ++ .../wrangler/pkg/generic/controller.go | 194 ++++++ .../wrangler/pkg/generic/controllerfactory.go | 124 ++++ .../rancher/wrangler/pkg/generic/handlers.go | 72 ++ .../rancher/wrangler/pkg/generic/remove.go | 119 ++++ .../{norman => wrangler}/pkg/kv/split.go | 6 +- .../{norman => wrangler/pkg}/leader/leader.go | 18 +- .../rancher/wrangler/pkg/merr/error.go | 38 ++ .../rancher/wrangler/pkg/name/name.go | 59 ++ .../pkg/objectset/objectset.go | 89 ++- .../wrangler/pkg/relatedresource/changeset.go | 63 ++ .../pkg/resolvehome/main.go} | 27 +- .../rancher/wrangler/pkg/signals/signal.go | 44 ++ .../wrangler/pkg/signals/signal_posix.go | 26 + .../wrangler/pkg/signals/signal_windows.go} | 11 +- .../types => wrangler/pkg}/slice/contains.go | 0 .../starter.go => wrangler/pkg/start/all.go} | 4 +- vendor/k8s.io/client-go/discovery/fake/BUILD | 46 ++ .../client-go/discovery/fake/discovery.go | 160 +++++ vendor/k8s.io/code-generator/BUILD | 29 + vendor/k8s.io/code-generator/CONTRIBUTING.md | 7 + vendor/k8s.io/code-generator/LICENSE | 202 ++++++ vendor/k8s.io/code-generator/OWNERS | 13 + vendor/k8s.io/code-generator/README.md | 24 + .../k8s.io/code-generator/SECURITY_CONTACTS | 17 + .../code-generator/cmd/client-gen/BUILD | 46 ++ .../code-generator/cmd/client-gen/OWNERS | 10 + .../code-generator/cmd/client-gen/README.md | 4 + .../code-generator/cmd/client-gen/args/BUILD | 47 ++ .../cmd/client-gen/args/args.go | 120 ++++ .../cmd/client-gen/args/gvpackages.go | 183 +++++ .../cmd/client-gen/args/gvtype.go | 110 +++ .../cmd/client-gen/generators/BUILD | 51 ++ .../client-gen/generators/client_generator.go | 403 +++++++++++ .../cmd/client-gen/generators/fake/BUILD | 41 ++ .../generators/fake/fake_client_generator.go | 130 ++++ .../fake/generator_fake_for_clientset.go | 169 +++++ .../fake/generator_fake_for_group.go | 130 ++++ .../fake/generator_fake_for_type.go | 479 +++++++++++++ .../generators/generator_for_clientset.go | 178 +++++ .../generators/generator_for_expansion.go | 54 ++ .../generators/generator_for_group.go | 247 +++++++ .../generators/generator_for_type.go | 599 +++++++++++++++++ .../cmd/client-gen/generators/scheme/BUILD | 33 + .../generators/scheme/generator_for_scheme.go | 186 +++++ .../cmd/client-gen/generators/util/BUILD | 34 + .../cmd/client-gen/generators/util/tags.go | 341 ++++++++++ .../cmd/client-gen/path}/BUILD | 8 +- .../cmd/client-gen/path/path.go | 31 + .../code-generator/cmd/client-gen/types/BUILD | 37 + .../cmd/client-gen/types/helpers.go | 121 ++++ .../cmd/client-gen/types/types.go | 75 +++ .../code-generator/cmd/deepcopy-gen/BUILD | 43 ++ .../cmd/deepcopy-gen/args/BUILD | 28 + .../cmd/deepcopy-gen/args/args.go | 54 ++ .../code-generator/cmd/informer-gen/BUILD | 44 ++ .../cmd/informer-gen/args/BUILD | 28 + .../cmd/informer-gen/args/args.go | 77 +++ .../cmd/informer-gen/generators/BUILD | 47 ++ .../cmd/informer-gen/generators/factory.go | 258 +++++++ .../generators/factoryinterface.go | 90 +++ .../cmd/informer-gen/generators/generic.go | 184 +++++ .../informer-gen/generators/groupinterface.go | 118 ++++ .../cmd/informer-gen/generators/informer.go | 186 +++++ .../cmd/informer-gen/generators/packages.go | 352 ++++++++++ .../cmd/informer-gen/generators/tags.go | 33 + .../cmd/informer-gen/generators/types.go | 42 ++ .../generators/versioninterface.go | 109 +++ .../cmd/lister-gen/.import-restrictions | 1 + .../code-generator/cmd/lister-gen/BUILD | 44 ++ .../code-generator/cmd/lister-gen/args/BUILD | 28 + .../cmd/lister-gen/args/args.go | 56 ++ .../cmd/lister-gen/generators/BUILD | 39 ++ .../cmd/lister-gen/generators/expansion.go | 67 ++ .../cmd/lister-gen/generators/lister.go | 371 ++++++++++ .../cmd/lister-gen/generators/tags.go | 33 + .../k8s.io/code-generator/code-of-conduct.md | 3 + .../k8s.io/code-generator/generate-groups.sh | 92 +++ .../generate-internal-groups.sh | 110 +++ vendor/k8s.io/code-generator/pkg/namer/BUILD | 27 + .../code-generator/pkg/namer/tag-override.go | 58 ++ vendor/k8s.io/code-generator/pkg/util/BUILD | 23 + .../k8s.io/code-generator/pkg/util/build.go | 61 ++ vendor/k8s.io/kubernetes/staging/BUILD | 17 + vendor/k8s.io/kubernetes/staging/OWNERS | 16 + vendor/k8s.io/kubernetes/staging/README.md | 105 +++ .../kubernetes/staging/repos_generated.bzl | 41 ++ vendor/k8s.io/kubernetes/staging/src/BUILD | 43 ++ .../staging/src/k8s.io/client-go/BUILD | 94 +++ .../src/k8s.io/client-go/CONTRIBUTING.md | 7 + .../staging/src/k8s.io/client-go/INSTALL.md | 162 +++++ .../staging/src/k8s.io/client-go/LICENSE | 202 ++++++ .../staging/src/k8s.io/client-go/OWNERS | 19 + .../src/k8s.io/client-go/SECURITY_CONTACTS | 17 + .../src/k8s.io/client-go/code-of-conduct.md | 3 + .../src/k8s.io/client-go/kubernetes/BUILD | 108 +++ .../k8s.io/client-go/kubernetes/clientset.go | 482 +++++++++++++ .../src/k8s.io/client-go/kubernetes/doc.go | 20 + .../src/k8s.io/client-go/kubernetes/import.go | 19 + .../k8s.io/client-go/tools/clientcmd/BUILD | 78 +++ .../client-go/tools/clientcmd/auth_loaders.go | 111 +++ .../tools/clientcmd/client_config.go | 569 ++++++++++++++++ .../client-go/tools/clientcmd/config.go | 490 ++++++++++++++ .../k8s.io/client-go/tools/clientcmd/doc.go | 37 + .../k8s.io/client-go/tools/clientcmd/flag.go | 49 ++ .../client-go/tools/clientcmd/helpers.go | 35 + .../client-go/tools/clientcmd/loader.go | 633 ++++++++++++++++++ .../tools/clientcmd/merged_client_builder.go | 173 +++++ .../client-go/tools/clientcmd/overrides.go | 247 +++++++ .../client-go/tools/clientcmd/validation.go | 298 +++++++++ 409 files changed, 24151 insertions(+), 20484 deletions(-) rename {types => pkg}/apis/k3s.cattle.io/v1/types.go (91%) rename {types => pkg}/codegen/cleanup/main.go (100%) rename {types => pkg}/codegen/main.go (100%) delete mode 100644 types/apis/apps/v1/zz_generated_daemon_set_controller.go delete mode 100644 types/apis/apps/v1/zz_generated_daemon_set_lifecycle_adapter.go delete mode 100644 types/apis/apps/v1/zz_generated_deepcopy.go delete mode 100644 types/apis/apps/v1/zz_generated_deployment_controller.go delete mode 100644 types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go delete mode 100644 types/apis/apps/v1/zz_generated_k8s_client.go delete mode 100644 types/apis/apps/v1/zz_generated_scheme.go delete mode 100644 types/apis/batch/v1/zz_generated_deepcopy.go delete mode 100644 types/apis/batch/v1/zz_generated_job_controller.go delete mode 100644 types/apis/batch/v1/zz_generated_job_lifecycle_adapter.go delete mode 100644 types/apis/batch/v1/zz_generated_k8s_client.go delete mode 100644 types/apis/batch/v1/zz_generated_scheme.go delete mode 100644 types/apis/core/v1/zz_generated_config_map_controller.go delete mode 100644 types/apis/core/v1/zz_generated_config_map_lifecycle_adapter.go delete mode 100644 types/apis/core/v1/zz_generated_deepcopy.go delete mode 100644 types/apis/core/v1/zz_generated_endpoints_controller.go delete mode 100644 types/apis/core/v1/zz_generated_endpoints_lifecycle_adapter.go delete mode 100644 types/apis/core/v1/zz_generated_k8s_client.go delete mode 100644 types/apis/core/v1/zz_generated_node_controller.go delete mode 100644 types/apis/core/v1/zz_generated_node_lifecycle_adapter.go delete mode 100644 types/apis/core/v1/zz_generated_pod_controller.go delete mode 100644 types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go delete mode 100644 types/apis/core/v1/zz_generated_scheme.go delete mode 100644 types/apis/core/v1/zz_generated_service_account_controller.go delete mode 100644 types/apis/core/v1/zz_generated_service_account_lifecycle_adapter.go delete mode 100644 types/apis/core/v1/zz_generated_service_controller.go delete mode 100644 types/apis/core/v1/zz_generated_service_lifecycle_adapter.go delete mode 100644 types/apis/k3s.cattle.io/v1/schema.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_addon_controller.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_addon_lifecycle_adapter.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_controller.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_lifecycle_adapter.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_k8s_client.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_listener_config_controller.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_listener_config_lifecycle_adapter.go delete mode 100644 types/apis/k3s.cattle.io/v1/zz_generated_scheme.go delete mode 100644 types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_controller.go delete mode 100644 types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_lifecycle_adapter.go delete mode 100644 types/apis/rbac.authorization.k8s.io/v1/zz_generated_deepcopy.go delete mode 100644 types/apis/rbac.authorization.k8s.io/v1/zz_generated_k8s_client.go delete mode 100644 types/apis/rbac.authorization.k8s.io/v1/zz_generated_scheme.go create mode 100644 vendor/github.com/matryer/moq/.gitignore create mode 100644 vendor/github.com/matryer/moq/.travis.yml create mode 100644 vendor/github.com/matryer/moq/LICENSE create mode 100644 vendor/github.com/matryer/moq/README.md create mode 100644 vendor/github.com/matryer/moq/moq-logo-small.png create mode 100644 vendor/github.com/matryer/moq/moq-logo.png create mode 100644 vendor/github.com/matryer/moq/pkg/moq/moq.go create mode 100644 vendor/github.com/matryer/moq/pkg/moq/template.go create mode 100644 vendor/github.com/matryer/moq/preview.png create mode 100644 vendor/github.com/rancher/dynamiclistener/LICENSE rename vendor/github.com/rancher/{norman/pkg => dynamiclistener}/cert/cert.go (100%) rename vendor/github.com/rancher/{norman/pkg => dynamiclistener}/cert/csr.go (100%) rename vendor/github.com/rancher/{norman/pkg => dynamiclistener}/cert/io.go (100%) rename vendor/github.com/rancher/{norman/pkg => dynamiclistener}/cert/pem.go (100%) create mode 100644 vendor/github.com/rancher/dynamiclistener/go.mod create mode 100644 vendor/github.com/rancher/dynamiclistener/go.sum rename vendor/github.com/rancher/{norman/pkg => }/dynamiclistener/read.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/dynamiclistener/server.go (98%) rename vendor/github.com/rancher/{norman/pkg => }/dynamiclistener/types.go (86%) rename vendor/github.com/rancher/{norman => helm-controller}/.dockerignore (69%) create mode 100644 vendor/github.com/rancher/helm-controller/.drone.yml create mode 100644 vendor/github.com/rancher/helm-controller/.gitignore create mode 100644 vendor/github.com/rancher/helm-controller/Dockerfile.dapper create mode 100644 vendor/github.com/rancher/helm-controller/Dockerfile.dapper479579668 rename vendor/github.com/rancher/{norman => helm-controller}/LICENSE (100%) create mode 100644 vendor/github.com/rancher/helm-controller/Makefile create mode 100644 vendor/github.com/rancher/helm-controller/README.md create mode 100644 vendor/github.com/rancher/helm-controller/go.mod create mode 100644 vendor/github.com/rancher/helm-controller/go.sum rename vendor/{k8s.io/kubernetes/pkg/util/maps/string.go => github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/doc.go} (66%) create mode 100644 vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/types.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_deepcopy.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_list_types.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_register.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/zz_generated_register.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/clientset.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/doc.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/doc.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/register.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/doc.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/generated_expansion.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helm.cattle.io_client.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helmchart.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/factory.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/interface.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/helmchart.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/interface.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/factory.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/generic.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/interface.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/helmchart.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/interface.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/expansion_generated.go create mode 100644 vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/helmchart.go rename {pkg => vendor/github.com/rancher/helm-controller/pkg}/helm/controller.go (66%) create mode 100644 vendor/github.com/rancher/helm-controller/vendor.conf delete mode 100644 vendor/github.com/rancher/norman/.drone.yml delete mode 100644 vendor/github.com/rancher/norman/.gitignore delete mode 100644 vendor/github.com/rancher/norman/Dockerfile.dapper delete mode 100644 vendor/github.com/rancher/norman/api/access/list.go delete mode 100644 vendor/github.com/rancher/norman/api/builtin/api_root.go delete mode 100644 vendor/github.com/rancher/norman/api/builtin/schema.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/create.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/delete.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/list.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/query.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/update.go delete mode 100644 vendor/github.com/rancher/norman/api/handler/validate.go delete mode 100644 vendor/github.com/rancher/norman/api/server.go delete mode 100644 vendor/github.com/rancher/norman/api/types.go delete mode 100644 vendor/github.com/rancher/norman/api/validate.go delete mode 100644 vendor/github.com/rancher/norman/api/writer/headers.go delete mode 100644 vendor/github.com/rancher/norman/api/writer/html.go delete mode 100644 vendor/github.com/rancher/norman/api/writer/json.go delete mode 100644 vendor/github.com/rancher/norman/authorization/all.go delete mode 100644 vendor/github.com/rancher/norman/build.go delete mode 100644 vendor/github.com/rancher/norman/controller/cluster_check.go delete mode 100644 vendor/github.com/rancher/norman/controller/error.go delete mode 100644 vendor/github.com/rancher/norman/controller/generic_controller.go delete mode 100644 vendor/github.com/rancher/norman/generator/client_template.go delete mode 100644 vendor/github.com/rancher/norman/generator/controller_template.go delete mode 100644 vendor/github.com/rancher/norman/generator/default.go delete mode 100644 vendor/github.com/rancher/norman/generator/funcs.go delete mode 100644 vendor/github.com/rancher/norman/generator/generator.go delete mode 100644 vendor/github.com/rancher/norman/generator/k8s_client_template.go delete mode 100644 vendor/github.com/rancher/norman/generator/lifecycle_template.go delete mode 100644 vendor/github.com/rancher/norman/generator/scheme_template.go delete mode 100644 vendor/github.com/rancher/norman/generator/type_template.go delete mode 100644 vendor/github.com/rancher/norman/httperror/error.go delete mode 100644 vendor/github.com/rancher/norman/httperror/handler/handler.go delete mode 100644 vendor/github.com/rancher/norman/lifecycle/object.go delete mode 100644 vendor/github.com/rancher/norman/metrics/generic_controller.go delete mode 100644 vendor/github.com/rancher/norman/name/name.go delete mode 100644 vendor/github.com/rancher/norman/objectclient/dynamic/content.go delete mode 100644 vendor/github.com/rancher/norman/objectclient/object_client.go delete mode 100644 vendor/github.com/rancher/norman/parse/browser.go delete mode 100644 vendor/github.com/rancher/norman/parse/builder/builder.go delete mode 100644 vendor/github.com/rancher/norman/parse/collection.go delete mode 100644 vendor/github.com/rancher/norman/parse/parse.go delete mode 100644 vendor/github.com/rancher/norman/parse/read_input.go delete mode 100644 vendor/github.com/rancher/norman/parse/subcontext.go delete mode 100644 vendor/github.com/rancher/norman/parse/validate.go delete mode 100644 vendor/github.com/rancher/norman/pkg/broadcast/broadcaster.go delete mode 100644 vendor/github.com/rancher/norman/pkg/changeset/changeset.go delete mode 100644 vendor/github.com/rancher/norman/pkg/clientaccess/clientaccess.go delete mode 100644 vendor/github.com/rancher/norman/pkg/objectset/desiredset.go delete mode 100644 vendor/github.com/rancher/norman/pkg/objectset/desiredset_process.go delete mode 100644 vendor/github.com/rancher/norman/pkg/objectset/injectors/marshal.go delete mode 100644 vendor/github.com/rancher/norman/pkg/objectset/template.go delete mode 100644 vendor/github.com/rancher/norman/pkg/proxy/proxy_server.go delete mode 100644 vendor/github.com/rancher/norman/restwatch/rest.go delete mode 100644 vendor/github.com/rancher/norman/signal/sigterm.go delete mode 100644 vendor/github.com/rancher/norman/store/crd/init.go delete mode 100644 vendor/github.com/rancher/norman/store/empty/empty_store.go delete mode 100644 vendor/github.com/rancher/norman/store/proxy/error_wrapper.go delete mode 100644 vendor/github.com/rancher/norman/store/proxy/proxy_store.go delete mode 100644 vendor/github.com/rancher/norman/store/proxy/share_watch.go delete mode 100644 vendor/github.com/rancher/norman/store/schema/schema_store.go delete mode 100644 vendor/github.com/rancher/norman/store/wrapper/wrapper.go delete mode 100644 vendor/github.com/rancher/norman/types.go delete mode 100644 vendor/github.com/rancher/norman/types/condition.go delete mode 100644 vendor/github.com/rancher/norman/types/convert/convert.go delete mode 100644 vendor/github.com/rancher/norman/types/convert/merge/merge.go delete mode 100644 vendor/github.com/rancher/norman/types/convert/ref.go delete mode 100644 vendor/github.com/rancher/norman/types/convert/transform.go delete mode 100644 vendor/github.com/rancher/norman/types/convert/value_set_string.go delete mode 100644 vendor/github.com/rancher/norman/types/definition/definition.go delete mode 100644 vendor/github.com/rancher/norman/types/encoder.go delete mode 100644 vendor/github.com/rancher/norman/types/factory/schemas.go delete mode 100644 vendor/github.com/rancher/norman/types/id.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/access.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/annotation_field.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/apigroup.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/base64.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/batchmove.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/changetype.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/check.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/condition.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/copy.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/display_name.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/drop.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/embed.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/enum.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/json_encode.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/label_field.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/log.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/metadata.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/move.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/object.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/pendingstatus.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/read_only.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/rename_reference.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/required.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/root.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/scope.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/set_value.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/slice_merge.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/slice_to_map.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/union_embed.go delete mode 100644 vendor/github.com/rancher/norman/types/mapper/untyped_move.go delete mode 100644 vendor/github.com/rancher/norman/types/reflection.go delete mode 100644 vendor/github.com/rancher/norman/types/schema_funcs.go delete mode 100644 vendor/github.com/rancher/norman/types/schemas.go delete mode 100644 vendor/github.com/rancher/norman/types/server_types.go delete mode 100644 vendor/github.com/rancher/norman/types/types.go delete mode 100644 vendor/github.com/rancher/norman/types/values/values.go delete mode 100644 vendor/github.com/rancher/norman/urlbuilder/url.go delete mode 100644 vendor/github.com/rancher/norman/vendor.conf create mode 100644 vendor/github.com/rancher/remotedialer/LICENSE create mode 100644 vendor/github.com/rancher/remotedialer/README.md rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/client.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/client_dialer.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/connection.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/dialer.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/message.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/peer.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/server.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/session.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/session_manager.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/session_windows.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/types.go (100%) rename vendor/github.com/rancher/{norman/pkg => }/remotedialer/wsconn.go (100%) create mode 100644 vendor/github.com/rancher/wrangler-api/.dockerignore create mode 100644 vendor/github.com/rancher/wrangler-api/.drone.yml create mode 100644 vendor/github.com/rancher/wrangler-api/.gitignore create mode 100644 vendor/github.com/rancher/wrangler-api/.golangci.json create mode 100644 vendor/github.com/rancher/wrangler-api/Dockerfile.dapper create mode 100644 vendor/github.com/rancher/wrangler-api/LICENSE rename vendor/github.com/rancher/{norman => wrangler-api}/Makefile (92%) rename vendor/github.com/rancher/{norman => wrangler-api}/README.md (65%) create mode 100644 vendor/github.com/rancher/wrangler-api/go.mod create mode 100644 vendor/github.com/rancher/wrangler-api/go.sum create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/factory.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/daemonset.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/deployment.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/factory.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/job.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/factory.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/configmap.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/endpoints.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/namespace.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/node.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/persistentvolumeclaim.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/pod.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/secret.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/service.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/serviceaccount.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/factory.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrole.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrolebinding.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/interface.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/role.go create mode 100644 vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/rolebinding.go create mode 100644 vendor/github.com/rancher/wrangler/LICENSE create mode 100644 vendor/github.com/rancher/wrangler/README.md create mode 100644 vendor/github.com/rancher/wrangler/go.mod create mode 100644 vendor/github.com/rancher/wrangler/go.sum create mode 100644 vendor/github.com/rancher/wrangler/pkg/apply/apply.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/apply/client_factory.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go rename vendor/github.com/rancher/{norman/pkg/objectset => wrangler/pkg/apply}/desiredset_apply.go (59%) rename vendor/github.com/rancher/{norman/pkg/objectset => wrangler/pkg/apply}/desiredset_compare.go (78%) create mode 100644 vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go rename vendor/github.com/rancher/{norman/pkg/objectset => wrangler/pkg/apply}/injectors/registry.go (100%) rename vendor/github.com/rancher/{norman/generator => wrangler/pkg}/cleanup/cleanup.go (100%) rename vendor/github.com/rancher/{norman => wrangler/pkg}/condition/condition.go (55%) create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/OWNERS create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/README.md create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/args/args.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/args/groupversion.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/client_generator.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/factory_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_interface_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_version_interface_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/list_type_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/pkg.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_version_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/util.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/crd/init.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/generic/change.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/generic/controller.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/generic/controllerfactory.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/generic/handlers.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/generic/remove.go rename vendor/github.com/rancher/{norman => wrangler}/pkg/kv/split.go (75%) rename vendor/github.com/rancher/{norman => wrangler/pkg}/leader/leader.go (67%) create mode 100644 vendor/github.com/rancher/wrangler/pkg/merr/error.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/name/name.go rename vendor/github.com/rancher/{norman => wrangler}/pkg/objectset/objectset.go (53%) create mode 100644 vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go rename vendor/github.com/rancher/{norman/pkg/resolvehome/home.go => wrangler/pkg/resolvehome/main.go} (51%) create mode 100644 vendor/github.com/rancher/wrangler/pkg/signals/signal.go create mode 100644 vendor/github.com/rancher/wrangler/pkg/signals/signal_posix.go rename vendor/{k8s.io/kubernetes/pkg/util/maps/doc.go => github.com/rancher/wrangler/pkg/signals/signal_windows.go} (81%) rename vendor/github.com/rancher/{norman/types => wrangler/pkg}/slice/contains.go (100%) rename vendor/github.com/rancher/{norman/controller/starter.go => wrangler/pkg/start/all.go} (87%) create mode 100644 vendor/k8s.io/client-go/discovery/fake/BUILD create mode 100644 vendor/k8s.io/client-go/discovery/fake/discovery.go create mode 100644 vendor/k8s.io/code-generator/BUILD create mode 100644 vendor/k8s.io/code-generator/CONTRIBUTING.md create mode 100644 vendor/k8s.io/code-generator/LICENSE create mode 100644 vendor/k8s.io/code-generator/OWNERS create mode 100644 vendor/k8s.io/code-generator/README.md create mode 100644 vendor/k8s.io/code-generator/SECURITY_CONTACTS create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/OWNERS create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/README.md create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/args/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/args/args.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/util/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go rename vendor/k8s.io/{kubernetes/pkg/util/maps => code-generator/cmd/client-gen/path}/BUILD (69%) create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/path/path.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/types/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go create mode 100644 vendor/k8s.io/code-generator/cmd/client-gen/types/types.go create mode 100644 vendor/k8s.io/code-generator/cmd/deepcopy-gen/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/args/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go create mode 100644 vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/args/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/generators/BUILD create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go create mode 100644 vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go create mode 100644 vendor/k8s.io/code-generator/code-of-conduct.md create mode 100755 vendor/k8s.io/code-generator/generate-groups.sh create mode 100755 vendor/k8s.io/code-generator/generate-internal-groups.sh create mode 100644 vendor/k8s.io/code-generator/pkg/namer/BUILD create mode 100644 vendor/k8s.io/code-generator/pkg/namer/tag-override.go create mode 100644 vendor/k8s.io/code-generator/pkg/util/BUILD create mode 100644 vendor/k8s.io/code-generator/pkg/util/build.go create mode 100644 vendor/k8s.io/kubernetes/staging/BUILD create mode 100644 vendor/k8s.io/kubernetes/staging/OWNERS create mode 100644 vendor/k8s.io/kubernetes/staging/README.md create mode 100644 vendor/k8s.io/kubernetes/staging/repos_generated.bzl create mode 100644 vendor/k8s.io/kubernetes/staging/src/BUILD create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/BUILD create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/CONTRIBUTING.md create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/INSTALL.md create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/LICENSE create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/code-of-conduct.md create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/import.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/doc.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/flag.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/helpers.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go create mode 100644 vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/validation.go diff --git a/types/apis/k3s.cattle.io/v1/types.go b/pkg/apis/k3s.cattle.io/v1/types.go similarity index 91% rename from types/apis/k3s.cattle.io/v1/types.go rename to pkg/apis/k3s.cattle.io/v1/types.go index 1a900b1ffd..ee6e5cc6bb 100644 --- a/types/apis/k3s.cattle.io/v1/types.go +++ b/pkg/apis/k3s.cattle.io/v1/types.go @@ -1,16 +1,13 @@ package v1 import ( - "github.com/rancher/norman/pkg/dynamiclistener" - "github.com/rancher/norman/types" + "github.com/rancher/dynamiclistener" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" ) type ListenerConfig struct { - types.Namespaced - metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -18,8 +15,6 @@ type ListenerConfig struct { } type Addon struct { - types.Namespaced - metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -37,8 +32,6 @@ type AddonStatus struct { } type HelmChart struct { - types.Namespaced - metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/types/codegen/cleanup/main.go b/pkg/codegen/cleanup/main.go similarity index 100% rename from types/codegen/cleanup/main.go rename to pkg/codegen/cleanup/main.go diff --git a/types/codegen/main.go b/pkg/codegen/main.go similarity index 100% rename from types/codegen/main.go rename to pkg/codegen/main.go diff --git a/trash.lock b/trash.lock index 48eafc6271..9a3a7bf415 100755 --- a/trash.lock +++ b/trash.lock @@ -162,6 +162,9 @@ import: version: 89fcab3d43de07060e4fd4c1547430ed57e87f24 - package: github.com/lithammer/dedent version: v1.1.0 +- package: github.com/matryer/moq + version: ee5226d43009 + repo: https://github.com/rancher/moq.git - package: github.com/mattn/go-shellwords version: v1.0.3-20-gf8471b0a71ded0 - package: github.com/mattn/go-sqlite3 @@ -216,9 +219,16 @@ import: version: v0.2.0 - package: github.com/prometheus/procfs version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259 -- package: github.com/rancher/norman - version: 50017efee23caa79542ef685b65a7b783e0a73ca - repo: https://github.com/ibuildthecloud/norman.git +- package: github.com/rancher/dynamiclistener + version: 077eb13a904f2c62496f31b158135d9743526f82 +- package: github.com/rancher/helm-controller + version: 4f3b43bfd868bcb74fe847f8df88c482e9b70ff8 +- package: github.com/rancher/remotedialer + version: 20ec38853712bb6d348f0db9ac47d34c954c6b00 +- package: github.com/rancher/wrangler + version: 4202dbfa88013c19238bb004d82e013f0593493d +- package: github.com/rancher/wrangler-api + version: efe26ac6a9d720e1bfa5a8cc5f8dce5ad598ce26 - package: github.com/robfig/cron version: v1-53-gdf38d32658d878 - package: github.com/rootless-containers/rootlesskit diff --git a/types/apis/apps/v1/zz_generated_daemon_set_controller.go b/types/apis/apps/v1/zz_generated_daemon_set_controller.go deleted file mode 100644 index 3db3c3f1ef..0000000000 --- a/types/apis/apps/v1/zz_generated_daemon_set_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "k8s.io/api/apps/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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - DaemonSetGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "DaemonSet", - } - DaemonSetResource = metav1.APIResource{ - Name: "daemonsets", - SingularName: "daemonset", - Namespaced: true, - - Kind: DaemonSetGroupVersionKind.Kind, - } -) - -func NewDaemonSet(namespace, name string, obj v1.DaemonSet) *v1.DaemonSet { - obj.APIVersion, obj.Kind = DaemonSetGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type DaemonSetList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.DaemonSet -} - -type DaemonSetHandlerFunc func(key string, obj *v1.DaemonSet) (runtime.Object, error) - -type DaemonSetChangeHandlerFunc func(obj *v1.DaemonSet) (runtime.Object, error) - -type DaemonSetLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.DaemonSet, err error) - Get(namespace, name string) (*v1.DaemonSet, error) -} - -type DaemonSetController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() DaemonSetLister - AddHandler(ctx context.Context, name string, handler DaemonSetHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler DaemonSetHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type DaemonSetInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.DaemonSet) (*v1.DaemonSet, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.DaemonSet, error) - Get(name string, opts metav1.GetOptions) (*v1.DaemonSet, error) - Update(*v1.DaemonSet) (*v1.DaemonSet, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*DaemonSetList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() DaemonSetController - AddHandler(ctx context.Context, name string, sync DaemonSetHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle DaemonSetLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DaemonSetHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DaemonSetLifecycle) -} - -type daemonSetLister struct { - controller *daemonSetController -} - -func (l *daemonSetLister) List(namespace string, selector labels.Selector) (ret []*v1.DaemonSet, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.DaemonSet)) - }) - return -} - -func (l *daemonSetLister) Get(namespace, name string) (*v1.DaemonSet, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: DaemonSetGroupVersionKind.Group, - Resource: "daemonSet", - }, key) - } - return obj.(*v1.DaemonSet), nil -} - -type daemonSetController struct { - controller.GenericController -} - -func (c *daemonSetController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *daemonSetController) Lister() DaemonSetLister { - return &daemonSetLister{ - controller: c, - } -} - -func (c *daemonSetController) AddHandler(ctx context.Context, name string, handler DaemonSetHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.DaemonSet); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *daemonSetController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler DaemonSetHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.DaemonSet); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type daemonSetFactory struct { -} - -func (c daemonSetFactory) Object() runtime.Object { - return &v1.DaemonSet{} -} - -func (c daemonSetFactory) List() runtime.Object { - return &DaemonSetList{} -} - -func (s *daemonSetClient) Controller() DaemonSetController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.daemonSetControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(DaemonSetGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &daemonSetController{ - GenericController: genericController, - } - - s.client.daemonSetControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type daemonSetClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller DaemonSetController -} - -func (s *daemonSetClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *daemonSetClient) Create(o *v1.DaemonSet) (*v1.DaemonSet, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.DaemonSet), err -} - -func (s *daemonSetClient) Get(name string, opts metav1.GetOptions) (*v1.DaemonSet, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.DaemonSet), err -} - -func (s *daemonSetClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.DaemonSet, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.DaemonSet), err -} - -func (s *daemonSetClient) Update(o *v1.DaemonSet) (*v1.DaemonSet, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.DaemonSet), err -} - -func (s *daemonSetClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *daemonSetClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *daemonSetClient) List(opts metav1.ListOptions) (*DaemonSetList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*DaemonSetList), err -} - -func (s *daemonSetClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *daemonSetClient) Patch(o *v1.DaemonSet, patchType types.PatchType, data []byte, subresources ...string) (*v1.DaemonSet, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.DaemonSet), err -} - -func (s *daemonSetClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *daemonSetClient) AddHandler(ctx context.Context, name string, sync DaemonSetHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *daemonSetClient) AddLifecycle(ctx context.Context, name string, lifecycle DaemonSetLifecycle) { - sync := NewDaemonSetLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *daemonSetClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DaemonSetHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *daemonSetClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DaemonSetLifecycle) { - sync := NewDaemonSetLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type DaemonSetIndexer func(obj *v1.DaemonSet) ([]string, error) - -type DaemonSetClientCache interface { - Get(namespace, name string) (*v1.DaemonSet, error) - List(namespace string, selector labels.Selector) ([]*v1.DaemonSet, error) - - Index(name string, indexer DaemonSetIndexer) - GetIndexed(name, key string) ([]*v1.DaemonSet, error) -} - -type DaemonSetClient interface { - Create(*v1.DaemonSet) (*v1.DaemonSet, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.DaemonSet, error) - Update(*v1.DaemonSet) (*v1.DaemonSet, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*DaemonSetList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() DaemonSetClientCache - - OnCreate(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() DaemonSetInterface -} - -type daemonSetClientCache struct { - client *daemonSetClient2 -} - -type daemonSetClient2 struct { - iface DaemonSetInterface - controller DaemonSetController -} - -func (n *daemonSetClient2) Interface() DaemonSetInterface { - return n.iface -} - -func (n *daemonSetClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *daemonSetClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *daemonSetClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *daemonSetClient2) Create(obj *v1.DaemonSet) (*v1.DaemonSet, error) { - return n.iface.Create(obj) -} - -func (n *daemonSetClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.DaemonSet, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *daemonSetClient2) Update(obj *v1.DaemonSet) (*v1.DaemonSet, error) { - return n.iface.Update(obj) -} - -func (n *daemonSetClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *daemonSetClient2) List(namespace string, opts metav1.ListOptions) (*DaemonSetList, error) { - return n.iface.List(opts) -} - -func (n *daemonSetClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *daemonSetClientCache) Get(namespace, name string) (*v1.DaemonSet, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *daemonSetClientCache) List(namespace string, selector labels.Selector) ([]*v1.DaemonSet, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *daemonSetClient2) Cache() DaemonSetClientCache { - n.loadController() - return &daemonSetClientCache{ - client: n, - } -} - -func (n *daemonSetClient2) OnCreate(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &daemonSetLifecycleDelegate{create: sync}) -} - -func (n *daemonSetClient2) OnChange(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &daemonSetLifecycleDelegate{update: sync}) -} - -func (n *daemonSetClient2) OnRemove(ctx context.Context, name string, sync DaemonSetChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &daemonSetLifecycleDelegate{remove: sync}) -} - -func (n *daemonSetClientCache) Index(name string, indexer DaemonSetIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.DaemonSet); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *daemonSetClientCache) GetIndexed(name, key string) ([]*v1.DaemonSet, error) { - var result []*v1.DaemonSet - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.DaemonSet); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *daemonSetClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type daemonSetLifecycleDelegate struct { - create DaemonSetChangeHandlerFunc - update DaemonSetChangeHandlerFunc - remove DaemonSetChangeHandlerFunc -} - -func (n *daemonSetLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *daemonSetLifecycleDelegate) Create(obj *v1.DaemonSet) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *daemonSetLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *daemonSetLifecycleDelegate) Remove(obj *v1.DaemonSet) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *daemonSetLifecycleDelegate) Updated(obj *v1.DaemonSet) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/apps/v1/zz_generated_daemon_set_lifecycle_adapter.go b/types/apis/apps/v1/zz_generated_daemon_set_lifecycle_adapter.go deleted file mode 100644 index 1b45e13215..0000000000 --- a/types/apis/apps/v1/zz_generated_daemon_set_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type DaemonSetLifecycle interface { - Create(obj *v1.DaemonSet) (runtime.Object, error) - Remove(obj *v1.DaemonSet) (runtime.Object, error) - Updated(obj *v1.DaemonSet) (runtime.Object, error) -} - -type daemonSetLifecycleAdapter struct { - lifecycle DaemonSetLifecycle -} - -func (w *daemonSetLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *daemonSetLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *daemonSetLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.DaemonSet)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *daemonSetLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.DaemonSet)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *daemonSetLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.DaemonSet)) - if o == nil { - return nil, err - } - return o, err -} - -func NewDaemonSetLifecycleAdapter(name string, clusterScoped bool, client DaemonSetInterface, l DaemonSetLifecycle) DaemonSetHandlerFunc { - adapter := &daemonSetLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.DaemonSet) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/apps/v1/zz_generated_deepcopy.go b/types/apis/apps/v1/zz_generated_deepcopy.go deleted file mode 100644 index b58e7eeb71..0000000000 --- a/types/apis/apps/v1/zz_generated_deepcopy.go +++ /dev/null @@ -1,72 +0,0 @@ -package v1 - -import ( - appsv1 "k8s.io/api/apps/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 *DaemonSetList) DeepCopyInto(out *DaemonSetList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]appsv1.DaemonSet, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DaemonSetList. -func (in *DaemonSetList) DeepCopy() *DaemonSetList { - if in == nil { - return nil - } - out := new(DaemonSetList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DaemonSetList) 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 *DeploymentList) DeepCopyInto(out *DeploymentList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]appsv1.Deployment, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentList. -func (in *DeploymentList) DeepCopy() *DeploymentList { - if in == nil { - return nil - } - out := new(DeploymentList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DeploymentList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/types/apis/apps/v1/zz_generated_deployment_controller.go b/types/apis/apps/v1/zz_generated_deployment_controller.go deleted file mode 100644 index 3ddb52c204..0000000000 --- a/types/apis/apps/v1/zz_generated_deployment_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "k8s.io/api/apps/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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - DeploymentGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Deployment", - } - DeploymentResource = metav1.APIResource{ - Name: "deployments", - SingularName: "deployment", - Namespaced: true, - - Kind: DeploymentGroupVersionKind.Kind, - } -) - -func NewDeployment(namespace, name string, obj v1.Deployment) *v1.Deployment { - obj.APIVersion, obj.Kind = DeploymentGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type DeploymentList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Deployment -} - -type DeploymentHandlerFunc func(key string, obj *v1.Deployment) (runtime.Object, error) - -type DeploymentChangeHandlerFunc func(obj *v1.Deployment) (runtime.Object, error) - -type DeploymentLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Deployment, err error) - Get(namespace, name string) (*v1.Deployment, error) -} - -type DeploymentController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() DeploymentLister - AddHandler(ctx context.Context, name string, handler DeploymentHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler DeploymentHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type DeploymentInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Deployment) (*v1.Deployment, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) - Get(name string, opts metav1.GetOptions) (*v1.Deployment, error) - Update(*v1.Deployment) (*v1.Deployment, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*DeploymentList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() DeploymentController - AddHandler(ctx context.Context, name string, sync DeploymentHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle DeploymentLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DeploymentHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DeploymentLifecycle) -} - -type deploymentLister struct { - controller *deploymentController -} - -func (l *deploymentLister) List(namespace string, selector labels.Selector) (ret []*v1.Deployment, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Deployment)) - }) - return -} - -func (l *deploymentLister) Get(namespace, name string) (*v1.Deployment, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: DeploymentGroupVersionKind.Group, - Resource: "deployment", - }, key) - } - return obj.(*v1.Deployment), nil -} - -type deploymentController struct { - controller.GenericController -} - -func (c *deploymentController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *deploymentController) Lister() DeploymentLister { - return &deploymentLister{ - controller: c, - } -} - -func (c *deploymentController) AddHandler(ctx context.Context, name string, handler DeploymentHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Deployment); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *deploymentController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler DeploymentHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Deployment); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type deploymentFactory struct { -} - -func (c deploymentFactory) Object() runtime.Object { - return &v1.Deployment{} -} - -func (c deploymentFactory) List() runtime.Object { - return &DeploymentList{} -} - -func (s *deploymentClient) Controller() DeploymentController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.deploymentControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(DeploymentGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &deploymentController{ - GenericController: genericController, - } - - s.client.deploymentControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type deploymentClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller DeploymentController -} - -func (s *deploymentClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *deploymentClient) Create(o *v1.Deployment) (*v1.Deployment, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Deployment), err -} - -func (s *deploymentClient) Get(name string, opts metav1.GetOptions) (*v1.Deployment, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Deployment), err -} - -func (s *deploymentClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Deployment), err -} - -func (s *deploymentClient) Update(o *v1.Deployment) (*v1.Deployment, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Deployment), err -} - -func (s *deploymentClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *deploymentClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *deploymentClient) List(opts metav1.ListOptions) (*DeploymentList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*DeploymentList), err -} - -func (s *deploymentClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *deploymentClient) Patch(o *v1.Deployment, patchType types.PatchType, data []byte, subresources ...string) (*v1.Deployment, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Deployment), err -} - -func (s *deploymentClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *deploymentClient) AddHandler(ctx context.Context, name string, sync DeploymentHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *deploymentClient) AddLifecycle(ctx context.Context, name string, lifecycle DeploymentLifecycle) { - sync := NewDeploymentLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *deploymentClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync DeploymentHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *deploymentClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle DeploymentLifecycle) { - sync := NewDeploymentLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type DeploymentIndexer func(obj *v1.Deployment) ([]string, error) - -type DeploymentClientCache interface { - Get(namespace, name string) (*v1.Deployment, error) - List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) - - Index(name string, indexer DeploymentIndexer) - GetIndexed(name, key string) ([]*v1.Deployment, error) -} - -type DeploymentClient interface { - Create(*v1.Deployment) (*v1.Deployment, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) - Update(*v1.Deployment) (*v1.Deployment, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*DeploymentList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() DeploymentClientCache - - OnCreate(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() DeploymentInterface -} - -type deploymentClientCache struct { - client *deploymentClient2 -} - -type deploymentClient2 struct { - iface DeploymentInterface - controller DeploymentController -} - -func (n *deploymentClient2) Interface() DeploymentInterface { - return n.iface -} - -func (n *deploymentClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *deploymentClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *deploymentClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *deploymentClient2) Create(obj *v1.Deployment) (*v1.Deployment, error) { - return n.iface.Create(obj) -} - -func (n *deploymentClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Deployment, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *deploymentClient2) Update(obj *v1.Deployment) (*v1.Deployment, error) { - return n.iface.Update(obj) -} - -func (n *deploymentClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *deploymentClient2) List(namespace string, opts metav1.ListOptions) (*DeploymentList, error) { - return n.iface.List(opts) -} - -func (n *deploymentClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *deploymentClientCache) Get(namespace, name string) (*v1.Deployment, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *deploymentClientCache) List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *deploymentClient2) Cache() DeploymentClientCache { - n.loadController() - return &deploymentClientCache{ - client: n, - } -} - -func (n *deploymentClient2) OnCreate(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &deploymentLifecycleDelegate{create: sync}) -} - -func (n *deploymentClient2) OnChange(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &deploymentLifecycleDelegate{update: sync}) -} - -func (n *deploymentClient2) OnRemove(ctx context.Context, name string, sync DeploymentChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &deploymentLifecycleDelegate{remove: sync}) -} - -func (n *deploymentClientCache) Index(name string, indexer DeploymentIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Deployment); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *deploymentClientCache) GetIndexed(name, key string) ([]*v1.Deployment, error) { - var result []*v1.Deployment - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Deployment); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *deploymentClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type deploymentLifecycleDelegate struct { - create DeploymentChangeHandlerFunc - update DeploymentChangeHandlerFunc - remove DeploymentChangeHandlerFunc -} - -func (n *deploymentLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *deploymentLifecycleDelegate) Create(obj *v1.Deployment) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *deploymentLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *deploymentLifecycleDelegate) Remove(obj *v1.Deployment) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *deploymentLifecycleDelegate) Updated(obj *v1.Deployment) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go b/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go deleted file mode 100644 index 152b5058b7..0000000000 --- a/types/apis/apps/v1/zz_generated_deployment_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type DeploymentLifecycle interface { - Create(obj *v1.Deployment) (runtime.Object, error) - Remove(obj *v1.Deployment) (runtime.Object, error) - Updated(obj *v1.Deployment) (runtime.Object, error) -} - -type deploymentLifecycleAdapter struct { - lifecycle DeploymentLifecycle -} - -func (w *deploymentLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *deploymentLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *deploymentLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Deployment)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *deploymentLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Deployment)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *deploymentLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Deployment)) - if o == nil { - return nil, err - } - return o, err -} - -func NewDeploymentLifecycleAdapter(name string, clusterScoped bool, client DeploymentInterface, l DeploymentLifecycle) DeploymentHandlerFunc { - adapter := &deploymentLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Deployment) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/apps/v1/zz_generated_k8s_client.go b/types/apis/apps/v1/zz_generated_k8s_client.go deleted file mode 100644 index 7fea8da718..0000000000 --- a/types/apis/apps/v1/zz_generated_k8s_client.go +++ /dev/null @@ -1,139 +0,0 @@ -package v1 - -import ( - "context" - "sync" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - - DaemonSetsGetter - DeploymentsGetter -} - -type Clients struct { - Interface Interface - - DaemonSet DaemonSetClient - Deployment DeploymentClient -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - - daemonSetControllers map[string]DaemonSetController - deploymentControllers map[string]DeploymentController -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - - DaemonSet: &daemonSetClient2{ - iface: iface.DaemonSets(""), - }, - Deployment: &deploymentClient2{ - iface: iface.Deployments(""), - }, - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - - daemonSetControllers: map[string]DaemonSetController{}, - deploymentControllers: map[string]DeploymentController{}, - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -type DaemonSetsGetter interface { - DaemonSets(namespace string) DaemonSetInterface -} - -func (c *Client) DaemonSets(namespace string) DaemonSetInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &DaemonSetResource, DaemonSetGroupVersionKind, daemonSetFactory{}) - return &daemonSetClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type DeploymentsGetter interface { - Deployments(namespace string) DeploymentInterface -} - -func (c *Client) Deployments(namespace string) DeploymentInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &DeploymentResource, DeploymentGroupVersionKind, deploymentFactory{}) - return &deploymentClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} diff --git a/types/apis/apps/v1/zz_generated_scheme.go b/types/apis/apps/v1/zz_generated_scheme.go deleted file mode 100644 index d587bca7a0..0000000000 --- a/types/apis/apps/v1/zz_generated_scheme.go +++ /dev/null @@ -1,40 +0,0 @@ -package v1 - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "apps" - Version = "v1" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - - &DaemonSetList{}, - &DeploymentList{}, - ) - return nil -} diff --git a/types/apis/batch/v1/zz_generated_deepcopy.go b/types/apis/batch/v1/zz_generated_deepcopy.go deleted file mode 100644 index 7d0d3c14d1..0000000000 --- a/types/apis/batch/v1/zz_generated_deepcopy.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - batchv1 "k8s.io/api/batch/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 *JobList) DeepCopyInto(out *JobList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]batchv1.Job, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JobList. -func (in *JobList) DeepCopy() *JobList { - if in == nil { - return nil - } - out := new(JobList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *JobList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/types/apis/batch/v1/zz_generated_job_controller.go b/types/apis/batch/v1/zz_generated_job_controller.go deleted file mode 100644 index 886f353b30..0000000000 --- a/types/apis/batch/v1/zz_generated_job_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "k8s.io/api/batch/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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - JobGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Job", - } - JobResource = metav1.APIResource{ - Name: "jobs", - SingularName: "job", - Namespaced: true, - - Kind: JobGroupVersionKind.Kind, - } -) - -func NewJob(namespace, name string, obj v1.Job) *v1.Job { - obj.APIVersion, obj.Kind = JobGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type JobList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Job -} - -type JobHandlerFunc func(key string, obj *v1.Job) (runtime.Object, error) - -type JobChangeHandlerFunc func(obj *v1.Job) (runtime.Object, error) - -type JobLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Job, err error) - Get(namespace, name string) (*v1.Job, error) -} - -type JobController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() JobLister - AddHandler(ctx context.Context, name string, handler JobHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler JobHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type JobInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Job) (*v1.Job, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Job, error) - Get(name string, opts metav1.GetOptions) (*v1.Job, error) - Update(*v1.Job) (*v1.Job, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*JobList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() JobController - AddHandler(ctx context.Context, name string, sync JobHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle JobLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync JobHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle JobLifecycle) -} - -type jobLister struct { - controller *jobController -} - -func (l *jobLister) List(namespace string, selector labels.Selector) (ret []*v1.Job, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Job)) - }) - return -} - -func (l *jobLister) Get(namespace, name string) (*v1.Job, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: JobGroupVersionKind.Group, - Resource: "job", - }, key) - } - return obj.(*v1.Job), nil -} - -type jobController struct { - controller.GenericController -} - -func (c *jobController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *jobController) Lister() JobLister { - return &jobLister{ - controller: c, - } -} - -func (c *jobController) AddHandler(ctx context.Context, name string, handler JobHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Job); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *jobController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler JobHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Job); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type jobFactory struct { -} - -func (c jobFactory) Object() runtime.Object { - return &v1.Job{} -} - -func (c jobFactory) List() runtime.Object { - return &JobList{} -} - -func (s *jobClient) Controller() JobController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.jobControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(JobGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &jobController{ - GenericController: genericController, - } - - s.client.jobControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type jobClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller JobController -} - -func (s *jobClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *jobClient) Create(o *v1.Job) (*v1.Job, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Job), err -} - -func (s *jobClient) Get(name string, opts metav1.GetOptions) (*v1.Job, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Job), err -} - -func (s *jobClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Job, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Job), err -} - -func (s *jobClient) Update(o *v1.Job) (*v1.Job, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Job), err -} - -func (s *jobClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *jobClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *jobClient) List(opts metav1.ListOptions) (*JobList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*JobList), err -} - -func (s *jobClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *jobClient) Patch(o *v1.Job, patchType types.PatchType, data []byte, subresources ...string) (*v1.Job, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Job), err -} - -func (s *jobClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *jobClient) AddHandler(ctx context.Context, name string, sync JobHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *jobClient) AddLifecycle(ctx context.Context, name string, lifecycle JobLifecycle) { - sync := NewJobLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *jobClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync JobHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *jobClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle JobLifecycle) { - sync := NewJobLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type JobIndexer func(obj *v1.Job) ([]string, error) - -type JobClientCache interface { - Get(namespace, name string) (*v1.Job, error) - List(namespace string, selector labels.Selector) ([]*v1.Job, error) - - Index(name string, indexer JobIndexer) - GetIndexed(name, key string) ([]*v1.Job, error) -} - -type JobClient interface { - Create(*v1.Job) (*v1.Job, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Job, error) - Update(*v1.Job) (*v1.Job, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*JobList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() JobClientCache - - OnCreate(ctx context.Context, name string, sync JobChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync JobChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync JobChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() JobInterface -} - -type jobClientCache struct { - client *jobClient2 -} - -type jobClient2 struct { - iface JobInterface - controller JobController -} - -func (n *jobClient2) Interface() JobInterface { - return n.iface -} - -func (n *jobClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *jobClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *jobClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *jobClient2) Create(obj *v1.Job) (*v1.Job, error) { - return n.iface.Create(obj) -} - -func (n *jobClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Job, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *jobClient2) Update(obj *v1.Job) (*v1.Job, error) { - return n.iface.Update(obj) -} - -func (n *jobClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *jobClient2) List(namespace string, opts metav1.ListOptions) (*JobList, error) { - return n.iface.List(opts) -} - -func (n *jobClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *jobClientCache) Get(namespace, name string) (*v1.Job, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *jobClientCache) List(namespace string, selector labels.Selector) ([]*v1.Job, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *jobClient2) Cache() JobClientCache { - n.loadController() - return &jobClientCache{ - client: n, - } -} - -func (n *jobClient2) OnCreate(ctx context.Context, name string, sync JobChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &jobLifecycleDelegate{create: sync}) -} - -func (n *jobClient2) OnChange(ctx context.Context, name string, sync JobChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &jobLifecycleDelegate{update: sync}) -} - -func (n *jobClient2) OnRemove(ctx context.Context, name string, sync JobChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &jobLifecycleDelegate{remove: sync}) -} - -func (n *jobClientCache) Index(name string, indexer JobIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Job); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *jobClientCache) GetIndexed(name, key string) ([]*v1.Job, error) { - var result []*v1.Job - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Job); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *jobClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type jobLifecycleDelegate struct { - create JobChangeHandlerFunc - update JobChangeHandlerFunc - remove JobChangeHandlerFunc -} - -func (n *jobLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *jobLifecycleDelegate) Create(obj *v1.Job) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *jobLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *jobLifecycleDelegate) Remove(obj *v1.Job) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *jobLifecycleDelegate) Updated(obj *v1.Job) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/batch/v1/zz_generated_job_lifecycle_adapter.go b/types/apis/batch/v1/zz_generated_job_lifecycle_adapter.go deleted file mode 100644 index 1294f834e0..0000000000 --- a/types/apis/batch/v1/zz_generated_job_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/batch/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type JobLifecycle interface { - Create(obj *v1.Job) (runtime.Object, error) - Remove(obj *v1.Job) (runtime.Object, error) - Updated(obj *v1.Job) (runtime.Object, error) -} - -type jobLifecycleAdapter struct { - lifecycle JobLifecycle -} - -func (w *jobLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *jobLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *jobLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Job)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *jobLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Job)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *jobLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Job)) - if o == nil { - return nil, err - } - return o, err -} - -func NewJobLifecycleAdapter(name string, clusterScoped bool, client JobInterface, l JobLifecycle) JobHandlerFunc { - adapter := &jobLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Job) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/batch/v1/zz_generated_k8s_client.go b/types/apis/batch/v1/zz_generated_k8s_client.go deleted file mode 100644 index c1ff70a6a4..0000000000 --- a/types/apis/batch/v1/zz_generated_k8s_client.go +++ /dev/null @@ -1,119 +0,0 @@ -package v1 - -import ( - "context" - "sync" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - - JobsGetter -} - -type Clients struct { - Interface Interface - - Job JobClient -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - - jobControllers map[string]JobController -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - - Job: &jobClient2{ - iface: iface.Jobs(""), - }, - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - - jobControllers: map[string]JobController{}, - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -type JobsGetter interface { - Jobs(namespace string) JobInterface -} - -func (c *Client) Jobs(namespace string) JobInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &JobResource, JobGroupVersionKind, jobFactory{}) - return &jobClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} diff --git a/types/apis/batch/v1/zz_generated_scheme.go b/types/apis/batch/v1/zz_generated_scheme.go deleted file mode 100644 index e740c6d5a2..0000000000 --- a/types/apis/batch/v1/zz_generated_scheme.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "batch" - Version = "v1" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - - &JobList{}, - ) - return nil -} diff --git a/types/apis/core/v1/zz_generated_config_map_controller.go b/types/apis/core/v1/zz_generated_config_map_controller.go deleted file mode 100644 index 5cf44e6c58..0000000000 --- a/types/apis/core/v1/zz_generated_config_map_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - ConfigMapGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "ConfigMap", - } - ConfigMapResource = metav1.APIResource{ - Name: "configmaps", - SingularName: "configmap", - Namespaced: true, - - Kind: ConfigMapGroupVersionKind.Kind, - } -) - -func NewConfigMap(namespace, name string, obj v1.ConfigMap) *v1.ConfigMap { - obj.APIVersion, obj.Kind = ConfigMapGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type ConfigMapList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.ConfigMap -} - -type ConfigMapHandlerFunc func(key string, obj *v1.ConfigMap) (runtime.Object, error) - -type ConfigMapChangeHandlerFunc func(obj *v1.ConfigMap) (runtime.Object, error) - -type ConfigMapLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.ConfigMap, err error) - Get(namespace, name string) (*v1.ConfigMap, error) -} - -type ConfigMapController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() ConfigMapLister - AddHandler(ctx context.Context, name string, handler ConfigMapHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ConfigMapHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type ConfigMapInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.ConfigMap) (*v1.ConfigMap, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ConfigMap, error) - Get(name string, opts metav1.GetOptions) (*v1.ConfigMap, error) - Update(*v1.ConfigMap) (*v1.ConfigMap, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*ConfigMapList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() ConfigMapController - AddHandler(ctx context.Context, name string, sync ConfigMapHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle ConfigMapLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ConfigMapHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ConfigMapLifecycle) -} - -type configMapLister struct { - controller *configMapController -} - -func (l *configMapLister) List(namespace string, selector labels.Selector) (ret []*v1.ConfigMap, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.ConfigMap)) - }) - return -} - -func (l *configMapLister) Get(namespace, name string) (*v1.ConfigMap, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: ConfigMapGroupVersionKind.Group, - Resource: "configMap", - }, key) - } - return obj.(*v1.ConfigMap), nil -} - -type configMapController struct { - controller.GenericController -} - -func (c *configMapController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *configMapController) Lister() ConfigMapLister { - return &configMapLister{ - controller: c, - } -} - -func (c *configMapController) AddHandler(ctx context.Context, name string, handler ConfigMapHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ConfigMap); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *configMapController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ConfigMapHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ConfigMap); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type configMapFactory struct { -} - -func (c configMapFactory) Object() runtime.Object { - return &v1.ConfigMap{} -} - -func (c configMapFactory) List() runtime.Object { - return &ConfigMapList{} -} - -func (s *configMapClient) Controller() ConfigMapController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.configMapControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(ConfigMapGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &configMapController{ - GenericController: genericController, - } - - s.client.configMapControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type configMapClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller ConfigMapController -} - -func (s *configMapClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *configMapClient) Create(o *v1.ConfigMap) (*v1.ConfigMap, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.ConfigMap), err -} - -func (s *configMapClient) Get(name string, opts metav1.GetOptions) (*v1.ConfigMap, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.ConfigMap), err -} - -func (s *configMapClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ConfigMap, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.ConfigMap), err -} - -func (s *configMapClient) Update(o *v1.ConfigMap) (*v1.ConfigMap, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.ConfigMap), err -} - -func (s *configMapClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *configMapClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *configMapClient) List(opts metav1.ListOptions) (*ConfigMapList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*ConfigMapList), err -} - -func (s *configMapClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *configMapClient) Patch(o *v1.ConfigMap, patchType types.PatchType, data []byte, subresources ...string) (*v1.ConfigMap, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.ConfigMap), err -} - -func (s *configMapClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *configMapClient) AddHandler(ctx context.Context, name string, sync ConfigMapHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *configMapClient) AddLifecycle(ctx context.Context, name string, lifecycle ConfigMapLifecycle) { - sync := NewConfigMapLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *configMapClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ConfigMapHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *configMapClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ConfigMapLifecycle) { - sync := NewConfigMapLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type ConfigMapIndexer func(obj *v1.ConfigMap) ([]string, error) - -type ConfigMapClientCache interface { - Get(namespace, name string) (*v1.ConfigMap, error) - List(namespace string, selector labels.Selector) ([]*v1.ConfigMap, error) - - Index(name string, indexer ConfigMapIndexer) - GetIndexed(name, key string) ([]*v1.ConfigMap, error) -} - -type ConfigMapClient interface { - Create(*v1.ConfigMap) (*v1.ConfigMap, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.ConfigMap, error) - Update(*v1.ConfigMap) (*v1.ConfigMap, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*ConfigMapList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() ConfigMapClientCache - - OnCreate(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() ConfigMapInterface -} - -type configMapClientCache struct { - client *configMapClient2 -} - -type configMapClient2 struct { - iface ConfigMapInterface - controller ConfigMapController -} - -func (n *configMapClient2) Interface() ConfigMapInterface { - return n.iface -} - -func (n *configMapClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *configMapClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *configMapClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *configMapClient2) Create(obj *v1.ConfigMap) (*v1.ConfigMap, error) { - return n.iface.Create(obj) -} - -func (n *configMapClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.ConfigMap, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *configMapClient2) Update(obj *v1.ConfigMap) (*v1.ConfigMap, error) { - return n.iface.Update(obj) -} - -func (n *configMapClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *configMapClient2) List(namespace string, opts metav1.ListOptions) (*ConfigMapList, error) { - return n.iface.List(opts) -} - -func (n *configMapClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *configMapClientCache) Get(namespace, name string) (*v1.ConfigMap, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *configMapClientCache) List(namespace string, selector labels.Selector) ([]*v1.ConfigMap, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *configMapClient2) Cache() ConfigMapClientCache { - n.loadController() - return &configMapClientCache{ - client: n, - } -} - -func (n *configMapClient2) OnCreate(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &configMapLifecycleDelegate{create: sync}) -} - -func (n *configMapClient2) OnChange(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &configMapLifecycleDelegate{update: sync}) -} - -func (n *configMapClient2) OnRemove(ctx context.Context, name string, sync ConfigMapChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &configMapLifecycleDelegate{remove: sync}) -} - -func (n *configMapClientCache) Index(name string, indexer ConfigMapIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.ConfigMap); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *configMapClientCache) GetIndexed(name, key string) ([]*v1.ConfigMap, error) { - var result []*v1.ConfigMap - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.ConfigMap); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *configMapClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type configMapLifecycleDelegate struct { - create ConfigMapChangeHandlerFunc - update ConfigMapChangeHandlerFunc - remove ConfigMapChangeHandlerFunc -} - -func (n *configMapLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *configMapLifecycleDelegate) Create(obj *v1.ConfigMap) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *configMapLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *configMapLifecycleDelegate) Remove(obj *v1.ConfigMap) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *configMapLifecycleDelegate) Updated(obj *v1.ConfigMap) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_config_map_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_config_map_lifecycle_adapter.go deleted file mode 100644 index d707c27dd8..0000000000 --- a/types/apis/core/v1/zz_generated_config_map_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type ConfigMapLifecycle interface { - Create(obj *v1.ConfigMap) (runtime.Object, error) - Remove(obj *v1.ConfigMap) (runtime.Object, error) - Updated(obj *v1.ConfigMap) (runtime.Object, error) -} - -type configMapLifecycleAdapter struct { - lifecycle ConfigMapLifecycle -} - -func (w *configMapLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *configMapLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *configMapLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.ConfigMap)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *configMapLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.ConfigMap)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *configMapLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.ConfigMap)) - if o == nil { - return nil, err - } - return o, err -} - -func NewConfigMapLifecycleAdapter(name string, clusterScoped bool, client ConfigMapInterface, l ConfigMapLifecycle) ConfigMapHandlerFunc { - adapter := &configMapLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.ConfigMap) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/core/v1/zz_generated_deepcopy.go b/types/apis/core/v1/zz_generated_deepcopy.go deleted file mode 100644 index 59b141f51d..0000000000 --- a/types/apis/core/v1/zz_generated_deepcopy.go +++ /dev/null @@ -1,204 +0,0 @@ -package v1 - -import ( - corev1 "k8s.io/api/core/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 *ConfigMapList) DeepCopyInto(out *ConfigMapList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.ConfigMap, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapList. -func (in *ConfigMapList) DeepCopy() *ConfigMapList { - if in == nil { - return nil - } - out := new(ConfigMapList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ConfigMapList) 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 *EndpointsList) DeepCopyInto(out *EndpointsList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.Endpoints, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointsList. -func (in *EndpointsList) DeepCopy() *EndpointsList { - if in == nil { - return nil - } - out := new(EndpointsList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *EndpointsList) 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 *NodeList) DeepCopyInto(out *NodeList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.Node, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeList. -func (in *NodeList) DeepCopy() *NodeList { - if in == nil { - return nil - } - out := new(NodeList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *NodeList) 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 *PodList) DeepCopyInto(out *PodList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.Pod, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodList. -func (in *PodList) DeepCopy() *PodList { - if in == nil { - return nil - } - out := new(PodList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PodList) 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 *ServiceAccountList) DeepCopyInto(out *ServiceAccountList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.ServiceAccount, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountList. -func (in *ServiceAccountList) DeepCopy() *ServiceAccountList { - if in == nil { - return nil - } - out := new(ServiceAccountList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ServiceAccountList) 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 *ServiceList) DeepCopyInto(out *ServiceList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]corev1.Service, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceList. -func (in *ServiceList) DeepCopy() *ServiceList { - if in == nil { - return nil - } - out := new(ServiceList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ServiceList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/types/apis/core/v1/zz_generated_endpoints_controller.go b/types/apis/core/v1/zz_generated_endpoints_controller.go deleted file mode 100644 index 7938d46877..0000000000 --- a/types/apis/core/v1/zz_generated_endpoints_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - EndpointsGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Endpoints", - } - EndpointsResource = metav1.APIResource{ - Name: "endpoints", - SingularName: "endpoints", - Namespaced: true, - - Kind: EndpointsGroupVersionKind.Kind, - } -) - -func NewEndpoints(namespace, name string, obj v1.Endpoints) *v1.Endpoints { - obj.APIVersion, obj.Kind = EndpointsGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type EndpointsList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Endpoints -} - -type EndpointsHandlerFunc func(key string, obj *v1.Endpoints) (runtime.Object, error) - -type EndpointsChangeHandlerFunc func(obj *v1.Endpoints) (runtime.Object, error) - -type EndpointsLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Endpoints, err error) - Get(namespace, name string) (*v1.Endpoints, error) -} - -type EndpointsController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() EndpointsLister - AddHandler(ctx context.Context, name string, handler EndpointsHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler EndpointsHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type EndpointsInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Endpoints) (*v1.Endpoints, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Endpoints, error) - Get(name string, opts metav1.GetOptions) (*v1.Endpoints, error) - Update(*v1.Endpoints) (*v1.Endpoints, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*EndpointsList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() EndpointsController - AddHandler(ctx context.Context, name string, sync EndpointsHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle EndpointsLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync EndpointsHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle EndpointsLifecycle) -} - -type endpointsLister struct { - controller *endpointsController -} - -func (l *endpointsLister) List(namespace string, selector labels.Selector) (ret []*v1.Endpoints, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Endpoints)) - }) - return -} - -func (l *endpointsLister) Get(namespace, name string) (*v1.Endpoints, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: EndpointsGroupVersionKind.Group, - Resource: "endpoints", - }, key) - } - return obj.(*v1.Endpoints), nil -} - -type endpointsController struct { - controller.GenericController -} - -func (c *endpointsController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *endpointsController) Lister() EndpointsLister { - return &endpointsLister{ - controller: c, - } -} - -func (c *endpointsController) AddHandler(ctx context.Context, name string, handler EndpointsHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Endpoints); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *endpointsController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler EndpointsHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Endpoints); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type endpointsFactory struct { -} - -func (c endpointsFactory) Object() runtime.Object { - return &v1.Endpoints{} -} - -func (c endpointsFactory) List() runtime.Object { - return &EndpointsList{} -} - -func (s *endpointsClient) Controller() EndpointsController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.endpointsControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(EndpointsGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &endpointsController{ - GenericController: genericController, - } - - s.client.endpointsControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type endpointsClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller EndpointsController -} - -func (s *endpointsClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *endpointsClient) Create(o *v1.Endpoints) (*v1.Endpoints, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Endpoints), err -} - -func (s *endpointsClient) Get(name string, opts metav1.GetOptions) (*v1.Endpoints, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Endpoints), err -} - -func (s *endpointsClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Endpoints, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Endpoints), err -} - -func (s *endpointsClient) Update(o *v1.Endpoints) (*v1.Endpoints, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Endpoints), err -} - -func (s *endpointsClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *endpointsClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *endpointsClient) List(opts metav1.ListOptions) (*EndpointsList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*EndpointsList), err -} - -func (s *endpointsClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *endpointsClient) Patch(o *v1.Endpoints, patchType types.PatchType, data []byte, subresources ...string) (*v1.Endpoints, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Endpoints), err -} - -func (s *endpointsClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *endpointsClient) AddHandler(ctx context.Context, name string, sync EndpointsHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *endpointsClient) AddLifecycle(ctx context.Context, name string, lifecycle EndpointsLifecycle) { - sync := NewEndpointsLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *endpointsClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync EndpointsHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *endpointsClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle EndpointsLifecycle) { - sync := NewEndpointsLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type EndpointsIndexer func(obj *v1.Endpoints) ([]string, error) - -type EndpointsClientCache interface { - Get(namespace, name string) (*v1.Endpoints, error) - List(namespace string, selector labels.Selector) ([]*v1.Endpoints, error) - - Index(name string, indexer EndpointsIndexer) - GetIndexed(name, key string) ([]*v1.Endpoints, error) -} - -type EndpointsClient interface { - Create(*v1.Endpoints) (*v1.Endpoints, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Endpoints, error) - Update(*v1.Endpoints) (*v1.Endpoints, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*EndpointsList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() EndpointsClientCache - - OnCreate(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() EndpointsInterface -} - -type endpointsClientCache struct { - client *endpointsClient2 -} - -type endpointsClient2 struct { - iface EndpointsInterface - controller EndpointsController -} - -func (n *endpointsClient2) Interface() EndpointsInterface { - return n.iface -} - -func (n *endpointsClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *endpointsClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *endpointsClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *endpointsClient2) Create(obj *v1.Endpoints) (*v1.Endpoints, error) { - return n.iface.Create(obj) -} - -func (n *endpointsClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Endpoints, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *endpointsClient2) Update(obj *v1.Endpoints) (*v1.Endpoints, error) { - return n.iface.Update(obj) -} - -func (n *endpointsClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *endpointsClient2) List(namespace string, opts metav1.ListOptions) (*EndpointsList, error) { - return n.iface.List(opts) -} - -func (n *endpointsClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *endpointsClientCache) Get(namespace, name string) (*v1.Endpoints, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *endpointsClientCache) List(namespace string, selector labels.Selector) ([]*v1.Endpoints, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *endpointsClient2) Cache() EndpointsClientCache { - n.loadController() - return &endpointsClientCache{ - client: n, - } -} - -func (n *endpointsClient2) OnCreate(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &endpointsLifecycleDelegate{create: sync}) -} - -func (n *endpointsClient2) OnChange(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &endpointsLifecycleDelegate{update: sync}) -} - -func (n *endpointsClient2) OnRemove(ctx context.Context, name string, sync EndpointsChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &endpointsLifecycleDelegate{remove: sync}) -} - -func (n *endpointsClientCache) Index(name string, indexer EndpointsIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Endpoints); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *endpointsClientCache) GetIndexed(name, key string) ([]*v1.Endpoints, error) { - var result []*v1.Endpoints - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Endpoints); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *endpointsClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type endpointsLifecycleDelegate struct { - create EndpointsChangeHandlerFunc - update EndpointsChangeHandlerFunc - remove EndpointsChangeHandlerFunc -} - -func (n *endpointsLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *endpointsLifecycleDelegate) Create(obj *v1.Endpoints) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *endpointsLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *endpointsLifecycleDelegate) Remove(obj *v1.Endpoints) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *endpointsLifecycleDelegate) Updated(obj *v1.Endpoints) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_endpoints_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_endpoints_lifecycle_adapter.go deleted file mode 100644 index f4cfe4817e..0000000000 --- a/types/apis/core/v1/zz_generated_endpoints_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type EndpointsLifecycle interface { - Create(obj *v1.Endpoints) (runtime.Object, error) - Remove(obj *v1.Endpoints) (runtime.Object, error) - Updated(obj *v1.Endpoints) (runtime.Object, error) -} - -type endpointsLifecycleAdapter struct { - lifecycle EndpointsLifecycle -} - -func (w *endpointsLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *endpointsLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *endpointsLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Endpoints)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *endpointsLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Endpoints)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *endpointsLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Endpoints)) - if o == nil { - return nil, err - } - return o, err -} - -func NewEndpointsLifecycleAdapter(name string, clusterScoped bool, client EndpointsInterface, l EndpointsLifecycle) EndpointsHandlerFunc { - adapter := &endpointsLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Endpoints) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/core/v1/zz_generated_k8s_client.go b/types/apis/core/v1/zz_generated_k8s_client.go deleted file mode 100644 index 02fe931aab..0000000000 --- a/types/apis/core/v1/zz_generated_k8s_client.go +++ /dev/null @@ -1,219 +0,0 @@ -package v1 - -import ( - "context" - "sync" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - - NodesGetter - ServiceAccountsGetter - EndpointsGetter - ServicesGetter - PodsGetter - ConfigMapsGetter -} - -type Clients struct { - Interface Interface - - Node NodeClient - ServiceAccount ServiceAccountClient - Endpoints EndpointsClient - Service ServiceClient - Pod PodClient - ConfigMap ConfigMapClient -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - - nodeControllers map[string]NodeController - serviceAccountControllers map[string]ServiceAccountController - endpointsControllers map[string]EndpointsController - serviceControllers map[string]ServiceController - podControllers map[string]PodController - configMapControllers map[string]ConfigMapController -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - - Node: &nodeClient2{ - iface: iface.Nodes(""), - }, - ServiceAccount: &serviceAccountClient2{ - iface: iface.ServiceAccounts(""), - }, - Endpoints: &endpointsClient2{ - iface: iface.Endpoints(""), - }, - Service: &serviceClient2{ - iface: iface.Services(""), - }, - Pod: &podClient2{ - iface: iface.Pods(""), - }, - ConfigMap: &configMapClient2{ - iface: iface.ConfigMaps(""), - }, - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - - nodeControllers: map[string]NodeController{}, - serviceAccountControllers: map[string]ServiceAccountController{}, - endpointsControllers: map[string]EndpointsController{}, - serviceControllers: map[string]ServiceController{}, - podControllers: map[string]PodController{}, - configMapControllers: map[string]ConfigMapController{}, - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -type NodesGetter interface { - Nodes(namespace string) NodeInterface -} - -func (c *Client) Nodes(namespace string) NodeInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &NodeResource, NodeGroupVersionKind, nodeFactory{}) - return &nodeClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type ServiceAccountsGetter interface { - ServiceAccounts(namespace string) ServiceAccountInterface -} - -func (c *Client) ServiceAccounts(namespace string) ServiceAccountInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ServiceAccountResource, ServiceAccountGroupVersionKind, serviceAccountFactory{}) - return &serviceAccountClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type EndpointsGetter interface { - Endpoints(namespace string) EndpointsInterface -} - -func (c *Client) Endpoints(namespace string) EndpointsInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &EndpointsResource, EndpointsGroupVersionKind, endpointsFactory{}) - return &endpointsClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type ServicesGetter interface { - Services(namespace string) ServiceInterface -} - -func (c *Client) Services(namespace string) ServiceInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ServiceResource, ServiceGroupVersionKind, serviceFactory{}) - return &serviceClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type PodsGetter interface { - Pods(namespace string) PodInterface -} - -func (c *Client) Pods(namespace string) PodInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &PodResource, PodGroupVersionKind, podFactory{}) - return &podClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type ConfigMapsGetter interface { - ConfigMaps(namespace string) ConfigMapInterface -} - -func (c *Client) ConfigMaps(namespace string) ConfigMapInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ConfigMapResource, ConfigMapGroupVersionKind, configMapFactory{}) - return &configMapClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} diff --git a/types/apis/core/v1/zz_generated_node_controller.go b/types/apis/core/v1/zz_generated_node_controller.go deleted file mode 100644 index 031977f018..0000000000 --- a/types/apis/core/v1/zz_generated_node_controller.go +++ /dev/null @@ -1,440 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - NodeGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Node", - } - NodeResource = metav1.APIResource{ - Name: "nodes", - SingularName: "node", - Namespaced: false, - Kind: NodeGroupVersionKind.Kind, - } -) - -func NewNode(namespace, name string, obj v1.Node) *v1.Node { - obj.APIVersion, obj.Kind = NodeGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type NodeList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Node -} - -type NodeHandlerFunc func(key string, obj *v1.Node) (runtime.Object, error) - -type NodeChangeHandlerFunc func(obj *v1.Node) (runtime.Object, error) - -type NodeLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Node, err error) - Get(namespace, name string) (*v1.Node, error) -} - -type NodeController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() NodeLister - AddHandler(ctx context.Context, name string, handler NodeHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler NodeHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type NodeInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Node) (*v1.Node, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) - Get(name string, opts metav1.GetOptions) (*v1.Node, error) - Update(*v1.Node) (*v1.Node, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*NodeList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() NodeController - AddHandler(ctx context.Context, name string, sync NodeHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle NodeLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync NodeHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle NodeLifecycle) -} - -type nodeLister struct { - controller *nodeController -} - -func (l *nodeLister) List(namespace string, selector labels.Selector) (ret []*v1.Node, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Node)) - }) - return -} - -func (l *nodeLister) Get(namespace, name string) (*v1.Node, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: NodeGroupVersionKind.Group, - Resource: "node", - }, key) - } - return obj.(*v1.Node), nil -} - -type nodeController struct { - controller.GenericController -} - -func (c *nodeController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *nodeController) Lister() NodeLister { - return &nodeLister{ - controller: c, - } -} - -func (c *nodeController) AddHandler(ctx context.Context, name string, handler NodeHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Node); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *nodeController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler NodeHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Node); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type nodeFactory struct { -} - -func (c nodeFactory) Object() runtime.Object { - return &v1.Node{} -} - -func (c nodeFactory) List() runtime.Object { - return &NodeList{} -} - -func (s *nodeClient) Controller() NodeController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.nodeControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(NodeGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &nodeController{ - GenericController: genericController, - } - - s.client.nodeControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type nodeClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller NodeController -} - -func (s *nodeClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *nodeClient) Create(o *v1.Node) (*v1.Node, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Node), err -} - -func (s *nodeClient) Get(name string, opts metav1.GetOptions) (*v1.Node, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Node), err -} - -func (s *nodeClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Node), err -} - -func (s *nodeClient) Update(o *v1.Node) (*v1.Node, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Node), err -} - -func (s *nodeClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *nodeClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *nodeClient) List(opts metav1.ListOptions) (*NodeList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*NodeList), err -} - -func (s *nodeClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *nodeClient) Patch(o *v1.Node, patchType types.PatchType, data []byte, subresources ...string) (*v1.Node, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Node), err -} - -func (s *nodeClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *nodeClient) AddHandler(ctx context.Context, name string, sync NodeHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *nodeClient) AddLifecycle(ctx context.Context, name string, lifecycle NodeLifecycle) { - sync := NewNodeLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *nodeClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync NodeHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *nodeClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle NodeLifecycle) { - sync := NewNodeLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type NodeIndexer func(obj *v1.Node) ([]string, error) - -type NodeClientCache interface { - Get(namespace, name string) (*v1.Node, error) - List(namespace string, selector labels.Selector) ([]*v1.Node, error) - - Index(name string, indexer NodeIndexer) - GetIndexed(name, key string) ([]*v1.Node, error) -} - -type NodeClient interface { - Create(*v1.Node) (*v1.Node, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) - Update(*v1.Node) (*v1.Node, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*NodeList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() NodeClientCache - - OnCreate(ctx context.Context, name string, sync NodeChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync NodeChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync NodeChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() NodeInterface -} - -type nodeClientCache struct { - client *nodeClient2 -} - -type nodeClient2 struct { - iface NodeInterface - controller NodeController -} - -func (n *nodeClient2) Interface() NodeInterface { - return n.iface -} - -func (n *nodeClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *nodeClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *nodeClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *nodeClient2) Create(obj *v1.Node) (*v1.Node, error) { - return n.iface.Create(obj) -} - -func (n *nodeClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Node, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *nodeClient2) Update(obj *v1.Node) (*v1.Node, error) { - return n.iface.Update(obj) -} - -func (n *nodeClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *nodeClient2) List(namespace string, opts metav1.ListOptions) (*NodeList, error) { - return n.iface.List(opts) -} - -func (n *nodeClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *nodeClientCache) Get(namespace, name string) (*v1.Node, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *nodeClientCache) List(namespace string, selector labels.Selector) ([]*v1.Node, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *nodeClient2) Cache() NodeClientCache { - n.loadController() - return &nodeClientCache{ - client: n, - } -} - -func (n *nodeClient2) OnCreate(ctx context.Context, name string, sync NodeChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &nodeLifecycleDelegate{create: sync}) -} - -func (n *nodeClient2) OnChange(ctx context.Context, name string, sync NodeChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &nodeLifecycleDelegate{update: sync}) -} - -func (n *nodeClient2) OnRemove(ctx context.Context, name string, sync NodeChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &nodeLifecycleDelegate{remove: sync}) -} - -func (n *nodeClientCache) Index(name string, indexer NodeIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Node); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *nodeClientCache) GetIndexed(name, key string) ([]*v1.Node, error) { - var result []*v1.Node - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Node); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *nodeClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type nodeLifecycleDelegate struct { - create NodeChangeHandlerFunc - update NodeChangeHandlerFunc - remove NodeChangeHandlerFunc -} - -func (n *nodeLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *nodeLifecycleDelegate) Create(obj *v1.Node) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *nodeLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *nodeLifecycleDelegate) Remove(obj *v1.Node) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *nodeLifecycleDelegate) Updated(obj *v1.Node) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go deleted file mode 100644 index 9cd3306a53..0000000000 --- a/types/apis/core/v1/zz_generated_node_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type NodeLifecycle interface { - Create(obj *v1.Node) (runtime.Object, error) - Remove(obj *v1.Node) (runtime.Object, error) - Updated(obj *v1.Node) (runtime.Object, error) -} - -type nodeLifecycleAdapter struct { - lifecycle NodeLifecycle -} - -func (w *nodeLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *nodeLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *nodeLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Node)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *nodeLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Node)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *nodeLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Node)) - if o == nil { - return nil, err - } - return o, err -} - -func NewNodeLifecycleAdapter(name string, clusterScoped bool, client NodeInterface, l NodeLifecycle) NodeHandlerFunc { - adapter := &nodeLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Node) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/core/v1/zz_generated_pod_controller.go b/types/apis/core/v1/zz_generated_pod_controller.go deleted file mode 100644 index 421678df19..0000000000 --- a/types/apis/core/v1/zz_generated_pod_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - PodGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Pod", - } - PodResource = metav1.APIResource{ - Name: "pods", - SingularName: "pod", - Namespaced: true, - - Kind: PodGroupVersionKind.Kind, - } -) - -func NewPod(namespace, name string, obj v1.Pod) *v1.Pod { - obj.APIVersion, obj.Kind = PodGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type PodList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Pod -} - -type PodHandlerFunc func(key string, obj *v1.Pod) (runtime.Object, error) - -type PodChangeHandlerFunc func(obj *v1.Pod) (runtime.Object, error) - -type PodLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Pod, err error) - Get(namespace, name string) (*v1.Pod, error) -} - -type PodController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() PodLister - AddHandler(ctx context.Context, name string, handler PodHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler PodHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type PodInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Pod) (*v1.Pod, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) - Get(name string, opts metav1.GetOptions) (*v1.Pod, error) - Update(*v1.Pod) (*v1.Pod, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*PodList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() PodController - AddHandler(ctx context.Context, name string, sync PodHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle PodLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync PodHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle PodLifecycle) -} - -type podLister struct { - controller *podController -} - -func (l *podLister) List(namespace string, selector labels.Selector) (ret []*v1.Pod, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Pod)) - }) - return -} - -func (l *podLister) Get(namespace, name string) (*v1.Pod, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: PodGroupVersionKind.Group, - Resource: "pod", - }, key) - } - return obj.(*v1.Pod), nil -} - -type podController struct { - controller.GenericController -} - -func (c *podController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *podController) Lister() PodLister { - return &podLister{ - controller: c, - } -} - -func (c *podController) AddHandler(ctx context.Context, name string, handler PodHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Pod); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *podController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler PodHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Pod); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type podFactory struct { -} - -func (c podFactory) Object() runtime.Object { - return &v1.Pod{} -} - -func (c podFactory) List() runtime.Object { - return &PodList{} -} - -func (s *podClient) Controller() PodController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.podControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(PodGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &podController{ - GenericController: genericController, - } - - s.client.podControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type podClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller PodController -} - -func (s *podClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *podClient) Create(o *v1.Pod) (*v1.Pod, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Pod), err -} - -func (s *podClient) Get(name string, opts metav1.GetOptions) (*v1.Pod, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Pod), err -} - -func (s *podClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Pod), err -} - -func (s *podClient) Update(o *v1.Pod) (*v1.Pod, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Pod), err -} - -func (s *podClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *podClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *podClient) List(opts metav1.ListOptions) (*PodList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*PodList), err -} - -func (s *podClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *podClient) Patch(o *v1.Pod, patchType types.PatchType, data []byte, subresources ...string) (*v1.Pod, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Pod), err -} - -func (s *podClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *podClient) AddHandler(ctx context.Context, name string, sync PodHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *podClient) AddLifecycle(ctx context.Context, name string, lifecycle PodLifecycle) { - sync := NewPodLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *podClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync PodHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *podClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle PodLifecycle) { - sync := NewPodLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type PodIndexer func(obj *v1.Pod) ([]string, error) - -type PodClientCache interface { - Get(namespace, name string) (*v1.Pod, error) - List(namespace string, selector labels.Selector) ([]*v1.Pod, error) - - Index(name string, indexer PodIndexer) - GetIndexed(name, key string) ([]*v1.Pod, error) -} - -type PodClient interface { - Create(*v1.Pod) (*v1.Pod, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) - Update(*v1.Pod) (*v1.Pod, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*PodList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() PodClientCache - - OnCreate(ctx context.Context, name string, sync PodChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync PodChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync PodChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() PodInterface -} - -type podClientCache struct { - client *podClient2 -} - -type podClient2 struct { - iface PodInterface - controller PodController -} - -func (n *podClient2) Interface() PodInterface { - return n.iface -} - -func (n *podClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *podClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *podClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *podClient2) Create(obj *v1.Pod) (*v1.Pod, error) { - return n.iface.Create(obj) -} - -func (n *podClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Pod, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *podClient2) Update(obj *v1.Pod) (*v1.Pod, error) { - return n.iface.Update(obj) -} - -func (n *podClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *podClient2) List(namespace string, opts metav1.ListOptions) (*PodList, error) { - return n.iface.List(opts) -} - -func (n *podClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *podClientCache) Get(namespace, name string) (*v1.Pod, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *podClientCache) List(namespace string, selector labels.Selector) ([]*v1.Pod, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *podClient2) Cache() PodClientCache { - n.loadController() - return &podClientCache{ - client: n, - } -} - -func (n *podClient2) OnCreate(ctx context.Context, name string, sync PodChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &podLifecycleDelegate{create: sync}) -} - -func (n *podClient2) OnChange(ctx context.Context, name string, sync PodChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &podLifecycleDelegate{update: sync}) -} - -func (n *podClient2) OnRemove(ctx context.Context, name string, sync PodChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &podLifecycleDelegate{remove: sync}) -} - -func (n *podClientCache) Index(name string, indexer PodIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Pod); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *podClientCache) GetIndexed(name, key string) ([]*v1.Pod, error) { - var result []*v1.Pod - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Pod); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *podClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type podLifecycleDelegate struct { - create PodChangeHandlerFunc - update PodChangeHandlerFunc - remove PodChangeHandlerFunc -} - -func (n *podLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *podLifecycleDelegate) Create(obj *v1.Pod) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *podLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *podLifecycleDelegate) Remove(obj *v1.Pod) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *podLifecycleDelegate) Updated(obj *v1.Pod) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go deleted file mode 100644 index aa761dedcd..0000000000 --- a/types/apis/core/v1/zz_generated_pod_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type PodLifecycle interface { - Create(obj *v1.Pod) (runtime.Object, error) - Remove(obj *v1.Pod) (runtime.Object, error) - Updated(obj *v1.Pod) (runtime.Object, error) -} - -type podLifecycleAdapter struct { - lifecycle PodLifecycle -} - -func (w *podLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *podLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *podLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Pod)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *podLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Pod)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *podLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Pod)) - if o == nil { - return nil, err - } - return o, err -} - -func NewPodLifecycleAdapter(name string, clusterScoped bool, client PodInterface, l PodLifecycle) PodHandlerFunc { - adapter := &podLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Pod) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/core/v1/zz_generated_scheme.go b/types/apis/core/v1/zz_generated_scheme.go deleted file mode 100644 index b81a8d382a..0000000000 --- a/types/apis/core/v1/zz_generated_scheme.go +++ /dev/null @@ -1,44 +0,0 @@ -package v1 - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "" - Version = "v1" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - - &NodeList{}, - &ServiceAccountList{}, - &EndpointsList{}, - &ServiceList{}, - &PodList{}, - &ConfigMapList{}, - ) - return nil -} diff --git a/types/apis/core/v1/zz_generated_service_account_controller.go b/types/apis/core/v1/zz_generated_service_account_controller.go deleted file mode 100644 index dbeb3bae53..0000000000 --- a/types/apis/core/v1/zz_generated_service_account_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - ServiceAccountGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "ServiceAccount", - } - ServiceAccountResource = metav1.APIResource{ - Name: "serviceaccounts", - SingularName: "serviceaccount", - Namespaced: true, - - Kind: ServiceAccountGroupVersionKind.Kind, - } -) - -func NewServiceAccount(namespace, name string, obj v1.ServiceAccount) *v1.ServiceAccount { - obj.APIVersion, obj.Kind = ServiceAccountGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type ServiceAccountList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.ServiceAccount -} - -type ServiceAccountHandlerFunc func(key string, obj *v1.ServiceAccount) (runtime.Object, error) - -type ServiceAccountChangeHandlerFunc func(obj *v1.ServiceAccount) (runtime.Object, error) - -type ServiceAccountLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.ServiceAccount, err error) - Get(namespace, name string) (*v1.ServiceAccount, error) -} - -type ServiceAccountController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() ServiceAccountLister - AddHandler(ctx context.Context, name string, handler ServiceAccountHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ServiceAccountHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type ServiceAccountInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.ServiceAccount) (*v1.ServiceAccount, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) - Get(name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) - Update(*v1.ServiceAccount) (*v1.ServiceAccount, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*ServiceAccountList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() ServiceAccountController - AddHandler(ctx context.Context, name string, sync ServiceAccountHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle ServiceAccountLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceAccountHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceAccountLifecycle) -} - -type serviceAccountLister struct { - controller *serviceAccountController -} - -func (l *serviceAccountLister) List(namespace string, selector labels.Selector) (ret []*v1.ServiceAccount, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.ServiceAccount)) - }) - return -} - -func (l *serviceAccountLister) Get(namespace, name string) (*v1.ServiceAccount, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: ServiceAccountGroupVersionKind.Group, - Resource: "serviceAccount", - }, key) - } - return obj.(*v1.ServiceAccount), nil -} - -type serviceAccountController struct { - controller.GenericController -} - -func (c *serviceAccountController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *serviceAccountController) Lister() ServiceAccountLister { - return &serviceAccountLister{ - controller: c, - } -} - -func (c *serviceAccountController) AddHandler(ctx context.Context, name string, handler ServiceAccountHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ServiceAccount); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *serviceAccountController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ServiceAccountHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ServiceAccount); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type serviceAccountFactory struct { -} - -func (c serviceAccountFactory) Object() runtime.Object { - return &v1.ServiceAccount{} -} - -func (c serviceAccountFactory) List() runtime.Object { - return &ServiceAccountList{} -} - -func (s *serviceAccountClient) Controller() ServiceAccountController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.serviceAccountControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(ServiceAccountGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &serviceAccountController{ - GenericController: genericController, - } - - s.client.serviceAccountControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type serviceAccountClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller ServiceAccountController -} - -func (s *serviceAccountClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *serviceAccountClient) Create(o *v1.ServiceAccount) (*v1.ServiceAccount, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.ServiceAccount), err -} - -func (s *serviceAccountClient) Get(name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.ServiceAccount), err -} - -func (s *serviceAccountClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.ServiceAccount), err -} - -func (s *serviceAccountClient) Update(o *v1.ServiceAccount) (*v1.ServiceAccount, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.ServiceAccount), err -} - -func (s *serviceAccountClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *serviceAccountClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *serviceAccountClient) List(opts metav1.ListOptions) (*ServiceAccountList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*ServiceAccountList), err -} - -func (s *serviceAccountClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *serviceAccountClient) Patch(o *v1.ServiceAccount, patchType types.PatchType, data []byte, subresources ...string) (*v1.ServiceAccount, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.ServiceAccount), err -} - -func (s *serviceAccountClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *serviceAccountClient) AddHandler(ctx context.Context, name string, sync ServiceAccountHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *serviceAccountClient) AddLifecycle(ctx context.Context, name string, lifecycle ServiceAccountLifecycle) { - sync := NewServiceAccountLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *serviceAccountClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceAccountHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *serviceAccountClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceAccountLifecycle) { - sync := NewServiceAccountLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type ServiceAccountIndexer func(obj *v1.ServiceAccount) ([]string, error) - -type ServiceAccountClientCache interface { - Get(namespace, name string) (*v1.ServiceAccount, error) - List(namespace string, selector labels.Selector) ([]*v1.ServiceAccount, error) - - Index(name string, indexer ServiceAccountIndexer) - GetIndexed(name, key string) ([]*v1.ServiceAccount, error) -} - -type ServiceAccountClient interface { - Create(*v1.ServiceAccount) (*v1.ServiceAccount, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) - Update(*v1.ServiceAccount) (*v1.ServiceAccount, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*ServiceAccountList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() ServiceAccountClientCache - - OnCreate(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() ServiceAccountInterface -} - -type serviceAccountClientCache struct { - client *serviceAccountClient2 -} - -type serviceAccountClient2 struct { - iface ServiceAccountInterface - controller ServiceAccountController -} - -func (n *serviceAccountClient2) Interface() ServiceAccountInterface { - return n.iface -} - -func (n *serviceAccountClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *serviceAccountClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *serviceAccountClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *serviceAccountClient2) Create(obj *v1.ServiceAccount) (*v1.ServiceAccount, error) { - return n.iface.Create(obj) -} - -func (n *serviceAccountClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.ServiceAccount, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *serviceAccountClient2) Update(obj *v1.ServiceAccount) (*v1.ServiceAccount, error) { - return n.iface.Update(obj) -} - -func (n *serviceAccountClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *serviceAccountClient2) List(namespace string, opts metav1.ListOptions) (*ServiceAccountList, error) { - return n.iface.List(opts) -} - -func (n *serviceAccountClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *serviceAccountClientCache) Get(namespace, name string) (*v1.ServiceAccount, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *serviceAccountClientCache) List(namespace string, selector labels.Selector) ([]*v1.ServiceAccount, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *serviceAccountClient2) Cache() ServiceAccountClientCache { - n.loadController() - return &serviceAccountClientCache{ - client: n, - } -} - -func (n *serviceAccountClient2) OnCreate(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &serviceAccountLifecycleDelegate{create: sync}) -} - -func (n *serviceAccountClient2) OnChange(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &serviceAccountLifecycleDelegate{update: sync}) -} - -func (n *serviceAccountClient2) OnRemove(ctx context.Context, name string, sync ServiceAccountChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &serviceAccountLifecycleDelegate{remove: sync}) -} - -func (n *serviceAccountClientCache) Index(name string, indexer ServiceAccountIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.ServiceAccount); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *serviceAccountClientCache) GetIndexed(name, key string) ([]*v1.ServiceAccount, error) { - var result []*v1.ServiceAccount - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.ServiceAccount); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *serviceAccountClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type serviceAccountLifecycleDelegate struct { - create ServiceAccountChangeHandlerFunc - update ServiceAccountChangeHandlerFunc - remove ServiceAccountChangeHandlerFunc -} - -func (n *serviceAccountLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *serviceAccountLifecycleDelegate) Create(obj *v1.ServiceAccount) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *serviceAccountLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *serviceAccountLifecycleDelegate) Remove(obj *v1.ServiceAccount) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *serviceAccountLifecycleDelegate) Updated(obj *v1.ServiceAccount) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_service_account_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_service_account_lifecycle_adapter.go deleted file mode 100644 index ca281c4fb5..0000000000 --- a/types/apis/core/v1/zz_generated_service_account_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type ServiceAccountLifecycle interface { - Create(obj *v1.ServiceAccount) (runtime.Object, error) - Remove(obj *v1.ServiceAccount) (runtime.Object, error) - Updated(obj *v1.ServiceAccount) (runtime.Object, error) -} - -type serviceAccountLifecycleAdapter struct { - lifecycle ServiceAccountLifecycle -} - -func (w *serviceAccountLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *serviceAccountLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *serviceAccountLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.ServiceAccount)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *serviceAccountLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.ServiceAccount)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *serviceAccountLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.ServiceAccount)) - if o == nil { - return nil, err - } - return o, err -} - -func NewServiceAccountLifecycleAdapter(name string, clusterScoped bool, client ServiceAccountInterface, l ServiceAccountLifecycle) ServiceAccountHandlerFunc { - adapter := &serviceAccountLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.ServiceAccount) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/core/v1/zz_generated_service_controller.go b/types/apis/core/v1/zz_generated_service_controller.go deleted file mode 100644 index 36153efab7..0000000000 --- a/types/apis/core/v1/zz_generated_service_controller.go +++ /dev/null @@ -1,441 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - ServiceGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Service", - } - ServiceResource = metav1.APIResource{ - Name: "services", - SingularName: "service", - Namespaced: true, - - Kind: ServiceGroupVersionKind.Kind, - } -) - -func NewService(namespace, name string, obj v1.Service) *v1.Service { - obj.APIVersion, obj.Kind = ServiceGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type ServiceList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.Service -} - -type ServiceHandlerFunc func(key string, obj *v1.Service) (runtime.Object, error) - -type ServiceChangeHandlerFunc func(obj *v1.Service) (runtime.Object, error) - -type ServiceLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.Service, err error) - Get(namespace, name string) (*v1.Service, error) -} - -type ServiceController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() ServiceLister - AddHandler(ctx context.Context, name string, handler ServiceHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ServiceHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type ServiceInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.Service) (*v1.Service, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) - Get(name string, opts metav1.GetOptions) (*v1.Service, error) - Update(*v1.Service) (*v1.Service, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*ServiceList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() ServiceController - AddHandler(ctx context.Context, name string, sync ServiceHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle ServiceLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceLifecycle) -} - -type serviceLister struct { - controller *serviceController -} - -func (l *serviceLister) List(namespace string, selector labels.Selector) (ret []*v1.Service, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.Service)) - }) - return -} - -func (l *serviceLister) Get(namespace, name string) (*v1.Service, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: ServiceGroupVersionKind.Group, - Resource: "service", - }, key) - } - return obj.(*v1.Service), nil -} - -type serviceController struct { - controller.GenericController -} - -func (c *serviceController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *serviceController) Lister() ServiceLister { - return &serviceLister{ - controller: c, - } -} - -func (c *serviceController) AddHandler(ctx context.Context, name string, handler ServiceHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Service); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *serviceController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ServiceHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.Service); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type serviceFactory struct { -} - -func (c serviceFactory) Object() runtime.Object { - return &v1.Service{} -} - -func (c serviceFactory) List() runtime.Object { - return &ServiceList{} -} - -func (s *serviceClient) Controller() ServiceController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.serviceControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(ServiceGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &serviceController{ - GenericController: genericController, - } - - s.client.serviceControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type serviceClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller ServiceController -} - -func (s *serviceClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *serviceClient) Create(o *v1.Service) (*v1.Service, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.Service), err -} - -func (s *serviceClient) Get(name string, opts metav1.GetOptions) (*v1.Service, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.Service), err -} - -func (s *serviceClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.Service), err -} - -func (s *serviceClient) Update(o *v1.Service) (*v1.Service, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.Service), err -} - -func (s *serviceClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *serviceClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *serviceClient) List(opts metav1.ListOptions) (*ServiceList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*ServiceList), err -} - -func (s *serviceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *serviceClient) Patch(o *v1.Service, patchType types.PatchType, data []byte, subresources ...string) (*v1.Service, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.Service), err -} - -func (s *serviceClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *serviceClient) AddHandler(ctx context.Context, name string, sync ServiceHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *serviceClient) AddLifecycle(ctx context.Context, name string, lifecycle ServiceLifecycle) { - sync := NewServiceLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *serviceClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ServiceHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *serviceClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ServiceLifecycle) { - sync := NewServiceLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type ServiceIndexer func(obj *v1.Service) ([]string, error) - -type ServiceClientCache interface { - Get(namespace, name string) (*v1.Service, error) - List(namespace string, selector labels.Selector) ([]*v1.Service, error) - - Index(name string, indexer ServiceIndexer) - GetIndexed(name, key string) ([]*v1.Service, error) -} - -type ServiceClient interface { - Create(*v1.Service) (*v1.Service, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) - Update(*v1.Service) (*v1.Service, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*ServiceList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() ServiceClientCache - - OnCreate(ctx context.Context, name string, sync ServiceChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync ServiceChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync ServiceChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() ServiceInterface -} - -type serviceClientCache struct { - client *serviceClient2 -} - -type serviceClient2 struct { - iface ServiceInterface - controller ServiceController -} - -func (n *serviceClient2) Interface() ServiceInterface { - return n.iface -} - -func (n *serviceClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *serviceClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *serviceClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *serviceClient2) Create(obj *v1.Service) (*v1.Service, error) { - return n.iface.Create(obj) -} - -func (n *serviceClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.Service, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *serviceClient2) Update(obj *v1.Service) (*v1.Service, error) { - return n.iface.Update(obj) -} - -func (n *serviceClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *serviceClient2) List(namespace string, opts metav1.ListOptions) (*ServiceList, error) { - return n.iface.List(opts) -} - -func (n *serviceClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *serviceClientCache) Get(namespace, name string) (*v1.Service, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *serviceClientCache) List(namespace string, selector labels.Selector) ([]*v1.Service, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *serviceClient2) Cache() ServiceClientCache { - n.loadController() - return &serviceClientCache{ - client: n, - } -} - -func (n *serviceClient2) OnCreate(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &serviceLifecycleDelegate{create: sync}) -} - -func (n *serviceClient2) OnChange(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &serviceLifecycleDelegate{update: sync}) -} - -func (n *serviceClient2) OnRemove(ctx context.Context, name string, sync ServiceChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &serviceLifecycleDelegate{remove: sync}) -} - -func (n *serviceClientCache) Index(name string, indexer ServiceIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.Service); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *serviceClientCache) GetIndexed(name, key string) ([]*v1.Service, error) { - var result []*v1.Service - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.Service); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *serviceClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type serviceLifecycleDelegate struct { - create ServiceChangeHandlerFunc - update ServiceChangeHandlerFunc - remove ServiceChangeHandlerFunc -} - -func (n *serviceLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *serviceLifecycleDelegate) Create(obj *v1.Service) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *serviceLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *serviceLifecycleDelegate) Remove(obj *v1.Service) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *serviceLifecycleDelegate) Updated(obj *v1.Service) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go b/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go deleted file mode 100644 index 37a28afd91..0000000000 --- a/types/apis/core/v1/zz_generated_service_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type ServiceLifecycle interface { - Create(obj *v1.Service) (runtime.Object, error) - Remove(obj *v1.Service) (runtime.Object, error) - Updated(obj *v1.Service) (runtime.Object, error) -} - -type serviceLifecycleAdapter struct { - lifecycle ServiceLifecycle -} - -func (w *serviceLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *serviceLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *serviceLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.Service)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *serviceLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.Service)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *serviceLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.Service)) - if o == nil { - return nil, err - } - return o, err -} - -func NewServiceLifecycleAdapter(name string, clusterScoped bool, client ServiceInterface, l ServiceLifecycle) ServiceHandlerFunc { - adapter := &serviceLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.Service) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/k3s.cattle.io/v1/schema.go b/types/apis/k3s.cattle.io/v1/schema.go deleted file mode 100644 index 0da5e105ce..0000000000 --- a/types/apis/k3s.cattle.io/v1/schema.go +++ /dev/null @@ -1,19 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/factory" -) - -var ( - APIVersion = types.APIVersion{ - Version: "v1", - Group: "k3s.cattle.io", - Path: "/v1-k3s", - } - - Schemas = factory.Schemas(&APIVersion). - MustImport(&APIVersion, Addon{}). - MustImport(&APIVersion, HelmChart{}). - MustImport(&APIVersion, ListenerConfig{}) -) diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_addon_controller.go b/types/apis/k3s.cattle.io/v1/zz_generated_addon_controller.go deleted file mode 100644 index 7525837675..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_addon_controller.go +++ /dev/null @@ -1,440 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - AddonGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "Addon", - } - AddonResource = metav1.APIResource{ - Name: "addons", - SingularName: "addon", - Namespaced: true, - - Kind: AddonGroupVersionKind.Kind, - } -) - -func NewAddon(namespace, name string, obj Addon) *Addon { - obj.APIVersion, obj.Kind = AddonGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type AddonList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Addon -} - -type AddonHandlerFunc func(key string, obj *Addon) (runtime.Object, error) - -type AddonChangeHandlerFunc func(obj *Addon) (runtime.Object, error) - -type AddonLister interface { - List(namespace string, selector labels.Selector) (ret []*Addon, err error) - Get(namespace, name string) (*Addon, error) -} - -type AddonController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() AddonLister - AddHandler(ctx context.Context, name string, handler AddonHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler AddonHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type AddonInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*Addon) (*Addon, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*Addon, error) - Get(name string, opts metav1.GetOptions) (*Addon, error) - Update(*Addon) (*Addon, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*AddonList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() AddonController - AddHandler(ctx context.Context, name string, sync AddonHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle AddonLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync AddonHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle AddonLifecycle) -} - -type addonLister struct { - controller *addonController -} - -func (l *addonLister) List(namespace string, selector labels.Selector) (ret []*Addon, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*Addon)) - }) - return -} - -func (l *addonLister) Get(namespace, name string) (*Addon, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: AddonGroupVersionKind.Group, - Resource: "addon", - }, key) - } - return obj.(*Addon), nil -} - -type addonController struct { - controller.GenericController -} - -func (c *addonController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *addonController) Lister() AddonLister { - return &addonLister{ - controller: c, - } -} - -func (c *addonController) AddHandler(ctx context.Context, name string, handler AddonHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*Addon); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *addonController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler AddonHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*Addon); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type addonFactory struct { -} - -func (c addonFactory) Object() runtime.Object { - return &Addon{} -} - -func (c addonFactory) List() runtime.Object { - return &AddonList{} -} - -func (s *addonClient) Controller() AddonController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.addonControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(AddonGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &addonController{ - GenericController: genericController, - } - - s.client.addonControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type addonClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller AddonController -} - -func (s *addonClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *addonClient) Create(o *Addon) (*Addon, error) { - obj, err := s.objectClient.Create(o) - return obj.(*Addon), err -} - -func (s *addonClient) Get(name string, opts metav1.GetOptions) (*Addon, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*Addon), err -} - -func (s *addonClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*Addon, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*Addon), err -} - -func (s *addonClient) Update(o *Addon) (*Addon, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*Addon), err -} - -func (s *addonClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *addonClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *addonClient) List(opts metav1.ListOptions) (*AddonList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*AddonList), err -} - -func (s *addonClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *addonClient) Patch(o *Addon, patchType types.PatchType, data []byte, subresources ...string) (*Addon, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*Addon), err -} - -func (s *addonClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *addonClient) AddHandler(ctx context.Context, name string, sync AddonHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *addonClient) AddLifecycle(ctx context.Context, name string, lifecycle AddonLifecycle) { - sync := NewAddonLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *addonClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync AddonHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *addonClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle AddonLifecycle) { - sync := NewAddonLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type AddonIndexer func(obj *Addon) ([]string, error) - -type AddonClientCache interface { - Get(namespace, name string) (*Addon, error) - List(namespace string, selector labels.Selector) ([]*Addon, error) - - Index(name string, indexer AddonIndexer) - GetIndexed(name, key string) ([]*Addon, error) -} - -type AddonClient interface { - Create(*Addon) (*Addon, error) - Get(namespace, name string, opts metav1.GetOptions) (*Addon, error) - Update(*Addon) (*Addon, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*AddonList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() AddonClientCache - - OnCreate(ctx context.Context, name string, sync AddonChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync AddonChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync AddonChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() AddonInterface -} - -type addonClientCache struct { - client *addonClient2 -} - -type addonClient2 struct { - iface AddonInterface - controller AddonController -} - -func (n *addonClient2) Interface() AddonInterface { - return n.iface -} - -func (n *addonClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *addonClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *addonClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *addonClient2) Create(obj *Addon) (*Addon, error) { - return n.iface.Create(obj) -} - -func (n *addonClient2) Get(namespace, name string, opts metav1.GetOptions) (*Addon, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *addonClient2) Update(obj *Addon) (*Addon, error) { - return n.iface.Update(obj) -} - -func (n *addonClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *addonClient2) List(namespace string, opts metav1.ListOptions) (*AddonList, error) { - return n.iface.List(opts) -} - -func (n *addonClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *addonClientCache) Get(namespace, name string) (*Addon, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *addonClientCache) List(namespace string, selector labels.Selector) ([]*Addon, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *addonClient2) Cache() AddonClientCache { - n.loadController() - return &addonClientCache{ - client: n, - } -} - -func (n *addonClient2) OnCreate(ctx context.Context, name string, sync AddonChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &addonLifecycleDelegate{create: sync}) -} - -func (n *addonClient2) OnChange(ctx context.Context, name string, sync AddonChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &addonLifecycleDelegate{update: sync}) -} - -func (n *addonClient2) OnRemove(ctx context.Context, name string, sync AddonChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &addonLifecycleDelegate{remove: sync}) -} - -func (n *addonClientCache) Index(name string, indexer AddonIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*Addon); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *addonClientCache) GetIndexed(name, key string) ([]*Addon, error) { - var result []*Addon - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*Addon); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *addonClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type addonLifecycleDelegate struct { - create AddonChangeHandlerFunc - update AddonChangeHandlerFunc - remove AddonChangeHandlerFunc -} - -func (n *addonLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *addonLifecycleDelegate) Create(obj *Addon) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *addonLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *addonLifecycleDelegate) Remove(obj *Addon) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *addonLifecycleDelegate) Updated(obj *Addon) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_addon_lifecycle_adapter.go b/types/apis/k3s.cattle.io/v1/zz_generated_addon_lifecycle_adapter.go deleted file mode 100644 index 9dc1513d2f..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_addon_lifecycle_adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - "k8s.io/apimachinery/pkg/runtime" -) - -type AddonLifecycle interface { - Create(obj *Addon) (runtime.Object, error) - Remove(obj *Addon) (runtime.Object, error) - Updated(obj *Addon) (runtime.Object, error) -} - -type addonLifecycleAdapter struct { - lifecycle AddonLifecycle -} - -func (w *addonLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *addonLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *addonLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*Addon)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *addonLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*Addon)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *addonLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*Addon)) - if o == nil { - return nil, err - } - return o, err -} - -func NewAddonLifecycleAdapter(name string, clusterScoped bool, client AddonInterface, l AddonLifecycle) AddonHandlerFunc { - adapter := &addonLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *Addon) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go b/types/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go deleted file mode 100644 index c8f79398f5..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go +++ /dev/null @@ -1,268 +0,0 @@ -package v1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - intstr "k8s.io/apimachinery/pkg/util/intstr" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Addon) DeepCopyInto(out *Addon) { - *out = *in - out.Namespaced = in.Namespaced - 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 Addon. -func (in *Addon) DeepCopy() *Addon { - if in == nil { - return nil - } - out := new(Addon) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Addon) 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 *AddonList) DeepCopyInto(out *AddonList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Addon, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonList. -func (in *AddonList) DeepCopy() *AddonList { - if in == nil { - return nil - } - out := new(AddonList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AddonList) 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 *AddonSpec) DeepCopyInto(out *AddonSpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonSpec. -func (in *AddonSpec) DeepCopy() *AddonSpec { - if in == nil { - return nil - } - out := new(AddonSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AddonStatus) DeepCopyInto(out *AddonStatus) { - *out = *in - if in.GVKs != nil { - in, out := &in.GVKs, &out.GVKs - *out = make([]schema.GroupVersionKind, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonStatus. -func (in *AddonStatus) DeepCopy() *AddonStatus { - if in == nil { - return nil - } - out := new(AddonStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HelmChart) DeepCopyInto(out *HelmChart) { - *out = *in - out.Namespaced = in.Namespaced - 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 HelmChart. -func (in *HelmChart) DeepCopy() *HelmChart { - if in == nil { - return nil - } - out := new(HelmChart) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *HelmChart) 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 *HelmChartList) DeepCopyInto(out *HelmChartList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]HelmChart, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartList. -func (in *HelmChartList) DeepCopy() *HelmChartList { - if in == nil { - return nil - } - out := new(HelmChartList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *HelmChartList) 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 *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) { - *out = *in - if in.Set != nil { - in, out := &in.Set, &out.Set - *out = make(map[string]intstr.IntOrString, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartSpec. -func (in *HelmChartSpec) DeepCopy() *HelmChartSpec { - if in == nil { - return nil - } - out := new(HelmChartSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HelmChartStatus) DeepCopyInto(out *HelmChartStatus) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartStatus. -func (in *HelmChartStatus) DeepCopy() *HelmChartStatus { - if in == nil { - return nil - } - out := new(HelmChartStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListenerConfig) DeepCopyInto(out *ListenerConfig) { - *out = *in - out.Namespaced = in.Namespaced - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfig. -func (in *ListenerConfig) DeepCopy() *ListenerConfig { - if in == nil { - return nil - } - out := new(ListenerConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListenerConfig) 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 *ListenerConfigList) DeepCopyInto(out *ListenerConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ListenerConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfigList. -func (in *ListenerConfigList) DeepCopy() *ListenerConfigList { - if in == nil { - return nil - } - out := new(ListenerConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListenerConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_controller.go b/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_controller.go deleted file mode 100644 index 57074d2f01..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_controller.go +++ /dev/null @@ -1,440 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - HelmChartGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "HelmChart", - } - HelmChartResource = metav1.APIResource{ - Name: "helmcharts", - SingularName: "helmchart", - Namespaced: true, - - Kind: HelmChartGroupVersionKind.Kind, - } -) - -func NewHelmChart(namespace, name string, obj HelmChart) *HelmChart { - obj.APIVersion, obj.Kind = HelmChartGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type HelmChartList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []HelmChart -} - -type HelmChartHandlerFunc func(key string, obj *HelmChart) (runtime.Object, error) - -type HelmChartChangeHandlerFunc func(obj *HelmChart) (runtime.Object, error) - -type HelmChartLister interface { - List(namespace string, selector labels.Selector) (ret []*HelmChart, err error) - Get(namespace, name string) (*HelmChart, error) -} - -type HelmChartController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() HelmChartLister - AddHandler(ctx context.Context, name string, handler HelmChartHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler HelmChartHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type HelmChartInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*HelmChart) (*HelmChart, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*HelmChart, error) - Get(name string, opts metav1.GetOptions) (*HelmChart, error) - Update(*HelmChart) (*HelmChart, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*HelmChartList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() HelmChartController - AddHandler(ctx context.Context, name string, sync HelmChartHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle HelmChartLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync HelmChartHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle HelmChartLifecycle) -} - -type helmChartLister struct { - controller *helmChartController -} - -func (l *helmChartLister) List(namespace string, selector labels.Selector) (ret []*HelmChart, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*HelmChart)) - }) - return -} - -func (l *helmChartLister) Get(namespace, name string) (*HelmChart, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: HelmChartGroupVersionKind.Group, - Resource: "helmChart", - }, key) - } - return obj.(*HelmChart), nil -} - -type helmChartController struct { - controller.GenericController -} - -func (c *helmChartController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *helmChartController) Lister() HelmChartLister { - return &helmChartLister{ - controller: c, - } -} - -func (c *helmChartController) AddHandler(ctx context.Context, name string, handler HelmChartHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*HelmChart); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *helmChartController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler HelmChartHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*HelmChart); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type helmChartFactory struct { -} - -func (c helmChartFactory) Object() runtime.Object { - return &HelmChart{} -} - -func (c helmChartFactory) List() runtime.Object { - return &HelmChartList{} -} - -func (s *helmChartClient) Controller() HelmChartController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.helmChartControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(HelmChartGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &helmChartController{ - GenericController: genericController, - } - - s.client.helmChartControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type helmChartClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller HelmChartController -} - -func (s *helmChartClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *helmChartClient) Create(o *HelmChart) (*HelmChart, error) { - obj, err := s.objectClient.Create(o) - return obj.(*HelmChart), err -} - -func (s *helmChartClient) Get(name string, opts metav1.GetOptions) (*HelmChart, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*HelmChart), err -} - -func (s *helmChartClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*HelmChart, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*HelmChart), err -} - -func (s *helmChartClient) Update(o *HelmChart) (*HelmChart, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*HelmChart), err -} - -func (s *helmChartClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *helmChartClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *helmChartClient) List(opts metav1.ListOptions) (*HelmChartList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*HelmChartList), err -} - -func (s *helmChartClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *helmChartClient) Patch(o *HelmChart, patchType types.PatchType, data []byte, subresources ...string) (*HelmChart, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*HelmChart), err -} - -func (s *helmChartClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *helmChartClient) AddHandler(ctx context.Context, name string, sync HelmChartHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *helmChartClient) AddLifecycle(ctx context.Context, name string, lifecycle HelmChartLifecycle) { - sync := NewHelmChartLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *helmChartClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync HelmChartHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *helmChartClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle HelmChartLifecycle) { - sync := NewHelmChartLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type HelmChartIndexer func(obj *HelmChart) ([]string, error) - -type HelmChartClientCache interface { - Get(namespace, name string) (*HelmChart, error) - List(namespace string, selector labels.Selector) ([]*HelmChart, error) - - Index(name string, indexer HelmChartIndexer) - GetIndexed(name, key string) ([]*HelmChart, error) -} - -type HelmChartClient interface { - Create(*HelmChart) (*HelmChart, error) - Get(namespace, name string, opts metav1.GetOptions) (*HelmChart, error) - Update(*HelmChart) (*HelmChart, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*HelmChartList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() HelmChartClientCache - - OnCreate(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() HelmChartInterface -} - -type helmChartClientCache struct { - client *helmChartClient2 -} - -type helmChartClient2 struct { - iface HelmChartInterface - controller HelmChartController -} - -func (n *helmChartClient2) Interface() HelmChartInterface { - return n.iface -} - -func (n *helmChartClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *helmChartClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *helmChartClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *helmChartClient2) Create(obj *HelmChart) (*HelmChart, error) { - return n.iface.Create(obj) -} - -func (n *helmChartClient2) Get(namespace, name string, opts metav1.GetOptions) (*HelmChart, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *helmChartClient2) Update(obj *HelmChart) (*HelmChart, error) { - return n.iface.Update(obj) -} - -func (n *helmChartClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *helmChartClient2) List(namespace string, opts metav1.ListOptions) (*HelmChartList, error) { - return n.iface.List(opts) -} - -func (n *helmChartClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *helmChartClientCache) Get(namespace, name string) (*HelmChart, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *helmChartClientCache) List(namespace string, selector labels.Selector) ([]*HelmChart, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *helmChartClient2) Cache() HelmChartClientCache { - n.loadController() - return &helmChartClientCache{ - client: n, - } -} - -func (n *helmChartClient2) OnCreate(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &helmChartLifecycleDelegate{create: sync}) -} - -func (n *helmChartClient2) OnChange(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &helmChartLifecycleDelegate{update: sync}) -} - -func (n *helmChartClient2) OnRemove(ctx context.Context, name string, sync HelmChartChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &helmChartLifecycleDelegate{remove: sync}) -} - -func (n *helmChartClientCache) Index(name string, indexer HelmChartIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*HelmChart); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *helmChartClientCache) GetIndexed(name, key string) ([]*HelmChart, error) { - var result []*HelmChart - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*HelmChart); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *helmChartClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type helmChartLifecycleDelegate struct { - create HelmChartChangeHandlerFunc - update HelmChartChangeHandlerFunc - remove HelmChartChangeHandlerFunc -} - -func (n *helmChartLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *helmChartLifecycleDelegate) Create(obj *HelmChart) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *helmChartLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *helmChartLifecycleDelegate) Remove(obj *HelmChart) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *helmChartLifecycleDelegate) Updated(obj *HelmChart) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_lifecycle_adapter.go b/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_lifecycle_adapter.go deleted file mode 100644 index 2a4a2af9f2..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_helm_chart_lifecycle_adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - "k8s.io/apimachinery/pkg/runtime" -) - -type HelmChartLifecycle interface { - Create(obj *HelmChart) (runtime.Object, error) - Remove(obj *HelmChart) (runtime.Object, error) - Updated(obj *HelmChart) (runtime.Object, error) -} - -type helmChartLifecycleAdapter struct { - lifecycle HelmChartLifecycle -} - -func (w *helmChartLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *helmChartLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *helmChartLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*HelmChart)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *helmChartLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*HelmChart)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *helmChartLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*HelmChart)) - if o == nil { - return nil, err - } - return o, err -} - -func NewHelmChartLifecycleAdapter(name string, clusterScoped bool, client HelmChartInterface, l HelmChartLifecycle) HelmChartHandlerFunc { - adapter := &helmChartLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *HelmChart) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_k8s_client.go b/types/apis/k3s.cattle.io/v1/zz_generated_k8s_client.go deleted file mode 100644 index d6a13905b3..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_k8s_client.go +++ /dev/null @@ -1,159 +0,0 @@ -package v1 - -import ( - "context" - "sync" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - - AddonsGetter - HelmChartsGetter - ListenerConfigsGetter -} - -type Clients struct { - Interface Interface - - Addon AddonClient - HelmChart HelmChartClient - ListenerConfig ListenerConfigClient -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - - addonControllers map[string]AddonController - helmChartControllers map[string]HelmChartController - listenerConfigControllers map[string]ListenerConfigController -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - - Addon: &addonClient2{ - iface: iface.Addons(""), - }, - HelmChart: &helmChartClient2{ - iface: iface.HelmCharts(""), - }, - ListenerConfig: &listenerConfigClient2{ - iface: iface.ListenerConfigs(""), - }, - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - - addonControllers: map[string]AddonController{}, - helmChartControllers: map[string]HelmChartController{}, - listenerConfigControllers: map[string]ListenerConfigController{}, - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -type AddonsGetter interface { - Addons(namespace string) AddonInterface -} - -func (c *Client) Addons(namespace string) AddonInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &AddonResource, AddonGroupVersionKind, addonFactory{}) - return &addonClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type HelmChartsGetter interface { - HelmCharts(namespace string) HelmChartInterface -} - -func (c *Client) HelmCharts(namespace string) HelmChartInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &HelmChartResource, HelmChartGroupVersionKind, helmChartFactory{}) - return &helmChartClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} - -type ListenerConfigsGetter interface { - ListenerConfigs(namespace string) ListenerConfigInterface -} - -func (c *Client) ListenerConfigs(namespace string) ListenerConfigInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ListenerConfigResource, ListenerConfigGroupVersionKind, listenerConfigFactory{}) - return &listenerConfigClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_controller.go b/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_controller.go deleted file mode 100644 index 6cb462c416..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_controller.go +++ /dev/null @@ -1,440 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - ListenerConfigGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "ListenerConfig", - } - ListenerConfigResource = metav1.APIResource{ - Name: "listenerconfigs", - SingularName: "listenerconfig", - Namespaced: true, - - Kind: ListenerConfigGroupVersionKind.Kind, - } -) - -func NewListenerConfig(namespace, name string, obj ListenerConfig) *ListenerConfig { - obj.APIVersion, obj.Kind = ListenerConfigGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type ListenerConfigList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ListenerConfig -} - -type ListenerConfigHandlerFunc func(key string, obj *ListenerConfig) (runtime.Object, error) - -type ListenerConfigChangeHandlerFunc func(obj *ListenerConfig) (runtime.Object, error) - -type ListenerConfigLister interface { - List(namespace string, selector labels.Selector) (ret []*ListenerConfig, err error) - Get(namespace, name string) (*ListenerConfig, error) -} - -type ListenerConfigController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() ListenerConfigLister - AddHandler(ctx context.Context, name string, handler ListenerConfigHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ListenerConfigHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type ListenerConfigInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*ListenerConfig) (*ListenerConfig, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*ListenerConfig, error) - Get(name string, opts metav1.GetOptions) (*ListenerConfig, error) - Update(*ListenerConfig) (*ListenerConfig, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*ListenerConfigList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() ListenerConfigController - AddHandler(ctx context.Context, name string, sync ListenerConfigHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle ListenerConfigLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ListenerConfigHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ListenerConfigLifecycle) -} - -type listenerConfigLister struct { - controller *listenerConfigController -} - -func (l *listenerConfigLister) List(namespace string, selector labels.Selector) (ret []*ListenerConfig, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*ListenerConfig)) - }) - return -} - -func (l *listenerConfigLister) Get(namespace, name string) (*ListenerConfig, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: ListenerConfigGroupVersionKind.Group, - Resource: "listenerConfig", - }, key) - } - return obj.(*ListenerConfig), nil -} - -type listenerConfigController struct { - controller.GenericController -} - -func (c *listenerConfigController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *listenerConfigController) Lister() ListenerConfigLister { - return &listenerConfigLister{ - controller: c, - } -} - -func (c *listenerConfigController) AddHandler(ctx context.Context, name string, handler ListenerConfigHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*ListenerConfig); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *listenerConfigController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ListenerConfigHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*ListenerConfig); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type listenerConfigFactory struct { -} - -func (c listenerConfigFactory) Object() runtime.Object { - return &ListenerConfig{} -} - -func (c listenerConfigFactory) List() runtime.Object { - return &ListenerConfigList{} -} - -func (s *listenerConfigClient) Controller() ListenerConfigController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.listenerConfigControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(ListenerConfigGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &listenerConfigController{ - GenericController: genericController, - } - - s.client.listenerConfigControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type listenerConfigClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller ListenerConfigController -} - -func (s *listenerConfigClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *listenerConfigClient) Create(o *ListenerConfig) (*ListenerConfig, error) { - obj, err := s.objectClient.Create(o) - return obj.(*ListenerConfig), err -} - -func (s *listenerConfigClient) Get(name string, opts metav1.GetOptions) (*ListenerConfig, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*ListenerConfig), err -} - -func (s *listenerConfigClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*ListenerConfig, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*ListenerConfig), err -} - -func (s *listenerConfigClient) Update(o *ListenerConfig) (*ListenerConfig, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*ListenerConfig), err -} - -func (s *listenerConfigClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *listenerConfigClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *listenerConfigClient) List(opts metav1.ListOptions) (*ListenerConfigList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*ListenerConfigList), err -} - -func (s *listenerConfigClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *listenerConfigClient) Patch(o *ListenerConfig, patchType types.PatchType, data []byte, subresources ...string) (*ListenerConfig, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*ListenerConfig), err -} - -func (s *listenerConfigClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *listenerConfigClient) AddHandler(ctx context.Context, name string, sync ListenerConfigHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *listenerConfigClient) AddLifecycle(ctx context.Context, name string, lifecycle ListenerConfigLifecycle) { - sync := NewListenerConfigLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *listenerConfigClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ListenerConfigHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *listenerConfigClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ListenerConfigLifecycle) { - sync := NewListenerConfigLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type ListenerConfigIndexer func(obj *ListenerConfig) ([]string, error) - -type ListenerConfigClientCache interface { - Get(namespace, name string) (*ListenerConfig, error) - List(namespace string, selector labels.Selector) ([]*ListenerConfig, error) - - Index(name string, indexer ListenerConfigIndexer) - GetIndexed(name, key string) ([]*ListenerConfig, error) -} - -type ListenerConfigClient interface { - Create(*ListenerConfig) (*ListenerConfig, error) - Get(namespace, name string, opts metav1.GetOptions) (*ListenerConfig, error) - Update(*ListenerConfig) (*ListenerConfig, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*ListenerConfigList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() ListenerConfigClientCache - - OnCreate(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() ListenerConfigInterface -} - -type listenerConfigClientCache struct { - client *listenerConfigClient2 -} - -type listenerConfigClient2 struct { - iface ListenerConfigInterface - controller ListenerConfigController -} - -func (n *listenerConfigClient2) Interface() ListenerConfigInterface { - return n.iface -} - -func (n *listenerConfigClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *listenerConfigClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *listenerConfigClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *listenerConfigClient2) Create(obj *ListenerConfig) (*ListenerConfig, error) { - return n.iface.Create(obj) -} - -func (n *listenerConfigClient2) Get(namespace, name string, opts metav1.GetOptions) (*ListenerConfig, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *listenerConfigClient2) Update(obj *ListenerConfig) (*ListenerConfig, error) { - return n.iface.Update(obj) -} - -func (n *listenerConfigClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *listenerConfigClient2) List(namespace string, opts metav1.ListOptions) (*ListenerConfigList, error) { - return n.iface.List(opts) -} - -func (n *listenerConfigClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *listenerConfigClientCache) Get(namespace, name string) (*ListenerConfig, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *listenerConfigClientCache) List(namespace string, selector labels.Selector) ([]*ListenerConfig, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *listenerConfigClient2) Cache() ListenerConfigClientCache { - n.loadController() - return &listenerConfigClientCache{ - client: n, - } -} - -func (n *listenerConfigClient2) OnCreate(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &listenerConfigLifecycleDelegate{create: sync}) -} - -func (n *listenerConfigClient2) OnChange(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &listenerConfigLifecycleDelegate{update: sync}) -} - -func (n *listenerConfigClient2) OnRemove(ctx context.Context, name string, sync ListenerConfigChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &listenerConfigLifecycleDelegate{remove: sync}) -} - -func (n *listenerConfigClientCache) Index(name string, indexer ListenerConfigIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*ListenerConfig); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *listenerConfigClientCache) GetIndexed(name, key string) ([]*ListenerConfig, error) { - var result []*ListenerConfig - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*ListenerConfig); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *listenerConfigClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type listenerConfigLifecycleDelegate struct { - create ListenerConfigChangeHandlerFunc - update ListenerConfigChangeHandlerFunc - remove ListenerConfigChangeHandlerFunc -} - -func (n *listenerConfigLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *listenerConfigLifecycleDelegate) Create(obj *ListenerConfig) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *listenerConfigLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *listenerConfigLifecycleDelegate) Remove(obj *ListenerConfig) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *listenerConfigLifecycleDelegate) Updated(obj *ListenerConfig) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_lifecycle_adapter.go b/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_lifecycle_adapter.go deleted file mode 100644 index 058e82268d..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_listener_config_lifecycle_adapter.go +++ /dev/null @@ -1,62 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - "k8s.io/apimachinery/pkg/runtime" -) - -type ListenerConfigLifecycle interface { - Create(obj *ListenerConfig) (runtime.Object, error) - Remove(obj *ListenerConfig) (runtime.Object, error) - Updated(obj *ListenerConfig) (runtime.Object, error) -} - -type listenerConfigLifecycleAdapter struct { - lifecycle ListenerConfigLifecycle -} - -func (w *listenerConfigLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *listenerConfigLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *listenerConfigLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*ListenerConfig)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *listenerConfigLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*ListenerConfig)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *listenerConfigLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*ListenerConfig)) - if o == nil { - return nil, err - } - return o, err -} - -func NewListenerConfigLifecycleAdapter(name string, clusterScoped bool, client ListenerConfigInterface, l ListenerConfigLifecycle) ListenerConfigHandlerFunc { - adapter := &listenerConfigLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *ListenerConfig) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/k3s.cattle.io/v1/zz_generated_scheme.go b/types/apis/k3s.cattle.io/v1/zz_generated_scheme.go deleted file mode 100644 index 1bd21605f9..0000000000 --- a/types/apis/k3s.cattle.io/v1/zz_generated_scheme.go +++ /dev/null @@ -1,44 +0,0 @@ -package v1 - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "k3s.cattle.io" - Version = "v1" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - - &Addon{}, - &AddonList{}, - &HelmChart{}, - &HelmChartList{}, - &ListenerConfig{}, - &ListenerConfigList{}, - ) - return nil -} diff --git a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_controller.go b/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_controller.go deleted file mode 100644 index 636660da63..0000000000 --- a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_controller.go +++ /dev/null @@ -1,440 +0,0 @@ -package v1 - -import ( - "context" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - v1 "k8s.io/api/rbac/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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - ClusterRoleBindingGroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "ClusterRoleBinding", - } - ClusterRoleBindingResource = metav1.APIResource{ - Name: "clusterrolebindings", - SingularName: "clusterrolebinding", - Namespaced: false, - Kind: ClusterRoleBindingGroupVersionKind.Kind, - } -) - -func NewClusterRoleBinding(namespace, name string, obj v1.ClusterRoleBinding) *v1.ClusterRoleBinding { - obj.APIVersion, obj.Kind = ClusterRoleBindingGroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type ClusterRoleBindingList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []v1.ClusterRoleBinding -} - -type ClusterRoleBindingHandlerFunc func(key string, obj *v1.ClusterRoleBinding) (runtime.Object, error) - -type ClusterRoleBindingChangeHandlerFunc func(obj *v1.ClusterRoleBinding) (runtime.Object, error) - -type ClusterRoleBindingLister interface { - List(namespace string, selector labels.Selector) (ret []*v1.ClusterRoleBinding, err error) - Get(namespace, name string) (*v1.ClusterRoleBinding, error) -} - -type ClusterRoleBindingController interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() ClusterRoleBindingLister - AddHandler(ctx context.Context, name string, handler ClusterRoleBindingHandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler ClusterRoleBindingHandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type ClusterRoleBindingInterface interface { - ObjectClient() *objectclient.ObjectClient - Create(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) - Get(name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) - Update(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*ClusterRoleBindingList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() ClusterRoleBindingController - AddHandler(ctx context.Context, name string, sync ClusterRoleBindingHandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle ClusterRoleBindingLifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ClusterRoleBindingHandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ClusterRoleBindingLifecycle) -} - -type clusterRoleBindingLister struct { - controller *clusterRoleBindingController -} - -func (l *clusterRoleBindingLister) List(namespace string, selector labels.Selector) (ret []*v1.ClusterRoleBinding, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*v1.ClusterRoleBinding)) - }) - return -} - -func (l *clusterRoleBindingLister) Get(namespace, name string) (*v1.ClusterRoleBinding, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: ClusterRoleBindingGroupVersionKind.Group, - Resource: "clusterRoleBinding", - }, key) - } - return obj.(*v1.ClusterRoleBinding), nil -} - -type clusterRoleBindingController struct { - controller.GenericController -} - -func (c *clusterRoleBindingController) Generic() controller.GenericController { - return c.GenericController -} - -func (c *clusterRoleBindingController) Lister() ClusterRoleBindingLister { - return &clusterRoleBindingLister{ - controller: c, - } -} - -func (c *clusterRoleBindingController) AddHandler(ctx context.Context, name string, handler ClusterRoleBindingHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ClusterRoleBinding); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *clusterRoleBindingController) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler ClusterRoleBindingHandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*v1.ClusterRoleBinding); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type clusterRoleBindingFactory struct { -} - -func (c clusterRoleBindingFactory) Object() runtime.Object { - return &v1.ClusterRoleBinding{} -} - -func (c clusterRoleBindingFactory) List() runtime.Object { - return &ClusterRoleBindingList{} -} - -func (s *clusterRoleBindingClient) Controller() ClusterRoleBindingController { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.clusterRoleBindingControllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController(ClusterRoleBindingGroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &clusterRoleBindingController{ - GenericController: genericController, - } - - s.client.clusterRoleBindingControllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type clusterRoleBindingClient struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller ClusterRoleBindingController -} - -func (s *clusterRoleBindingClient) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *clusterRoleBindingClient) Create(o *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { - obj, err := s.objectClient.Create(o) - return obj.(*v1.ClusterRoleBinding), err -} - -func (s *clusterRoleBindingClient) Get(name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*v1.ClusterRoleBinding), err -} - -func (s *clusterRoleBindingClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*v1.ClusterRoleBinding), err -} - -func (s *clusterRoleBindingClient) Update(o *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*v1.ClusterRoleBinding), err -} - -func (s *clusterRoleBindingClient) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *clusterRoleBindingClient) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *clusterRoleBindingClient) List(opts metav1.ListOptions) (*ClusterRoleBindingList, error) { - obj, err := s.objectClient.List(opts) - return obj.(*ClusterRoleBindingList), err -} - -func (s *clusterRoleBindingClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *clusterRoleBindingClient) Patch(o *v1.ClusterRoleBinding, patchType types.PatchType, data []byte, subresources ...string) (*v1.ClusterRoleBinding, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*v1.ClusterRoleBinding), err -} - -func (s *clusterRoleBindingClient) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *clusterRoleBindingClient) AddHandler(ctx context.Context, name string, sync ClusterRoleBindingHandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *clusterRoleBindingClient) AddLifecycle(ctx context.Context, name string, lifecycle ClusterRoleBindingLifecycle) { - sync := NewClusterRoleBindingLifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *clusterRoleBindingClient) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync ClusterRoleBindingHandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *clusterRoleBindingClient) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle ClusterRoleBindingLifecycle) { - sync := NewClusterRoleBindingLifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type ClusterRoleBindingIndexer func(obj *v1.ClusterRoleBinding) ([]string, error) - -type ClusterRoleBindingClientCache interface { - Get(namespace, name string) (*v1.ClusterRoleBinding, error) - List(namespace string, selector labels.Selector) ([]*v1.ClusterRoleBinding, error) - - Index(name string, indexer ClusterRoleBindingIndexer) - GetIndexed(name, key string) ([]*v1.ClusterRoleBinding, error) -} - -type ClusterRoleBindingClient interface { - Create(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) - Get(namespace, name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) - Update(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*ClusterRoleBindingList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() ClusterRoleBindingClientCache - - OnCreate(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() ClusterRoleBindingInterface -} - -type clusterRoleBindingClientCache struct { - client *clusterRoleBindingClient2 -} - -type clusterRoleBindingClient2 struct { - iface ClusterRoleBindingInterface - controller ClusterRoleBindingController -} - -func (n *clusterRoleBindingClient2) Interface() ClusterRoleBindingInterface { - return n.iface -} - -func (n *clusterRoleBindingClient2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *clusterRoleBindingClient2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *clusterRoleBindingClient2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *clusterRoleBindingClient2) Create(obj *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { - return n.iface.Create(obj) -} - -func (n *clusterRoleBindingClient2) Get(namespace, name string, opts metav1.GetOptions) (*v1.ClusterRoleBinding, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *clusterRoleBindingClient2) Update(obj *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { - return n.iface.Update(obj) -} - -func (n *clusterRoleBindingClient2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *clusterRoleBindingClient2) List(namespace string, opts metav1.ListOptions) (*ClusterRoleBindingList, error) { - return n.iface.List(opts) -} - -func (n *clusterRoleBindingClient2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *clusterRoleBindingClientCache) Get(namespace, name string) (*v1.ClusterRoleBinding, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *clusterRoleBindingClientCache) List(namespace string, selector labels.Selector) ([]*v1.ClusterRoleBinding, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *clusterRoleBindingClient2) Cache() ClusterRoleBindingClientCache { - n.loadController() - return &clusterRoleBindingClientCache{ - client: n, - } -} - -func (n *clusterRoleBindingClient2) OnCreate(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &clusterRoleBindingLifecycleDelegate{create: sync}) -} - -func (n *clusterRoleBindingClient2) OnChange(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &clusterRoleBindingLifecycleDelegate{update: sync}) -} - -func (n *clusterRoleBindingClient2) OnRemove(ctx context.Context, name string, sync ClusterRoleBindingChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &clusterRoleBindingLifecycleDelegate{remove: sync}) -} - -func (n *clusterRoleBindingClientCache) Index(name string, indexer ClusterRoleBindingIndexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*v1.ClusterRoleBinding); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *clusterRoleBindingClientCache) GetIndexed(name, key string) ([]*v1.ClusterRoleBinding, error) { - var result []*v1.ClusterRoleBinding - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*v1.ClusterRoleBinding); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *clusterRoleBindingClient2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type clusterRoleBindingLifecycleDelegate struct { - create ClusterRoleBindingChangeHandlerFunc - update ClusterRoleBindingChangeHandlerFunc - remove ClusterRoleBindingChangeHandlerFunc -} - -func (n *clusterRoleBindingLifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *clusterRoleBindingLifecycleDelegate) Create(obj *v1.ClusterRoleBinding) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *clusterRoleBindingLifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *clusterRoleBindingLifecycleDelegate) Remove(obj *v1.ClusterRoleBinding) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *clusterRoleBindingLifecycleDelegate) Updated(obj *v1.ClusterRoleBinding) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} diff --git a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_lifecycle_adapter.go b/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_lifecycle_adapter.go deleted file mode 100644 index 07d2b43719..0000000000 --- a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_cluster_role_binding_lifecycle_adapter.go +++ /dev/null @@ -1,63 +0,0 @@ -package v1 - -import ( - "github.com/rancher/norman/lifecycle" - v1 "k8s.io/api/rbac/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -type ClusterRoleBindingLifecycle interface { - Create(obj *v1.ClusterRoleBinding) (runtime.Object, error) - Remove(obj *v1.ClusterRoleBinding) (runtime.Object, error) - Updated(obj *v1.ClusterRoleBinding) (runtime.Object, error) -} - -type clusterRoleBindingLifecycleAdapter struct { - lifecycle ClusterRoleBindingLifecycle -} - -func (w *clusterRoleBindingLifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *clusterRoleBindingLifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *clusterRoleBindingLifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*v1.ClusterRoleBinding)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *clusterRoleBindingLifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*v1.ClusterRoleBinding)) - if o == nil { - return nil, err - } - return o, err -} - -func (w *clusterRoleBindingLifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*v1.ClusterRoleBinding)) - if o == nil { - return nil, err - } - return o, err -} - -func NewClusterRoleBindingLifecycleAdapter(name string, clusterScoped bool, client ClusterRoleBindingInterface, l ClusterRoleBindingLifecycle) ClusterRoleBindingHandlerFunc { - adapter := &clusterRoleBindingLifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *v1.ClusterRoleBinding) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} diff --git a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_deepcopy.go b/types/apis/rbac.authorization.k8s.io/v1/zz_generated_deepcopy.go deleted file mode 100644 index 404b0945f6..0000000000 --- a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_deepcopy.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - rbacv1 "k8s.io/api/rbac/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 *ClusterRoleBindingList) DeepCopyInto(out *ClusterRoleBindingList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]rbacv1.ClusterRoleBinding, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRoleBindingList. -func (in *ClusterRoleBindingList) DeepCopy() *ClusterRoleBindingList { - if in == nil { - return nil - } - out := new(ClusterRoleBindingList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterRoleBindingList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_k8s_client.go b/types/apis/rbac.authorization.k8s.io/v1/zz_generated_k8s_client.go deleted file mode 100644 index d4f0623b26..0000000000 --- a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_k8s_client.go +++ /dev/null @@ -1,119 +0,0 @@ -package v1 - -import ( - "context" - "sync" - - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - - ClusterRoleBindingsGetter -} - -type Clients struct { - Interface Interface - - ClusterRoleBinding ClusterRoleBindingClient -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - - clusterRoleBindingControllers map[string]ClusterRoleBindingController -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - - ClusterRoleBinding: &clusterRoleBindingClient2{ - iface: iface.ClusterRoleBindings(""), - }, - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - - clusterRoleBindingControllers: map[string]ClusterRoleBindingController{}, - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -type ClusterRoleBindingsGetter interface { - ClusterRoleBindings(namespace string) ClusterRoleBindingInterface -} - -func (c *Client) ClusterRoleBindings(namespace string) ClusterRoleBindingInterface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &ClusterRoleBindingResource, ClusterRoleBindingGroupVersionKind, clusterRoleBindingFactory{}) - return &clusterRoleBindingClient{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} diff --git a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_scheme.go b/types/apis/rbac.authorization.k8s.io/v1/zz_generated_scheme.go deleted file mode 100644 index 7c65b329fc..0000000000 --- a/types/apis/rbac.authorization.k8s.io/v1/zz_generated_scheme.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1 - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "rbac.authorization.k8s.io" - Version = "v1" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - - &ClusterRoleBindingList{}, - ) - return nil -} diff --git a/vendor.conf b/vendor.conf index 9baa515b1e..088baed964 100644 --- a/vendor.conf +++ b/vendor.conf @@ -11,7 +11,12 @@ package=github.com/opencontainers/runc/contrib/cmd/recvtty k8s.io/kubernetes v1.14.1-k3s.4 https://github.com/rancher/k3s.git transitive=true,staging=true -github.com/rancher/norman 50017efee23caa79542ef685b65a7b783e0a73ca https://github.com/ibuildthecloud/norman.git +github.com/rancher/wrangler 4202dbfa88013c19238bb004d82e013f0593493d +github.com/rancher/wrangler-api efe26ac6a9d720e1bfa5a8cc5f8dce5ad598ce26 +github.com/rancher/dynamiclistener 077eb13a904f2c62496f31b158135d9743526f82 +github.com/rancher/remotedialer 20ec38853712bb6d348f0db9ac47d34c954c6b00 +github.com/rancher/helm-controller 4f3b43bfd868bcb74fe847f8df88c482e9b70ff8 +github.com/matryer/moq ee5226d43009 https://github.com/rancher/moq.git github.com/coreos/flannel 823afe66b2266bf71f5bec24e6e28b26d70cfc7c https://github.com/ibuildthecloud/flannel.git github.com/natefinch/lumberjack aee4629129445bbdfb69aa565537dcfa16544311 github.com/gorilla/mux v1.6.2 @@ -121,3 +126,4 @@ github.com/rootless-containers/rootlesskit 893c1c3de71f54c301fdb85a7c0dd15c1933 github.com/theckman/go-flock v0.7.1 github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b + diff --git a/vendor/github.com/matryer/moq/.gitignore b/vendor/github.com/matryer/moq/.gitignore new file mode 100644 index 0000000000..b15784e0c8 --- /dev/null +++ b/vendor/github.com/matryer/moq/.gitignore @@ -0,0 +1,25 @@ +# 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 +.vscode diff --git a/vendor/github.com/matryer/moq/.travis.yml b/vendor/github.com/matryer/moq/.travis.yml new file mode 100644 index 0000000000..ebf53b319d --- /dev/null +++ b/vendor/github.com/matryer/moq/.travis.yml @@ -0,0 +1,19 @@ +language: go + +sudo: false + +go: + - 1.9.x + - 1.10.x + - 1.11.x + - tip + +before_install: + - go get golang.org/x/lint/golint + +before_script: + - go vet ./... + - golint ./... + +script: + - go test -v ./... diff --git a/vendor/github.com/matryer/moq/LICENSE b/vendor/github.com/matryer/moq/LICENSE new file mode 100644 index 0000000000..157d9d25d0 --- /dev/null +++ b/vendor/github.com/matryer/moq/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Mat Ryer and David Hernandez + +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/matryer/moq/README.md b/vendor/github.com/matryer/moq/README.md new file mode 100644 index 0000000000..06137df9d7 --- /dev/null +++ b/vendor/github.com/matryer/moq/README.md @@ -0,0 +1,108 @@ +![moq logo](moq-logo-small.png) [![Build Status](https://travis-ci.org/matryer/moq.svg?branch=master)](https://travis-ci.org/matryer/moq) [![Go Report Card](https://goreportcard.com/badge/github.com/matryer/moq)](https://goreportcard.com/report/github.com/matryer/moq) + +Interface mocking tool for go generate. + +By [Mat Ryer](https://twitter.com/matryer) and [David Hernandez](https://github.com/dahernan), with ideas lovingly stolen from [Ernesto Jimenez](https://github.com/ernesto-jimenez). + +### What is Moq? + +Moq is a tool that generates a struct from any interface. The struct can be used in test code as a mock of the interface. + +![Preview](preview.png) + +above: Moq generates the code on the right. + +You can read more in the [Meet Moq blog post](http://bit.ly/meetmoq). + +### Installing + +To start using Moq, just run go get: +``` +$ go get github.com/matryer/moq +``` + +### Usage + +``` +moq [flags] destination interface [interface2 [interface3 [...]]] + -out string + output file (default stdout) + -pkg string + package name (default will infer) +``` + +In a command line: + +``` +$ moq -out mocks_test.go . MyInterface +``` + +In code (for go generate): + +```go +package my + +//go:generate moq -out myinterface_moq_test.go . MyInterface + +type MyInterface interface { + Method1() error + Method2(i int) +} +``` + +Then run `go generate` for your package. + +### How to use it + +Mocking interfaces is a nice way to write unit tests where you can easily control the behaviour of the mocked object. + +Moq creates a struct that has a function field for each method, which you can declare in your test code. + +This this example, Moq generated the `EmailSenderMock` type: + +```go +func TestCompleteSignup(t *testing.T) { + + var sentTo string + + mockedEmailSender = &EmailSenderMock{ + SendFunc: func(to, subject, body string) error { + sentTo = to + return nil + }, + } + + CompleteSignUp("me@email.com", mockedEmailSender) + + callsToSend := len(mockedEmailSender.SendCalls()) + if callsToSend != 1 { + t.Errorf("Send was called %d times", callsToSend) + } + if sentTo != "me@email.com" { + t.Errorf("unexpected recipient: %s", sentTo) + } + +} + +func CompleteSignUp(to string, sender EmailSender) { + // TODO: this +} +``` + +The mocked structure implements the interface, where each method calls the associated function field. + +## Tips + +* Keep mocked logic inside the test that is using it +* Only mock the fields you need +* It will panic if a nil function gets called +* Name arguments in the interface for a better experience +* Use closured variables inside your test function to capture details about the calls to the methods +* Use `.MethodCalls()` to track the calls +* Use `go:generate` to invoke the `moq` command + +## License + +The Moq project (and all code) is licensed under the [MIT License](LICENSE). + +The Moq logo was created by [Chris Ryer](http://chrisryer.co.uk) and is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/). diff --git a/vendor/github.com/matryer/moq/moq-logo-small.png b/vendor/github.com/matryer/moq/moq-logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..7a71c177ec9f4051b6e0f0e8bddbd239db3d8efd GIT binary patch literal 32570 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/matryer/moq/moq-logo.png b/vendor/github.com/matryer/moq/moq-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7eae08f6f4df0ad596922f8004ceddcebbea9f8b GIT binary patch literal 29562 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 1 { + return nil, errors.New("More than one package was found") + } + return pkgs[0], nil +} + +type doc struct { + PackageName string + SourcePackagePrefix string + Objects []obj + Imports []string +} + +type obj struct { + InterfaceName string + Methods []*method +} +type method struct { + Name string + Params []*param + Returns []*param +} + +func (m *method) Arglist() string { + params := make([]string, len(m.Params)) + for i, p := range m.Params { + params[i] = p.String() + } + return strings.Join(params, ", ") +} + +func (m *method) ArgCallList() string { + params := make([]string, len(m.Params)) + for i, p := range m.Params { + params[i] = p.CallName() + } + return strings.Join(params, ", ") +} + +func (m *method) ReturnArglist() string { + params := make([]string, len(m.Returns)) + for i, p := range m.Returns { + params[i] = p.TypeString() + } + if len(m.Returns) > 1 { + return fmt.Sprintf("(%s)", strings.Join(params, ", ")) + } + return strings.Join(params, ", ") +} + +type param struct { + Name string + Type string + Variadic bool +} + +func (p param) String() string { + return fmt.Sprintf("%s %s", p.Name, p.TypeString()) +} + +func (p param) CallName() string { + if p.Variadic { + return p.Name + "..." + } + return p.Name +} + +func (p param) TypeString() string { + if p.Variadic { + return "..." + p.Type[2:] + } + return p.Type +} + +var templateFuncs = template.FuncMap{ + "Exported": func(s string) string { + if s == "" { + return "" + } + for _, initialism := range golintInitialisms { + if strings.ToUpper(s) == initialism { + return initialism + } + } + return strings.ToUpper(s[0:1]) + s[1:] + }, +} + +// stripVendorPath strips the vendor dir prefix from a package path. +// For example we might encounter an absolute path like +// github.com/foo/bar/vendor/github.com/pkg/errors which is resolved +// to github.com/pkg/errors. +func stripVendorPath(p string) string { + parts := strings.Split(p, "/vendor/") + if len(parts) == 1 { + return p + } + return strings.TrimLeft(path.Join(parts[1:]...), "/") +} + +// stripGopath takes the directory to a package and remove the gopath to get the +// canonical package name. +// +// taken from https://github.com/ernesto-jimenez/gogen +// Copyright (c) 2015 Ernesto Jiménez +func stripGopath(p string) string { + for _, gopath := range gopaths() { + p = strings.TrimPrefix(p, path.Join(gopath, "src")+"/") + } + return p +} + +func gopaths() []string { + return strings.Split(os.Getenv("GOPATH"), string(filepath.ListSeparator)) +} diff --git a/vendor/github.com/matryer/moq/pkg/moq/template.go b/vendor/github.com/matryer/moq/pkg/moq/template.go new file mode 100644 index 0000000000..d000f27231 --- /dev/null +++ b/vendor/github.com/matryer/moq/pkg/moq/template.go @@ -0,0 +1,107 @@ +package moq + +// moqImports are the imports all moq files get. +var moqImports = []string{} + +// moqTemplate is the template for mocked code. +var moqTemplate = `// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package {{.PackageName}} +{{- $sourcePackagePrefix := .SourcePackagePrefix}} + +import ( +{{- range .Imports }} + {{.}} +{{- end }} +) + +{{ range $i, $obj := .Objects -}} +var ( +{{- range .Methods }} + lock{{$obj.InterfaceName}}Mock{{.Name}} sync.RWMutex +{{- end }} +) + +// Ensure, that {{.InterfaceName}}Mock does implement {{.InterfaceName}}. +// If this is not the case, regenerate this file with moq. +var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.InterfaceName}}Mock{} + +// {{.InterfaceName}}Mock is a mock implementation of {{.InterfaceName}}. +// +// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) { +// +// // make and configure a mocked {{.InterfaceName}} +// mocked{{.InterfaceName}} := &{{.InterfaceName}}Mock{ {{ range .Methods }} +// {{.Name}}Func: func({{ .Arglist }}) {{.ReturnArglist}} { +// panic("mock out the {{.Name}} method") +// },{{- end }} +// } +// +// // use mocked{{.InterfaceName}} in code that requires {{.InterfaceName}} +// // and then make assertions. +// +// } +type {{.InterfaceName}}Mock struct { +{{- range .Methods }} + // {{.Name}}Func mocks the {{.Name}} method. + {{.Name}}Func func({{ .Arglist }}) {{.ReturnArglist}} +{{ end }} + // calls tracks calls to the methods. + calls struct { +{{- range .Methods }} + // {{ .Name }} holds details about calls to the {{.Name}} method. + {{ .Name }} []struct { + {{- range .Params }} + // {{ .Name | Exported }} is the {{ .Name }} argument value. + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } +{{- end }} + } +} +{{ range .Methods }} +// {{.Name}} calls {{.Name}}Func. +func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}({{.Arglist}}) {{.ReturnArglist}} { + if mock.{{.Name}}Func == nil { + panic("{{$obj.InterfaceName}}Mock.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called") + } + callInfo := struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + }{ + {{- range .Params }} + {{ .Name | Exported }}: {{ .Name }}, + {{- end }} + } + lock{{$obj.InterfaceName}}Mock{{.Name}}.Lock() + mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo) + lock{{$obj.InterfaceName}}Mock{{.Name}}.Unlock() +{{- if .ReturnArglist }} + return mock.{{.Name}}Func({{.ArgCallList}}) +{{- else }} + mock.{{.Name}}Func({{.ArgCallList}}) +{{- end }} +} + +// {{.Name}}Calls gets all the calls that were made to {{.Name}}. +// Check the length with: +// len(mocked{{$obj.InterfaceName}}.{{.Name}}Calls()) +func (mock *{{$obj.InterfaceName}}Mock) {{.Name}}Calls() []struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } { + var calls []struct { + {{- range .Params }} + {{ .Name | Exported }} {{ .Type }} + {{- end }} + } + lock{{$obj.InterfaceName}}Mock{{.Name}}.RLock() + calls = mock.calls.{{.Name}} + lock{{$obj.InterfaceName}}Mock{{.Name}}.RUnlock() + return calls +} +{{ end -}} +{{ end -}}` diff --git a/vendor/github.com/matryer/moq/preview.png b/vendor/github.com/matryer/moq/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..8fa7a627479e4305ab1feb607f02e24baab211d5 GIT binary patch literal 743543 zcmeFZcT|(#voDNYL`6YCKtZX3(xvwzNLN&PkzN9!gbo1_L6IuG2Sj@BgsRe{g-(DF zP)b5eA_Nj3BwW7doO|wB>*ssc<^1=qb@NA7@;rObo;`c!Gv%2i^0}`1wJXe5sHmu} zX*^Tar=p@Mq@ucPbot`R6}N?_a#U1T>77(mo@=P6+<)%rX7A);M@984GTHEw(aU~@ z98>)VdFOA$(*>x1@+!&GOujCzOm{!&Ewxfl>|?%WpPS!5RepNd%%I4?;$!!s8h(lW z%0SE7r)$X)yt$izMVUok>=AKD%7G&4iwzQ`dN^By->H3JN9B3`;K$m11$%3Kk;KVs z9~D_1p1by@7xi%`DF4e3s-!UjZU-x_$ceeeqEQ)wIj;KhV>MEe>i&xxMV?Qy?tY9r z`xfB2^ZtP9##}Da(I+_PJgss$_xtl_?k~}033O%9W$|@Q>qBN78M@`E;&0EoSV>cP zQM=in;kk#((~_K{ZVo!rZF--uWLpirq40i2numwcnoFb`RkFCMacl~ktjTimIlPlH z#eTb1!7?dzIENIX+jpFj<+8nYC*t{S(f8lS5;A_bVFm}TCBJ$4(e!-D&CfT=l!GEi zk`J~1kgs~UXU&Ja<*@!P6=unl`*x5(8*X&T`kIG9R@GgZ>hN)+wK%mucopka$=7Kt z{3CG;muoqGtoWxm{83ih7SDNj-+q!OhV9N-VKb+-u^-Vh=b7|&&CV#upS70mhCekH z&fA&k3uh|-_<}7@(&WeNouwwHAKx6)X$#Xim@8=NR;vqazBjx*SaImSIA~p?n)6WD zCFxu$n(hAbTMz$tl2Q^^D+M|o{arLHe3Itb5WR!fKcx(d`aFAeLzEejPRp3)!dlIf zzSaL?r)FVwRlR4R`S-)i=N|u}O;fxoc6;TW_BS^+$GdOcYI797T~v<0?)Oa%$Q1J| zo^bh>=*3&_6z(sb88ga))Tds$l1m;;drhc6<21f-)=8DY@1n=`%9z04tbTWb4i&w> znR_&iNfwT;6?ap8Q4mhM^Q`{P^7qj4y1XlAju&T?tp>xUG@37~0rpek{zQ)|`6)L) zU1Og=xBaW+Nz^=myYt!pIS}{dOXfnRxos_zxUw#t2LPUVTH^bo2fk+K;1|XBRgEGA zvDW~gchfkgPkqhc%t5xk#A-?hD>NIZ;hRwR>>f#^T)2v@uDTBPWVbuTM!h;} zhG|P=`kmNWZl5cFA9L08bh3?fIhuw))*Q$5fyP3#A(MTT)0K-@JgrUL>arF}D`_M% zQSgAt2|0y6RM&f9@UMa5UkY}H8=KF+)$rlq z;OOg|{lRw5efKuiBx%tF<*uHqaOT&zeXNnu{W^_C8%3&Dx#y3s@aJBNek)bpcSiCY z?XPoZzuDfPwpOA`JL4dGZbcDR_dTfke9~Ky>WePtli$e9Tp)yo{StCK&;RRcGgalg z&0h?DRPd*Qe$*Gg%Lql^zf7I?;HoOkn7a0jN8M*Up0>qPabAs7ONhV4dGF?ZYg_r+ zTf8dM50ZcCe!X~bTPik7Nr2*@>lAOy6O{S z#*Pn6qAQgjjXLjA&ArW0s`}D2DzM8X{r-&hnTc;#g;<7e+gN=z5=n`mt_e5dHHdv} z<835*1e2&1aG@f7r1!W8>vsJ$ceQuf{klAj<;SY-N84b(bHUd;Lw%RS_6^U*G& zH`6O$j(qR+!$p}oFRS{4d$c<%MWX$^uPXbCFh@17&|^C~;Y7)}=7i>CBRyH2t^0%< zAD(e0F!X;~(fGt!qjB(+ZrpzS%s8(;Pf6--Xu0Avk4*fz{(jpt(2r)i3wrVzSWX2V z+LuYZ+_!u+Im5NmwTyLUb({*#@^|$kO88!hmhy3 zmuX+V85)&8&vSqFJ3+bWhx*gkPqm(=EIoNzv&7fa{;B9Tj+gQ@e@xp+zTVbE-t~4x zgii_~jSvdUMU1PgnH{nR+-?tD&-sts?4Xl!~m{3nFGA=c)^4G#AGQ51G_(%&-VURz~;cAA^5Bx-M!MM($ z8!q*h#Srg|Fj-1d{_K;ai(?CP>tV9l=F+axDlGvmN-h2^ncgEC*VmlZ4%X~8Tt{U} z;8i1|#Bubd+o(dp@w*b(uARN;qcn6{*hT4!-!EE+WnaWx?253D@Q8RCu@?~+U948A z=A_0FZ4z@aW-q2I2F(IzUX;j7YtFDua}j|$?kr3WJ^AjH?v(EYNiQ`1Xq;zUF{=W~ zfHoaG#yjIP8B}QuqaH_9Fu?g=Xz>hQ9poDX7!)Vh-ClGqd;LM|``oa}8*^81pW0Y2 zyzpD$bRoi^OMIyDXX6-Q>ijZwKmD|Bv*hox>_qcMB(U`op_Gt_iQ3A@~H;gRME5IvYYKCntg{na- zz1mmQ-0>jOmFXqI7;;u_kz7rJu!^%9vy$Wvxzlx)bmrtr`X)vbG0=&+!Kn4*rG~Du zLBzLAj5&tf-S_juW?df|S{3eAh&!`r80-_Q+-VbxGsc!*D4(FDg~W%Hgap2IRy0$z z`?jpu^=h;L0YaaA6T=y-|5AikO5R^@XLRyy z2}=<{7nETjf+2X-t%C|JbMoXk0(&FVHAQDdyV7^Gb;}NH>G>k+LPf5XtMj)(5XOrP6cJiTUpicR@eL*607(?_=JAt3g$6CHLY0;;MGj1{n3SbX-*NW!o0wSwdU?OpLh}7l5 zgF%F$WaUiT5`ed9S2Nw**nbwCoRw@C+;|LKLVtekR5oWQQ?<|-(X3XDBADPBNYf?d zkIdk8@Qe4Yi<&-c|T~7^#MU=@a&OwJAOp!iFj2%J&^9$G9D(dK<(%|HMAh1;V&V0nD57)6DwJ9hTSWisC9Ml?C zHvuenJ3wLrVqzq3LRIBcKu-htQsKSk;L+nZFSB)!uz;AuT9se%`=e2oFN52`lDqDk zH{l%K>N>GNsa{EgxwlV-T<^FHIc_;?I&VnIANT?4)bTZoE+Ghn^{BqLGP!#raWb)o zM_u=J4zqN&Z@@3@!}Of#^a@%ScTT%MZ~#ic=b;77FSof9zTkRZrpgL7nE7-D9evtN z?k$5Evdm@8#gehRq#7SIAp#%(&!}uQcf+Pldely|;)kvsvoHc9=Gy`uEgAG-ni0M@ z?bZqJ)W9a31)&{Iq`}fE7#+p`sowp(lfTm^9ana2wH`4I&@Xc#Zoyp@X4= z)xT~>u%eUDk-gvO{m^-ByEV(V3#X;v2%aI1?Jf7{QA2WQM=08dX4^eWT6p+q6|K6b zn%d5ca^vp9w@ObZ#;N@37^zI?sG>Lj94V$E+rPg1iH*`fPoYmij(lCZs(8UnPPb!H}}SZ1b!v$)_H z9V%TyKQ@T&!4Ew7dLZ@2q{7+Yq>!_gCP1_B{MeIx;S9v-m64Z`j<&Roo2!78t(&!- zfS;@TN%}xVCF>`B^3m1K%j&+Ls|ye$?I*|nZzH5nKL2xBkp2F@4ex8b1_nNaH`>VLWQA5&!o|JlNS+0wtu>))=P2u%Kptl)nNU;YZ< znnW@cl_Hgfs?saJGh4_&FSDuawF3y-YHIZ72bZO5>7h=lMHNCfcYBbGpMk0dS(gfN z-VQ?G@BLJD?naD1-=<4?;f-WP-nZT_zatV;S2?WX(&AAS8z>f$xvy(#OLqVhdz5RT zn)Ae-?vb$O-LdW;_l5Xe>~W=suU%cUK^s}6FH8B>0~uDyhZr#7Ad7=+73}@^M<~_V z%lF^@zqkJ7=VoJ`ff(U4HF+`=gczp2pk62$hh+m`o~f>xvo8Y3?As8kb6KqydI!C znqb;(0XRpF(#&qSKWcsoSSEB*iZ3_~HfkCflWmXMQ=jP8ho=&U(S#|WuKZJf(u-|N< zNW2StejIqC{v1{-{tEb%VtRAoSp;wh{g$NPM^fH#1^@Ag!^OT1dc=P7G!}b9@l60t zyx+ZJiuLV9zT{^K!7r_%+ka{ka{A${q%#k0oYqQ;L%(V3j-Sl72vg?`(ntvJavf(* zr|uQ~%{&pnYINze^c+<~)8oI%(O1?0M;NGk8uB5)#tBS-voG41>9n-cEY42w=LNQy z>#4}PaNorbel<`#;8NkT7?;?6)>BH*KH{5~b`mfG;2a?*KCefm(b4awk)J7c zNO{#}Oei50sGf?)lffBJbB*cBSiq2&j?RbxR*mbiAu`NUr8kLF9|J#y6h)qzU}2{s z2e-MzQqET5XfesTxG3rTl3!E)SQfLDLQM4sKi{~Ar$1`WvoY}>k(UGAhnZa!unWvz zbUi(GT^*l50x(4u=$HU{){A57fpf@9X*Kpgs@QsBi%-*wo3(!eb?=XYTgFB&Rb4&`P`UD!WgP$NTiB zxN)J7589G~E?J%Pc)tmzNCuWWUG48?-+NL#1qC!zg6{yJK6A8zq8Kp@z(MYm3pi?r z+H1b4T(tl+_*6{C;Gaz4=RF996KUyL&8Ag=swsa!4Um62nxqInxj}q(_q5*ZIc;bF zw<3ILzQJf>A=RY96q^IzY+EI~p4d*$I5Mr;)Frh!Ri>g$UeID*W%D@GMxQe1qB<+8 z^rn>V>x8Uc24FTYixA)e$qdMrz*6+%G9xv9>@}mFjHFMSI8`hwBsG}874$gj9mX5P z-$?|X(&g}-x7SzpsHhaH@SZT~lb3L+yiGhQ@JlUY`S+UBQ;cM$;F+j{aid2uV!IEt zLHy>TPP3N-pS3tFozl5cg+2^bduFc-qID`y?qzn)L7BAJzml3lN6l&J^x11#<6c=h zn4q<6vek?^Hk5R2;$CcuMw}MCwS7ZPcod6jg7eF*AmL942`lLt8+fi+Q@$F}2M_#8 ztAu0luUpmH(Ii@j2GTYhFiFsc!qoO0EKle2U$F~e=p$$zI$1h2Y)%Ds*p>LuYCxJw z79yp4#y=8#Q>9lO8K`_S(fnPujO$6N3)MWr;6iG2A>EnfJ>mrW5Id4 z7;e_i_z$s30@(TBS}n&q|2o0l!g|^xYsOKsP3H z0Mvt|_c)z;-hZnY|LqkwmtkP#SA1eOPh>-EL#!|E^*9I$TAn;X^enlrbfV@7enm^t zd~)jJ{u)ax52nF461V!Y84dIT+pF=Tai_JtCsB%XkweLqskRmz-E*W&TQ)5I`MRuc zjOX6TE}?R-#N_YMg#f_UPIhSvFAFkImyvz~#wDzne4g+}W9& z@<5k)Nm9}z-*m{?#H>CDOOg5J-tt!7QrdcavFRY7*bDO&ztr0o8AWfyme%Z{VY6qY zUE2YR`~2|a+T=>7mk`%A%eoU-wbZ)~)?v29$Y!&>HfSj-7AtZo zpG^b59sP6nm@*A^Z z|3p{}JsVH2Jd?-LQg^qx7NoZs;M|sy44XK3VaE@Tm3Eu58P3Qu-2@x91kd|B_4XJ) zs<=b?)?+*vBJ?PIxhfCy1U@dtdumWuyY);|1DepV1dF7XNERko^h#MKNFE=2Z0%4G z1h!6Z_94}`n(cLVDporl8O!u%N!B=Zf31lC$1j!V)0!n1Whd_5#kOf~CS&Wy@xrvH z3{&iLzP;jMFbwG6#4mLh-c0OeCPYTn#mc8^SeK>eg9ek6w~FR7#O}HEo=2KsPxxFu z;nPr{aK0IAG|=-(rjphc>itA_@awkp2>*mpmwBA@sWEfytP|%$9&-+05VYC357VCh zNo<$tp|3y;Xz&E3@cA1JW-=RXw`0U?zPRxd%=$AlP)Si0Je#|;tdBK>r;b^$>mA*ZOQcvkLBg=r#;O!Ky&l3L$9Hf239>!0SSZ6RYH-6 z#(+tA`pQwHbtZ3QQ%ayti_iSNq{j>47d8a7OEHL!+3=ApWhc_SQ4=tN``&6V=DnnF zi~Gq5<=csYyknjWsLiS~!+$WJQb*&pb6?QCFPl|QfO=RD_B1ay0u^|M(W-g%-V(h} zKg3SX%{GF zQ1@xTKb@>6;5;8Y8>gc@k}=YX!p9!8nHM8EH0dVuVNNO0+7@x5K%1=>SlNT(afrsU zmS{ep!9?P)oLW7TE3%1!RBk)m4EnP4rFRPx#Z1dmM+OZ$gdSwI?4EO=d@reRO?_}Y4d&=zZ4hpNw{FyMcmE_(a76z@&xh2Djb<8F7KprEyV88Ofn4+y#hkyr>N9VC}fpZ@VNFmLp2cFC6|Kl+_hgsIz3Z7xWea zHe=dVs*YAV(_+ZILA^uji4$FP)m?|flcjW{`O^&m1c$D+eC@6S7f7=%4A5XCy03kE z7gq8H_DU~ObEeW(Fu9!3K^K}iTI4Pew3t5(UBvAp<6K;%3ieuz>l`3X zmn2VXOeYZJ_~cCHrgX^nFACBPd%F{h!}hc>Y$2qy*?b*s1t<9z(7G2kR;f(l>dS*M zh!Z$($w^5b8iVQ>iw9T-%t?Gr*jpNk{8VFOwY=K=>)C`6Mc|1?V$_b<1c#L z-ndlsHu9AA{ZG0*sdPUzYoT@@Ikp(vW~&=Af5Owm-XFZf;2y$5hG*-c1cMk5e)S}| zKJe0=^c%174AgG1aNe$aY3hXHe}yfKi1{EFuW{&F-tJ3dqTr5Vdu%a3CxhRITAwnU zJPDWA@4o?Ax$2ffQ!b!vK(=Jrc~1Yv6wb#MeJ)Hs`{?UY`HS?9lij=ZZjK3iUszRF zA2nIb_%V}PBESgpm+9$7g={$oth%>N(*HmbPZHk_hc`&o*pEaF^`U;wsetV96-N*y zuvJa+?k4mHY&kYHYHX$$+$^lIp#jUbMV4B#@Czf^3$BSJZ$8B+xUeaal{TBfjX)go z%LN+7lP;O_LZ_~;orpo2=9Z_mt91*h*GnSA!1vCiL!V2?=*=lMaeH_qGtEh4-CD2Nz&;j6ov{Z10Ale20bmR?Tdvn;uEJ-0$$~|$Yq*&~ z_fHJFhLfyR(>Q{IH@5qx{{xW{J&C>Crwvg~%=z-ohb!IoL)9n=0IVE#d7!MpCfLl# zl8gKTw3R0J4hCVPrieNP{o%VdBhz$-_$rP+x%K-$Vo)MG5oQ~MkNE#p_M9Hg-O-#K-?EJNcPs{7DQ z3qFq^X48}ujtJPGTQ}Fotxnin8k$OTvJ}^}Zjrz56v|^IcRjG;-4jZz0`T6-1`fY7tcS&^uo=e@-{q}Vt;^N#K9G#yRV_6fsIsXr0R^xxSs{RIOR7dp{T)X}#%J^A!) z$J-MhvX;aE3cCn7$k>t}eaNEa#?}rGdTP*MXX~<(>k@435I|#Ct&W4MRp#(TEt}V{}|6 z&+#F`YcUH(u|}%B``eL~-b{NrY>S%K%-y6f`-*-?nBQ^DZ|4?nuQDhqooJD(MI|D~ zfsjsmtyOhyVQ{Xl%uT1S?UUC+={f#d2v#Itc%nX?0%Z3eZ){KS1iiC%fyf;}4;GFf zFKkv(+{S$|uKR~u7iaR?g`MttzA9+5HN8ZGg8g{1+lZzpV*`7jqo9D_3zZ+&~$Sc#5BglXSn`4AvJ|_^RG|g zM}y9)XG_e+#l=W0Ug)0LPP548ZD6)B(NSi05)^|fGW`8nVyGJ9=t;aj*@A2}g*PG` zHi4!#E+ronfTS>#Qzr~RnCm^C=DEzwBB8t7HBdiIZQAJ)BDa{9gX$@Q8r(4%mEyzT z(OgcX8Y@x^@;HwmelYqWW$;HhO%(N-Pc3&I0BP=SupP6G;;DHq@f3Kib(+PkgZEMh zrBtS1Nt#ra7WPep3MoG@IW>! z?9D_(eAfJD4|ltpKBBWznH@lcWgB~ik$x=Wm#G$kc7uS{xhsg_fiab^TGG0l2($Z{ z0`lD_B&MW!@P_dNekh>7x0xbf4BF$WUD{2V-&jUbwj_u=4#u*On$BXKlm@hoi?0?* zbG;+?X^Ozlfhd%JX1&C5N2Y^&bx7Rqy*qrBCZ%ib_YzZySmBYpx*~d;o%~MltBV$b zPounkW_SZ^dyK=$X=&flJ|D_4Fq$d^y4Y2zwVr|XjPWQtl5tOS^PK^c%>I|{I~h-) zq&oOOPp4sv9!D5ywWNJ)B!krUahCWq@7&I09X%vnlOW;*>bVXVd1O=7&bPP-6(!a! zcz(p6n#>mYT3vec3~6?m-aW=X0vtLwN-Iig?47w zH%5Bb<;F=h;!Fy_;J##1`_zqZE@%IOIBzae&tw^cZCWgwu1ec)V*TbDV?glB8I02o zqzTz0vSCZ3c^@mqdo>VnRFu=!TSRRpKMd+KFEcZn@%zX5QQC@qX3{WC$He6-a;_i z{90A9ZOGKY>-R9ue}&rnp^9)Z%hXnRB+%a0?oYUt6!G2lvAd?`sL=)f+I5`FN{zaU zaw&m9Gm#T<4CxfeBpzx^ocNh8xaP=?zP_iEy}@;gd(-^(3`{@ur76CkYA~6xL2vHE zH75U6fB&N@Rv$V<;0gsd&zbFGIco(amYVWJBljvYzm_#r?`MX2lD&!Pwri~ZfBG|R z!=a;FBZsS`{OnrPS)E$~-5J&{e$QDuR^=Vq$7eDS9Rizz^+1Z%-OeU+EZBPFeds3Z z!h^C@1bytlcMhg?FY^e}>L*jy;T~Ue%5A8>xi9b7tTC62G^ZZ2L&JyE|LqZcFs!LE z<#y4&FHBn;y}3wO`$~E_KjMLZ8XCs5E+x2sD3Q6z=1zE1wu&7&hoW4~Y_2RDuJiVf z|7_0n2uw8Nk7KLeJFS3jr4rZ(Cz3Le|seV^2dLLxh zZVR?#Z7=bOc;;GSo6%$a8aoB?@h0n1SFZeI#io{tqi_J={Ctr*uw8pjFa2&d*!5ZC zLW9QPSuBQZX~Lh~Gvw=leIJD8$!$6<@^$gx zU>)hYe7j?O9cbV-d5;|u%)Yo>UFwG3ZW8CW61k6il3`23Q(?m6p1NH;Q zgFB;H&?7X?C!jle7z(aC7noT#p|@}y0fshLZ&wE&%PM&UTfRcXLYIS)ZX|S7F|x%r zGRxmSb127^E&NFIPD&D%fJmHeOfhK!%rtCe_+XrA35FH-@&6hQhceUHdXuBQE^rng z#%`wq<2y+J9$xZ$nDA;A!}@`xMA|Di;#x8Z((Gid-y+lZmCiRfs3K@H7J$@%9v)T! z2f27IeKkV&B4E(x*u&}UFHlq>!$Y6lG)W0w@H6Z%R{{E5Z8+H$hNaflYEP5JS9G1on$%gshT-I0DNj{gLNnloQ8Ylgx>q-H<$(0$vpV zA&P%L+y^lW)DP%**)#>-3-g3eeb-nQuXVMH3j*N{tz}<^CrUjvkodKGyX>j$gblW$ zT~Fy`fIKKdLw4b)c$a|(p;;xnlgdp!uc7G+xrA3t3nbl!0_}qJx7xKO`?}RO9dJqN z9ly8=7$HT`kz)|SX#NVNfK_B4-RHq;5HPX%|N~ZAO4wvpj(bD zw&F9{pbA2~$kK)kNKBA^z(VzY-RzsME`Mv%c%yb@-@h){^o2{vOj?Xb-@7?0aO0xF zQG=IkxdPU2Tr$S3*;AUcuurLCH{!!E&89DLsju19l!%a)z^1Vk;pvl$PI8!(6oy1w zdEv2nfiL|iCF*tT%!(0SA$#b*RjrcScl=BAfKcmfGmkFuSp~Bp*pS=O{>Lp!FW9rk zvOF=cX?L)gI~(Sds3#RU0uVPpG0;vE=0x%$G9?q#bDMbLJk>riP6k+1%?Byf@OrLi z*Y^5z{P{x@-fmW-!5R`EM08Fz^8%#KyE}alt$8)fV|S6O!0k#99tykb0c!x`;{9>% zzaG4hd1>r^mwndd#H z{>kux`7tn?xEeYiy~Or`AosF4R;PCJ;J0;%{Q;k`r8Xz_v%;}opw;6?=kySyfCe+~ zWPjEUa?m!VKC6z;7tW$vMT9t_(n$W~Yp4oXxP$}3c5TWbb=>I#WHB-1 z;;>oZVwB<79B&h{xuv;D<2F8sfSchZGQ%%n4@`bnjBT#849a}UBVg8u3vY0#vv6On zkyog4AQZZ0a#ir9u$xI|Z)JndCj~xK1vztg4!&5eQP~34vI_p-a-_d5KiibA5UjU= zN^#rm|Ff-ZRH!q(SkvJLBY2k;w0}#G6M2{^QJFZ8ckjs`KNbbwA3|Ui9MIiJEsuk@ znyK?gQsBm+Kbc*%WTiSiJU*B#H}doQ*i!c8v{qf-Fw?VeZ zRk&`xSWnBwRpxIV*coY$2b)W{XmxmDX;2-{37s608Vwkxp)~zZNCDdQif|oq;WaG|xzhj2}0_lzpb=D5M z)@a8as0Qr<-cTZ4_2>8bh>JvdzRZy4nj&t-PpYcNylW3_GLmzWDVM5}KloyKqpxMC z8rJpV^TU1ATHvU~N`C7EUwBG_wK@TlWU4*xBaiWXcIY$D(-h=eETs3fu1|vjZhBkS!`n}9`NWsc6pPLddu7-^o+nen5c z{VR1BN@oYI9Rz66t%v(8%h76eY9z2eq2BJQIx#P|nMPm$#(wLY?(D7+1qk%j*X{Zs;oQyUhQ$ik2%!fIY4F3{HQS3l-2NKEoU7=b9SN8K)9c`v6F7$}iQmDWpQL4W)-&;vyLM+2@MD|m2hXF=_wFur}up!2=`_+yr8MDGm)mB?6C&HCQ_8y zJ9U&7gGkrcL;B@uRcep>K4^y85th#DmNr^+=(g;t6Pux(aHMm`Gm)ey7P)G3Y%|4! z$qQFdr;KxLf7-g`-f31hw$P`K^=t}kJ{*{V zye8p4A7_i&c0BYdll>z{cH)hA@z>7M+!yD6?ARlNTMe5q(_y{y9!-@sC-t!*g(Jz3 zwhSMBc%{8%4GI=>dum>375E(LLEIo4b-LOh<(sf^2d)y+6(4$L?E}Z+!NlhuRs#A1F zXPq5oMyq21@I(7B9j#=K+Yu+n1sF4%APRejB2EfiiHoV*GYxe~LfN=mvt-N}=+5t) ztp4#uCpfU^ZlatFH)P~u{o}C}N_6=FDlB2PLEQ(38RW_9sD6swdz?y!jW4xup!f&K zJt+newwodMl3rW>MJ4`WtRE~* z=DtaJ3mZwzR{&caa{H{BV2a8ga-pXOfV6t;5)}wp zKdza$J_>4$(jfN4!-qR{-J1;!1SK-l>Rw3?@9m{;ng#^?HWm%dh9KA_1ZO!G$qSV~ z7?}=j@nj`KGqb7k)k&LIsZz)93c-(vwjY9L4`~4_pUY&pE2e{6?CTxuju+9#7v4rH z$=Ho35C;xvwrCyHV8^OeE+OnL$M?oJ+xUZ*q}S`!LY#veuV@fg4a!Nlr{r|ePR35s z%nBs#41P5&EcGNoVK&6RyQBWMa#=3nEHJpd0`RWPvPp)TWg?hm8HPtt(iB)H8^KoU zqX9q{sE0%&@8*=lb)HU_C=<-hlhyzat7Ro}Fl4b2ervJ_z7Yq-IB&Gb|J^5e-}*UF z?SBrmCR~)nX&TMMl;l`y>LicKy zegvUH5K_pU9vzg;!YhRUTU85jH_t`oaC9WTd z;#PV2Dj&G(8*1wPelr=9AwC1n_Z}t@+W#=={1SJQX~NXUjf3foJq~nsd?D>lOT4-n zg&?Pv58sQ3gFlN-+|zzX?(2XdmSGGJU_tu06uR)8g0>}D97kQGPt_ea8OvK-`#CT; zazR0_>zqQWaAKN;?QnLk$|o3Vcu!%DF=(3cL*JFi_3z6)3#)*Y7KM=zX#Py9&+0pW zZeh8Hp$iHxY{(W@I}qfZo!^3*XepS=isePue@(7W6lsIw4G7@+4vLyN^lp6=6In{K zX~eK%ndflC16LNtNyaI*#zsPGfjNQ|_zv8`LxDJz-#m5+|4Ds};Mm?;q2Fas9MKL@ zo3VIz7UT0Mb2{$B@Wd}kyR!1mK$U}U z%WmO)k|CrF1a^RMgjn{D7(UmaG2AoK-8~vDYFVV(-V?ApOIlfQQxN3fc3PA(8Om&H z6=-|j;YZZ zgVI5Mxx%005_4PkLC7YwPXe9a*GlxydWsBCp z@M#9}*?0aqvElqCpLm}h0sE!+pvP(CPpVlQhZcRtd1ga12x{1vP$wftCEuE_j;f@} zU!M$28hsm%^TyjgD(OqN5$ubhX>H3*%k6014A17lP^#q$!8!8*FAsWmdE13R-Y?Km z%=o-8YjQ_%qXMcD7wcrM6$3(;!1ZnT1Qx}PF9~K2548E?L4X-sJaI9^vOc=5n!6a_ zg#Pb?yJ0S&{qYC=!7XyBzYw)w`EBtP1rl+YAI;dYq33p-8`TZc)VRGYetPN>X8`#k zxajGl14F_<7`%-=Gv{(JPfIof(dvD3?^38yWR=bofddsY-ryTw z;)xhF-0DN-lk8STt5Etw(#k3aT$AJ}W21f8;hNAkoOm-JWw}aYMux)kIJ5fqLQz;C zKE=|DEwc-;8hhMqZjwqI=z*-IU}4vd$AAkWmizFFA`agDy{+&;F`|oJ zb6NlIb0~ikP$M`;WE_YsyUUt&*EaYoPf?)^EM1#&4VUQf=`nRO=wE;4p=f@=rLw$(%Y5-}CD_L%LyP71 zvgKO^OZe2@mpLV2${`RTmx_RR-3tM7VT#*d)mp4&m1t|zB2|B!0mswnM%`w0a8=+g z#l#kvH*G=zy)B9gYuE58>B4xuCIO2!$)>E#q{{yF40mAPR-S89CAjg)@#=pY2t7%E zi$`G_@dlb@TL~|Y=~Aka2+GzKS)&pGGHychHsNOeE$2DKi9eHBT81;&yTVS2!C;Fe z7oQor zY$6gx!{9st+5>xbt!5txzR5zmE@X6=w?Qs`e%r2^Q}Uh*ZIKYtd$j)uUdbn~hc)up z$P!;aaQOi3ec&r;h$BB+kK$Vv82I`Oj|b=KMVvd#Y%E(^j4D`^`mMkQuzRh(j?Q1YVh%|pcr5DT#MX%O|Fl?Pf{0T`I_NL=ri}) z^|8y27x@x1Cg!rtkKT8OLEN1=xwnOpC5G%}6#KtaO4`65fPNT@hjX*HWLO$Qcp}r1L|zKnvK~;xK+8Xgj2} zdB1mU?3^G2oioYqPin@(96NxrQ>cM&ktk1YNF_Y0Ixss(r{Re~sG4OSO8=Rus6{)p z7^npRgPx@Rk@bIvar!)U25kaDbdGc~AtTxd&JP|mTV7}7EeFuKD}?j~$VmToBySn6 z)bRNHOblsNVTF3^y{}nQtD4{A7abV_FMXB)^%D#H@IC}wy2Kbj{de*dv`L8Z&}77v zf78(UZA#f{qn?kW%5^evg?g-~ztQu%&d!YQ5bH4dGeVoaEwHUa-RF4MvBn{XWPzcU zs_St%R4%u1#`err0UuW8C9{GSW%le4`GSMkE@}OaAP@JicP8=SG6n53e6MsZd1!+{ znX(5fy8cVQV85)e8_YD;4FbWI4u*g91bnmbM9Z}scK9K{p76q$@z%Eb#P7Ikw>ni5oN&S;xViD% zl07qgZn<1h^Wl48I23@n#{FVJMquV4gb#L)zV(>N`_*>f_UK2-N+u+(mFGCf%)ifW zoWZBc;g$$v)L**5M&F(-=$;%$)sGO~Pic+)7JdOj3ZGPBG1VQ#6i*wUHr_bm`ALDP$k#V$OL<-13*7@6B zBP`%)yJVep{zZiER;nHnnW$Ah{22F{rxU8}gPY?JWK&QPps2>}mQP9uoJ9PUu8CIK zo`r?(z;?2S(_%oPSGM&JZMuWQlbWcYMTo;M(=^jh=sCfvj5^41$N~* zuzyp%6YKU&ybIXpAx!*-%@E`D6ak^YCpR&Sm16ztt~=S;2Y};ANJYvNn;;VMJ!Ioi zC4S?hj?st$Ee0awRy|S~uhPky!iK>Naw)qZ?X_u$?We{w})S|4Q z9C~H(mK&pNGm-66|3nYH>Z^-6ergd4H4l!t!VH#M_BK)J0csZ`R1M7hK9_fV)tbBF zhEq7)G~_VoNi4U;OoC7tdAJvhk(k;mltyI`lzT{c!aVdA=a7i!kA$+M!CQsX-A zbb^o$Z;a-K5U@bQssz}4CTjT4+SqvJ2xI-TUOz;YY5B39WvX}`4tE>}(L(eE*bPJW zGy@+nNs$Iq3;w94&4>gF--MG_8@M0H9l!DNUf>n9@U>jn-NV$9!nJJ47Y-ac$;+E7 z{dj?se^MCMn|dei1eePYJFTY6D_aD{VXZUVy9sgNcyKOKq4=dZXC0ek%fi)1cwF4 zzW}GS;bAg6gO;oet@b9DNLpG6-v8Pq5IT2d<>hOhoGuJ#lliruf0H<9^&5R=LDeS3 zdIx~;m)m)Y-;VoU#%ZI}t;_Fi4 zV7sNogE(@7e`fVHS4W;udSQU}D4)40gF* zhnuorEbII=!jy=^%`ADPAhc5Jn^J-`ZO8PDt?U8TB{0Vr^CxCxRd*HJ8{E%-1N#%_`=l*RlzewMh2X!78J|Popav&N?L2(k-Dzr> zK-m)MKL&oOzqi0kJF~gdHqUh!v(7Khz0yG|+pbdy?K36*O!EhLQSLzg9Nm_t=~-L& zuv!|J^Es>v>M)tsw%HEpY)H$h;LsT8_`sS>F;wHx?$7bcY+Xqi(Tg4XSo1rqmYh?z z>Vc+V^n4QqMLF1xnmLRLJEL8m5W8BN#sZm=}1yK8ZGhfoSF4#h3F7k3HL776Yiq{TxZ6nD6pIp?1F zW~S%fXTHA@0uOud-(Gv|cdhllD?K(rV{t8cQ*^!4k0zkJ`~EzClOlb1pneUPSqh0L z{>GhDo^i-3<55um61I+g(|QbudW9w-d%Y~#dhDozTAU7qi!4Eh{c+gl-`&*{WSgY- zD&}){`mJ8DeY`naORtq$SWr)Fv@iJ1e;FqR1J-(4IN-Hf%2Ian?u(cn@Y;e);pTp^ z+y}_@ck>f1p8ynm?cUq@FVcgNp&A5j0@2`1;s(#4!^<9i2tC^EHaZ5t!+?_g0l66JL8)b+GSko3SPB;6>UA_b8AjC|Lw z$GjN`$qEszSmsHH^)mYJU_FP$=^c^uBNl;hO3i0oJnnc60grALZ)1l5mdU z2|3g_)9f^-LabmXrqF$-u`axzl|^hgEIrD8;t4BojX{hWHrh28P~l&BJ}8+?f6&=3 zYA&l|LI77Ay8u*G4Doq@6=f)ij~i6zi5h|Pwn#PuCI>> zE=3*V;rlk%W_HcAn}KHOfmzoR5vve$1ZkfMR244vzTQ|ddx)n*RGV8k+yWBX)ts+e zyQryC(;rJF^!Lo=?T-$Re1}DE2fR;F-lsqIi{@?b$j5g1l{pHCvyPI_fdTDus2_53 zu=t0Qvrk;}sFzx`Tg|^dphq%1N7JX)6v$T+I4sDXP(~eX4>3%f;W`_RA@f@)rWsr zjy|Ha!2S`!p_d>+MYwyp01=EzKlT78KtAfUmJeoWpn_8_1NY(U99O- z1$y+NTny8NfFzf97voSE1Z&ekEvBp{Wm^J(J*b@ZO#E3l@1z@rO4CdHne08AdYykC z!yFaeFAB=D$Tn?QRTlxBtC&XnH-s_xR$wZ2ffeIOR>^248OkHU!X6rx9 zFG4&H#weYx13N?#{BF0mZqUu zLqpVRNBi5eNpW`P5OuL~PPTb7NW$MtB^B1XsWG(avwjg7JtT+xXmEJ`kU= zPj{^8c?2HYtkwh71`sz^fRnQ9x*(&gnxs@mVCccbTz>p-d<;TBt^7cVlay(a(C9fX z`+@{;;plPS7}o(>K7t*`L98?VSp#f;R_|3GQckbJa|A?Q1$G0Hf7N(Rl;n>2mn7RN z={WojqN2|lecc&ePGBs9+}o{k_6|7p)L6g*+JfEph1HaN;}1_E7Qw}WT95>j zPF*=eN3a1C8>35zIuL;02$|cjMu22++?=yEJso+BBC9RR&Iv-4jt-L|>tqk$pZA zZBhA@{e#SAmMHyF(bcvxmYO>8Avnm|Ty`~(gXlLIh&Q3>fV(iYOy{n5;+8v>1e1qg zD)*86MS6s^z@^8m)j4pF>a=?3Q1R9~m;K(e%~E0CzMAJJFzZaTfTu*(&@tVJ$wAbP zO*M~vbDlj8;S3hs*;lWZ%dBTJ2JGzDdz%J>|E6IdZe{uMRaT6@i3t#HKoJWk_!eFzIl^~|5%ZSIBH|ee-Bmo?V+Z%60Iv4 z1CX}54$vp+-2{7x3F{X%@NlXmEH#_QdNU4~L50Slsw^~G&bLxu>@8M1eySt_zhtn7 z=*KO1YW(NzBxok9kg}*Ng&I=RE^c~vI{3*p2f)=J*p=s9eVendgoWouU-($HeFz;> zsh;Og$sg`FDE9WXnyk`fTnf8JK%336%jn-ZZG;fdx+@t!8G<=utV zYZtLsYm_rW?zg<%_9M`&4AUWOj1Fi=yvWYH_X@lB3a4}Ix}FMTeC`^4UGW=k#Q)D4 zCS(6=vG%F+v`*EpnGh*D)cy{4$xWV8R|F#-Z51K44A@+~qW2ciU6|GcPcz^1ol*QH zX-(z(Y&zKd;kh;hhx>TJYl5H^UR&wdaqoV+BBY|{I^X9N==s4#eTDqT1VVPSQ1343 z*<5Q}vCBfd8xQi%QTxw3M7{s&_1w+VdbOjg#lyMl!NXm+<`};0Vz$!Jle-=diia0v zT`P>IIyliWmKqK6awXSn52RP3#esrv+}Z@jC|kXq!7QsJzBM56zp|ZK8gEW5?|}w^ z>@H^dMwTn?My(MdJ1wh#YDegR%-^DxUXw;+L|GN2n*~c1F{?V3RZ^}cVjjN}-QmQZ%?EEnC!X$uDv08owZ`8h9A$oMy%% z+y-y<*K9BV;$&pg^RE`BZ1m&-;IX`B$nos&ZZLEf`6}>!me~OP&t6dxVRnuqmt)|G z)H#H)vt9)&Ec323iJCs6Rf5;gPevYX=x@u5hcy z#w`f4dt*DNvxd!23O!^TE+phe{HNVr5Xe5%hG_CmAA!miJE#mV|K>M7Huug?Kh$Y1 zV3D`p17g?XvtS82JPT%yipyge8C1xYKZApMD0wFiJvUc7$cwxw7c_5IxyLgG7N@Hr z-YY)pt761|#a2p_-{+aZc4n4gUI<`AiFGo$SYBUF5_0cR|KNY;2f4Vt6H=MV<%oj1 z*WHuvv?R~ppF-~ht@UF~co3s6>BqGO{{`2N&fEBY2izglAnA>O3Z{+otJ4TRO51%4 zoVw%Fp_<|4?v}42rc$1UOA|8#PuV^{kDfHFvaohj<@?$qYwGQ*Jxd(I& z*6EAD4@fAvHA>)HiBtlrqIXO@Q<5Mtd0zJs>gDS+Z%c{&DP#}em&hJj*+3+{)Wx91%Q zEx59h1Y=e8am#E*U3Wf$hk*z4nW#7vsqQy7&NQE~q`@@5(A=A~cZO1%kM-$8D z>iWOprj-SrNchf=6<~jH?DR$_uk9N&VI8_t++`4wGpw&T;EU@!)8p=qDfx0~o;X$ZFkN*cNuA6&C#i=Duk}5Of;=IMt@<7Z4wPF=qZR6J{gM2w39<_8QBdj>9FpyiFRo zJ%ug1r1hOCCKm0qBNY3t^6F-b83PU#?k!%o2n(HTi(k@&0f5f`3+VjEfWLY7dKKj^ z$k17Cd%1&azbJUQrR2iC!V+L~yDDT6tgzbw3!f{Rf0oU&eLwa&BNv%l!O8f*!|`Sl z@rOnWrytMld*Tq&Ybkl0^8SyTLLl6-=9dPl}6m5v1MjqI0PVyResF@5c%8eGCV=^YY>2-h8;pSND?Y~*0F;00N>Rl@lz zr@(}US#SQZ(c2m19k_}RMm4Ro7wy9{Y6?myPZR#$cA=A!8Rdnu=P<5IG=5vXa8Qr)8AaN>&YM#~7yEV4&0t(}F@qqj_pxpUp zuU16AjEC|L5t{`!NJ|a1$PSeY5TZu;XQ1-$Hu1aPhT0II568`k8v2e_LmX#Gx=ejn zYC+BtYm|tRhMr31MZnxa38N>u5ZCHPS@6@9^OXQ&V?<|;Nzsr|=ZLvOVIO4)7s&ki zq&s_a-d_PSP?~)I2E&eptqc3rH2BY!-hF<=*t;N04Xy_YXOQPgN4%ca@;Ty)&$?I6 zfDA@K3HbMU9il26BT~otqjeEM1f)68Ct7XqqaGcY5}{t zZxO4GhvsI8rwS-ha|f!nQnex~Y)3P&DZpRcW1ANUwJ7^NtnU6nUq4Soz%D-i))FDA zQa3L}mU~Id<)d`CQ2Ad8h7XVc-Bl2uT9sSpylRkKdrO?RWm8QF zD9vcWy~oS)O9iZBu1ce|-4o`sv&E!JE({GIt1SsZap^Hy5bT*~IWOWebm)}zGiZ}_f5M)8)pwKU$5)cZk@ z>)|e62*H}qy|^vuDQ)3Xg`}X*>X^?T2yq`(S#yV69}TZ)sU4FQ`Kt48-RRylVo?Cj^{hF6rXV^OY{YP+Br~ZEOB_77p1?t4 znLxlrG_I1;NMXZ*(a8JOfq|{v2!O$eR-KPWs7HIfk8$$U>a;}iK>I!7EcvO6jZ?%; zaobTs^jt)p5S=tkCaAKM^IYeSClCn$wHT>_-g#C5D*lN>-v#ta$4*LLOQ#-0#WD>} zAu*n_35JO(BJb1I{knX3LzLI5Xfu{A0lo7i;^cZHuv6f$51x_}Pg7D4IqeVL2|>CK z&}5_h*BJf3BceB&p$48j(_$T;A1g`Cfq2_nVDJXu{U2*}c?SK!KTR z=ly)KzVN>v+0X!t&dasHlf1_fRnp*1{VgK#+X|(vkrM$VUWz7k{*(w}eTMP7SPcEsrDI9?60-SjfmHd#~KUIV;7*}E&F*}s)XpC@wyoa*J%Cl64r8fvDAfvz`1D_Ts|ujcjx!+%jmPlG@gdp zY~qjWiaSqj`^6VlN~k}Vq(5YK2LEE>zL-8ec?euu^u%xy5BkrXpwKM(Y6!HP}J0)%6p#7fSw;G%gra!G5UU0|y_;t$N27%w#pf zi2YsOA(K3jeUE4UZ!aiMBvp_0_fN>NB~@`TF~2jx1d5ugSC0T}dvCt3IomRSqDDfn zsjP)kQ)+zAD!4tm44G_d=3|75I%DJ6=n&u5SG!!i{2V=pSO&Z;rF@Ad>OB=}CDu$j z2ZL=j0QJDf+P2!Y7kGM893i4}Q8!BBA0r}W5-Ac%vNQJXY|!3m7TJXrl$N44H#di> zgM|a|B7yt_1r?-{OdsU)SuE8trezea;7;%Oa zh$7s@7$ZeKML~N#s~2DWc9nnskOKu-Hggcn8;B?KhB_|4?)A;tQJd}0l0VPQ4KV1wqQ6Fp{o`L=e#C$M zaNTG@n>Qqv=Vb2DAtGw*X-}KKJAwJVCD#`g*H=BfZ!O)`DjW>zW}D>wa;ke&snTS| zZ(kk-eaD5AcsIAHG_D0QuHBidtTP*j?OM*-XqWBdIq%C=&%n;Kj}&S(9xaU0)6zb5 zc0%P96i5llE5~(zj?{KbIXc4f_o$;3QMhtU8+md&BH5%lk^PiAF7iLCM<&QykZNUQ z!13CY+9UxLpIva<{V*o>lXy(-PAyt5vF|^Be!l3$k4aMcXmpU2ElxiAyXF0D&FOeZ z-`p*q^ILd4+7_Q`3@6UNO#&Bn`G-7ud#Vv5jlCCSosm@b-7<*-k{_cNkAgQUie8YA zsU7u?pUluv;nV%Wwxnm_LWTl>HoXJ4xN^khb9T1KDlP2_H!f9O?cPpvF*0I~ja47a z9AVk9jr?gIU#&lV?QG|H;W8+f=OQg9w`w+Ud3uKbeuQW8O@g&L56Ye@GQVux5?ODP- zgy4QdbwM87xm^bhK--7-NPI{n@P9eU2pey^LSNi>O!9 zb>;z(_aKvb+k+`tV4<4X(m*}sW0!|dxhl$^8kB*BM@R*Aa;+7Nyr3%?=e9+RVE*g* zpn)G{nkfV%XPzBeY9_Q=UfhirBB9Ljn)tXc?DcQDfCTsAc`Z^J(c^8&6(H(c*nl)35^bDHhw0)$0?Cx741P&yiU=#WBG zo5%RG?Y7bntR6#AUDSNdyIrpmqM`<>K0qVm;xxo1y`;WBJdL=aa9@SdtPK9i?El%x zya~a}|AYQ}9!cPNH99FwFsiZLk6c)l!pGr2)RSW8N?KYur(kv|yLzi}<)_n;a3DUm z89-5dxP(N8Y0TRQHr1IO1Pt;363~smMhc65&w=xa%pgP^+_{wkrqM(iaKdTlwfX7@ zIr7FAzqc1kK7PC#!IYMj{ZVk6t~ptawFo+Tua`p#wfEclxh=1xGO*6xg}w8`Jm_kO z(aYC2@DLpL&u+07D|ADQ;p*acRq=;T$cI{@$GQn;q#2Kfl#WQZg_s)`DdTVG#$@Pw z?ez{z#26;IIV*BC#Qti|g=+-gOlselvdho6T>tOK5MJGe<$!7!N8{{^0&> zHM?G3Q)@XWywzDHH+$=#Wj$NDVwQ(E@6g#1T$qQ0!~W-`^z^)h(o!33ZS7}E8R@5Q zO!#aI2Jjuk_EfKqg!L+(kI6{WzN|!4<&`@N@6B1|U2B4snczfZYl@ z^pU|&T@{H6(17=Cqv+3GAf1uSxo1W=Y*|Q*GbCWuI_JUbV=*fHzNDvc2s6g1e60;} z=X^N33Gt5winH)gK3)w@ywL2}qZ>TDT=6Fm76vf~?C6TC7{31=^(P<@s)QUmKhK{b z^?i>3sWHkf=d3m7hu#uM7&-%p8ZCUZ!Q}3)eG}7g@xz<|Ulu%~BWSk%NA}nwF|QmL z{LQIbo4F~g;?>9QThiNoaOWOCA(Isr#|Dp5a-5Y*J)bR|#}eW@!s!m-lNFBLznj_l zOlJ4k9Xsc`r1aB>;XOt4mNNyy0b_v>U||7L)l#7s3^FF-&J_<3Y7ZLPmbgFD3Xh1u zU4-*5`?cM|L3mU<*Uq)-Hzg+e`jMx*6Gioj{G@`|&z{_D$|*EKZCvX+V1?N2x#K?D z<;G$xCNFgP1Iu4W(+WJ(!BiXW>nrvPU)&=uTMDmH6-FvMc>U>SLO{uZNRvJORN!qm zW%aqBPjR7{4}IAV?b=3U%JiIW0v%Y5^GF|C8S1o0_G$UJF>p;B&9U1+hLSIm>f*idq-9DCAef*-`c^UJ_s9Ic}N^D&6l! z+X0ShIY8Wq)$j!U1<7w+PGW^4=O&-BPVZN;xqVl(AZNdq zSL}b;)GBOyG$gmA!sHyyn(sY&yyEJ2 zkESWwxjs?P+&OIdE#4X-IpYyYFW!b?FIE1?ws<1!6plA`=!C+5_zJ$D40M#~f_zcb zXgc~_kh^tP`8gdp39)%=IrsA5jK;D2{i_$0q(e=)XLoo$m%D49Q&{x}MBqHzR7(n% z^3*H!_gTqzi$$HrDat(Ks0ZCX<(IyP?|HY_fuYLZ6|bo#FZZ3UIS$yUtB#%|YFHuP zNT;EPR~K7eJfjC!>NXWPgj5_Ib-m(nDntB>vYGYHpvTswq0%tG;+FgC)kYPA8BIg2 z&7)d5z9)9i!%xgao1SS9vY4nIAJ-EK-IwhZV<&40FKMe143z!QlQt$!oZcoR#4E97X>?C zeVPQcaqD&73K(xMIdq;Zn@!HE#-mA0f4^=#ZVYsplLvGkvmP+7RaTtp`t6%hN#0x) zU{%4!(z=`Cp7#{z+E#Loe7>gr9Mdf&+cg|K*SW&DD+4l4J9RKS->+6l#pv@cAAq)2 zzXhWnwnmAIV1ABE(&*~(mc6;F<{^7~Scy2g&D|0UZ}#>k+MXQFEH7goliJ}UkIs~- z(y=-==;?g$YX89`@vU?$duncOTPKY?nC6XZ1xpl#b!jCOFy=Al@*;<~H`-;-P8@Mey2^t6SXd zyT;4=*;sEYH1XTDcod}*E(_%pRW%};G1lVaXbr1;IZddZ&+-R`46c_{j2)D`QRwrh z5c`>f+r!1+Qd|*QG6s*A1Tik`U&96O8QnREmOI>beo;BG$AC`)8zP%jht@tEtz9F_ zS-sE%EZ;EtB8X}yYB%U_K?AWDYY5e+w)8hjQLDlXw+JfZuDu99+b zy-MCFd1xbMDS6U#Kcx5tSdELt1U2#WpReZs{)vw42{{T{oiE5W>0I4}IC#`zD+a?I zD8NihjB!l`TBBBYLLFJoA-?lVkhVeu$q#*_16}+FZJkIyQ9xg*mRfC)y4zl)=~L^I zt_SHk+zK>$K|pNdD?!z*ksND20w?IXM%FoiR_C4h0x&SQKUsj0MR8e`aI;Q6bkPoaMA7YfsGt?u%>^GfR+fD&G}{GX|hrgWuYaKR*xmOfpgv<>v88NzLsr?W?#_MXn&6TT zCCwZK#h(Ro&1V`kQvWdRmgO`a$NKB5id8G%gq~r?Or|Wm`(~O9my?t5-F7AJORY># zk?x>ljDv|_%$_!%Lh`f?stS=7V$NE_L&@~ss_qGe7Rf9_b^M2GiHE(aa!BJ7wH}-I z{eK+69%^!4I~_--wk5+w8rRT*M!fw#ccYngH={aUqI}BdSie+NXHM>PBQ-5cNOJPl z2b~BkTK(XlZmZUEJF*<9GY?3*4T7%KHBXN4hTIamIwhKIko;I4COA)-F#EJi4UDk5 zFGU|@w8qZuEsag}gQoGKNzaw|-DK){-|~L(;GE#EFMStJ-4!QrbMK@DK7I@cHB~e^ z-MPKmmblBoXO@L$^7_Q$zX(3h@{Mu=ys;l1C8_;9Jrf12Q5$2gzPg%GQC3`d+H3vi zaQzbtQUMo6hF5PGNiq*{!PN2A+kI?@Hz9OcbcI~}zM&@y-5Z7!Yge|j)aQAAV#;L) zQ&k)rWs!r>2l``=GV!>=bl&?z&YO$HdvZjYx}PoKbx-jv?ImSUK@n&1S$D#ZwYQX7 zF2}8^XIx3C-q^RDxn+ygVJPSi^dVcZRzY)6$Xr9firf7@6<)FcG2h-ErDb-DMuR3Kf6(aHc64wp5!)<~fg z-k;|ud12Co0sb=>{!@;OWE_2wd83IYIVL4NJwoKDlVHKv6I)YL(`{#z)XT@GuneRX zl_ma)nWW_cb$M%Fduw+zvuM!FdrpUh$L86qSFcjWxFzj~r)K2hxbdRyJCjqo?WSl~ z+`*I?5+UMjL|E}uFCO#EXzopOxDk@ z?m7ZJiN5i&dDiNvdTCp25|~%k&H*3nsFK6?NKXfgBrq=q0=$4{glS(ZS|&2Nw1_R% z=)pr#HYZS%kTJs8IQ|o*%;$Ohq>bRFeD50x^Zw>dJR1_jL1d+2Y2!QrBJvheSLt1L zvnZX*vHaxw*a3ItZxk;gSZhpUV{3#DL<8piOqVWy`u22D8dx?@1zKBZ=@VY#?7jmy zkaRP1Bxk?RAZ>&0r>xlxi3vWeq8`*H%d8-}uhAxT{|Z_2y_w{_nzH|Fz~c%ogl@sO zfmu(pvv*VnaE*Kgy$9){@1~hTB5sNC>sOzf;nO@ic<55qOfba8tZ?PFxM47!-+b6) z+O{y&{g9nEZzC3SZdMsw_9O4{(12}R<*crh*QSotl2Lg;rEx~%%$kcr?U_Y2>+0>6 zQk&kQv#38ly~I`qp>d-Xhq46VA^pY@te>{tg8)(O6txq`;=W|I4u zccYt2uR!^1rBukS^u?<1Q=;B;PwaP8bCKs}U#^7qpSqh}1|Rk{bdJJBKwb+wflIe>n&CQU`@NYgr4;-?Z^in zir%-UHk|SKll@t1BT!Ls1d5`93&1g`69}pJ$(MAOv^$=A6`Q8;yl<~f&^8HUXQM~A z`G9cm?ZEoONeDRiB$&j#}#5@oNO#mjw)*=$EhPt)i84e0+SpSwL~1 z0N{gE?{jhctPi$z3^?xy`SLT8XE@;SDrpLFKZ>p+ zswA`{w($tne015aK8IylQW0@fh6pu~va-qhe*fcfu7i24s~;oOCWk56^;-eOU_1L& zlS6iCOh%D_QS@X5gcIM-c%4Eu^H4xfFoWVREZ^BAr-oNhRx+lV*fy$4-gnFDPRMTQ zmEkyg!N^L`6@fhu)N~yJM(G?tjS*8?^u>geNMTV zlc{j2m+2M4(t&m<=V%0y5~mgu#wlpB@xUxN$q4t0Eg|N3XSr&&k5_zl(hL3+o5JB_ ziPq971+@KL6iniRZd?a3hq;CGwOuSb9uLwbFh9ska_5Qqb7Nv*)!R-`H8nTmwXei$ zcqy9umW5FUESUKITnjwvZ*$)y)C}0bG%pDpa+~TE=1D=>~U6 zqROEkBRMh>XikEg64&cbN4YWzE%78nsim}-UI9iYo0O#|?l7todyi*zj6T*36GYd% zd2qv5{>Ygy;BnJFXse}T`H_Ve$)@Zm?t^IY_PZTqVuNX$>bKk1{Lx?3JdzSdm9wW5 zm;`>HQEqZy$EWK17ttBkc~bF{?|*UBSeOruME@>-pv*iJUaw_KQ(ceT&*W{vy^;2_ zZ;4_9=Mk{~)kZH;AuFbM#V|Rne^!uR@PEV5|>uVP~hqp$pq1iQD;{So_RQ1((C8|9ZBlvXOB7>oD@p9Z$yzIS)V z+V*`Y(v%xf4LSH+SksD!>OH5jN6*IB=gWgv!<12HpPn{4`6yKKBl>zNvU?I6^Ml+s z-dXa|PyCL=%fc+&RCBHB(vO_ooH}LEZ&nwAO+=nQc^pdDqhXS5p0P-3E{(q+SvDts zA$gfQqui%9DxeTzw58sZ3(nox4NDDneb zr>vzLYqziMX6XQ^rbbx0ioImMl%cHSbD022X|~1henQ(LeZP#%xpc<60BzFVI$m?QX1?dEhB60a6!MdZG(suA$#q= z;J0}ey*sX`y}Sv+OSMOMWG??G7KY+Qf33>&&k*;HK9MT$t5AOw@;DRhzS|K&$vH5h z){%!6(hTn1E^v-?jG(=d=KaV4nw94J@L6V8Q*?hu+%Ke|G6mc)jV7vKxuB~ zAnjB}{yaaMN~1ot|W`*V2!ViTL!g_nDDxeJMO0jE3cZQE(tT}d-4 z();Yp%wOBHJj;b)R6nl^!@My_XbOQNELKjh`s7r`K&=||UiH^DQm}{B*9nvngB2)| z`EfYG`=m|iLz()1A7O2#TrP)+nn4fu;^`Rm*KOyYjQc7(Pk+%H2lwj-Jrp_0l{qW~ zP$-#xis~BI*P_5n^2B-PY48;KQuDm?SQY%beYE~EnKm7e7?Trr!1V=|F-&>B*aCPO zFLFUb*`R>Zwz*HS>t6fP5-gSPKQQHR$5W04j&3a|S8nE`jDcswU*>swHiI*P>~KhagoGK_3a3fc6nG&`zM z7-aIyYmvQPb(yd#qtpK1UH~1;oC=0o0(^=x`>E}QphI@SU#t8F;_&ZN-2UQ36ABT@ zp48ib5K>26r$eD-=B4|$7&a5bWdwA_495lhC4DXJ z&Q9ys*I~Ij^TLrbJ-3O8#7^fIR%+K>2@_!>rV<4-D;Yo0?S+vp>lk0<a zr@;5BOzK)v-)PxXt_dAWy!9ZcFhf8aQtkbMmKfov50mV#sZm8nfn2 z%QxHkS7o7ayZ$9H zqe+>m+0!(MFht&09(2N=QXSZ@lE%tmhAf+Jrnx;3U3v8^99VOqSDWiX*lsc&m~>gT zCZEvb{jf)!#@)c`s!wKTo}!=fhM|k2oo%-(j%g&S(|G<;3t}Y{oYSqsUa8kLZebFi zkN^e>HQIY_Gg^mjmu9EYsOLdkKsrLN^l-mkpYGaQ?ieliO|{yMd?ReOn$n3$p>u0y zH$K67Lj6Y!x-=zIe16vkjnnSL%fSPofMl}N!CLoQniNqUC4woiVfR}lMdA*!%b$(S zx04%-r&>)3nLsT2K&cAWn_^|UWM#Z`WOvbX#pn$7#4nYA#n7jUxKO!GAz(#wVZUPH z7>mPosI#zU$Mfp7FmF($Nsh7x$Q2EOeEGX*1!v@`fIQzYZGX3QpD^FL&bhGul0crb~5u5(` z%jROQsh?jj&KG?;`{xAcsTw1d*IQF!>?@{+HJeh7*5(jkwwp)7r5_@bS{JCJ>QkoV zlU%cU6jb=KBnCcD2dVeD*T9~ay-Z&yK$_Jz(o3MeNGmKUnJbfZXPYjd181bb30R2! zaligg{PiA>#2(%Fc|i~hhE#i*7I~R+=0> zg=9vSlP^`K>yfW6@vp_kmIw)A=EDMkWqk46?da()!2xt-pgFX*?~2kMnJFBzt^tPv zi$xevtdzU+NBLr}monjt#1d~lZmyzhJi(&$WH0O7UJx1@E9`ceKozYu`#D!$#AEF|4I}<_h6birpdDSi`>c(cw&wjYxs8LCp1A8Q z9LJJ2!_^=TtedWAD;;48KWw!>+rui06#NzYlEp;+3n#u{K+esH7(0uJwm?v{o`g_% zM+f7!=l&l#=6lce0Ba!Q7NZq%PCLZBzIZ&v14WT=wyV=Ij(>eu%Q5TY6!0KGrrDvc zBc%@3RRZ0v8!kuC!#e$-s|?M@Y?CDrR++f!5f#{ zx?Z2Te8X6RC6jF$5^wq*k#0Q;Hhh(sl@oT(TGYSn#Lq|{Hh3G_n%Ygr>8JpGhpA&^ z+7Ax=0yQmRzCBwq+oviWSZ_YZN?K~Q=-_oWQegp9AZ(Gn?D&`(5GJtY{aQ0uZGs=V z6xQ+9FQ6nXg`*?N7QzEF;p|o?@gD7hxzNRh8TxMRVRW|KIBO&N#>9)pGOMNn9yhU- z6))f8>hb)^ySUXqN7QNG`z`>Yd+v5`$0v-Af+8DEie7&Vf9bw28ZHa&l?^{lhDh+! zmyEP5q#j9c!?C?SXcFT$VB(R{-Pf~Wc|0^ozd1*VH}5GP&P%O*SH0aZ7(;Ki-B~nu zU-sp#v&LNu8v@KQ2P$o|uck-TG6HUd#|?5eNmPtIl4Yh}3$Rh{)}8-N-n zX3N$~F-dCj@?V=5OnJ)tjxtEFs^(>ZqW+3JU<8?R!zh~UEcqiAkj4=?0BdSWqYd8S zSZ~oQyX|K}M_P0G{twEx2kbJ+LvID~I#bD)A`X~6BL#HsU6d4(B6}&DuN?F~qM4K| zdL|WC+DZ#8_il0}N^MYlrpvOV7GD=3QnJ110ILwOwRvM4q^*h1Hp1=@JV3W`^H>7r zWw-D7rg}O{h0il|csucn?8QY=BM*fs%VjpctK z4g}jBS&OS*jpd_t3&$SZo)*yJrP7d`=hn@8F~|ntZ_Ht6Y3V4`6DFFl26mPsp%B;s z*Nj}x!k>MWOYx0E?Vz6RF6`d+BaOF1F8+R8>rU@W+OVmtS(3s4Vt?hMz3S2Moy2yk z#GOfTJRV%--bH{-9Y%^g<=Y)RH2pqwNH?#tA1-#QArF@Ik51u`#eYPmEXHN}J)(M# zH~I4Q@XwaRy}e1kwrFSP2Cbpipg_=p_c8ks1!#e2VUX_iZts!Z_0Yze7UfXE*3;U2 z$rB9+JsIh}2W_J{BVogt_z&T0`Is#Z40YikbFO&Z2Z~Gr25<^}N{-O74lUB<%|a{~ zUy8b?8*8D{EtSXPS8?7bT8khp*X~xS5bUGVklc|yEn|!@UutJJUf=+}yZ+U|D8KgH zpp~l5useeu13Vc1Vl+|yD44b+IqQq7z`JDK>PD;8E2Imy8@iu+<=jlA8e8rs-Yor6 zTgB~ej;xP3t|=lQ2Of}Vf3C>jxO7C2)Q&VmK&KAtHgj{%z`k!Qd9xslmVwyvqzYzk z;5*39-5L4${!G@Em_;j6q05Ik)w|?M426mMLQqvsFQcP?|7(LYTijEoF|+be34670I84} zIxxPcglBn^;|ByU5ZGw6JvisiD?kKjO5QJ#Z5VsrNYNdYwOSlHT<#8*E->$hP(QnD zYI!Ih98vx3)L=1TW_G?l-}B*C3QU)6^jzuyhD2_bE4&vnr5D5TV;K zD&3hr4d2%eec3_9Eb>9(;hIwP20h0qF=fwv_EKCwLG7_+&Qe6+pZSW$qR0WF$Pdpj zaU_jpsdCyD;$}o7-r6RgeXk_;oH)38MgZ^-pvBk3%MqPA0+?!h%#?iiI(Vie3@piA zkZ*$Z5?6Zf&uO_fn{)*vZQcNAUMEFDH&9QQNQZ{JJ=U_tbySV#ItBbgmbFd3h@bDP zt-nkqmBIa9Sz{(QEbd5hbcOe6)WYFc;Zqs1;I#my4Zl@` zkBxPnVAaS-B;eiKuSUpTI=#%)i3yX}s_pkO`3R-bN zK$)+|2n@2(QIgVf@ig1r{El0hd~*^HpZI9svh^K!z0>tgTR3I=ugH4zC=59-KlJZV z-0{zXSaAnt4XuV^g31#G-Ak$(E0kG=`;PZodn#XY21ji>F;X^^-_|7eIY-Aza!2X; z!=@oN3JHljPI7^If=OCDCBo@RJ82xeT9b9M9rrxdUK)EjTu}Vt3urimwyqG@cXJptlLj7`EP{MF5e2E2su{Co8yoLR z9JJM6e^7o|r!{*f7IXz?B6EK5Ct)Q zm^xsK`k_jHUE7K8)VevR^Kd0IrvK}VwT`}xq{uln@OZSbQtV0y+ewxnTKrU8cj}u1 zA=|+@G?P6eS1No%aayL&#NJNdu}XfNqc21K@+dLxf}9LikudxuuFf3kh0-(ShB@HL zPc&z#O7rbc!ou0f9>>$vW>QNJng{E_=psJOm*OEgt2$^QymjAotXHqFzqs^FkP59c zR#z$wCswkq*Vay_d|axTOUgzSWHLyd2>JncyjSm@=g17|t+|Fw&Ju+I@2)j-lq{W1 z$Q?x9hnvy{hRa}PZQ_$R8Gm&uA+Fr=R?F=|4#_f%ybr`FurlL{zMv#)67tgoikTu( zGf_jgq6*PBhl}pNTw*5#)7MO=_uJ`n@<*IJRhf|yarwFTs&1ZrITcaOZY8a; zQjq{s^1pfWVKz^`;GvWRPu6z7e!bSAt@K*t<4VgHB&7r_vn=BuwWRWs?>cSuK`|G$ z$HNX}y<)`OZO=?&xTe{YhS8k)%@%ylM?mxPx*F%u__E+x&KPC3GR|*29=lIzdVb#w z$NhrTNBcxnO*4TPSs-njLGkX38yZV!w}p>k%QueWn_X^Mvarm}P*`YU`8iNCl+Cv| zezWx&@ZT_G@)LeGzuGI=^svD|J~rUKuJq$WD{GSf2a@}L!MmC0P?(asCYC4s;IUlK z655{Lwmoe#MkOa7R9_zg+w!JxIH`=4CCFrUU>uxkBcI+jzdRf|->nC*Z(WTEJbvJH zI&tWavGPx}GVcN#P8F`#W_)MuP%sF9`}LQ@wikHu@Q=2GyzdEqC1rX)Q0byifBM1N ze~DeevK*I{drg@{p0Bff4wpe=;p+oR84lV^o9G#d_L`VgFqY_7d%WJJiJAOF(02_M zl~WRFmR#FD^FWa81#}O)dQc9Gm`F8WJ%Og!rAO zCm9=BUmnVK71->~H5)essx=R7Dt-0H?u-x|)y!s~DwjD@X;#ay#^Zw8X;8kSRpu!) zZEjVnvVrLbO6&)A1GojqKf_~gqQa{B-f1?+**^}g- z@4wv=@Cr?_ij$8I5p1v$B3;cJl=4OdUkKmr(T`D5f54>S;EDP*9B>g$<2pboIHDkR zX_1ZP9jeC>#XAW!RELYxbFiI3bY-At$7y@$Y3U!vKDDJgM_nXEV(cS)xueMNJ3t}- zovRWIl)@&-d`C)@p(r0A^ZneixU@x-I4?j1@mRW|mEJI@L&U)Eft>s%!?&!JPGZ|E zEqM-Y#G~dgLAHO0=Qj}I?V&YyB#%Esl+hzTyYSN#e3fk=Jx=4g%Got3?hKfyp06w) zDrqS7jd9o+%k1>x)DNdCU9ZW2wMZewL?I#HckIl*fA=mO%6?SCWFHRMTZBc2Sf-Lv z`1~328|JWIASPLVtl0sHl9lbb70G}&5j*_|Y&D2MUs+k%=3+}SJelFg200v~x z1b9k+s9*7+we?+z`JSpOO-Z1{k+tm!mEW#1w2?2r-H&ix<#@QKjdnmeU2+SCo3yy} z`wnxz()6x~oq__ysMLtfNJ8@Qt@_qRK+B_|vYUVcMLEHr>y>LPLI&uTPd)9kD}jT9 zQcpXaZJ+e?2>b-EuJ)&-$N?Hw4#nY>J+yO^@Emn%8WRg0;kHfcvL6r2sD>o-MQjl7B}b5 zfsAeu*bKC>Fqd{UsdZ}O`$dV605e<}357gdaErN}0dUD=&laiDMZMlBe55bi9{!_& zpbKY|cxaNs5P4#&FK zjf|UPTE+0X<6ru|9`aaJoxrzsE3U$-cWM%Un6mV!cV@vRHxD~cpqG6_6xnmX&% zva7JrtEVAO78bZXgNt^+&2nSZtf5LItk2RF3RttKM@7&UK%|PT6s##82)?8jNvBx! z$Te{IHJklI5DmV{0oq=fuPh}kXv|R+y9jZtp(8C;&dZ>-t~xtJFK6$dI(tgYWs=o4 z^&BPUXK+AKba=!~9I9cB{hY`Do}G+{&FFW^`qI9 zRoGI`rozVKT17?OuiStW8ubq(6(_<;A~{!`NiKn5*96qMwbcK{i-)H&Ky|tN8S(g_ zM0kIOp~T8B6~3cj$jlMJvsaBA9$Bw|qt^At_;|o&EEhQ?y7iml_MHi=tt)TMNZBX) zJJN{#Y6_97Ft^Tc#{+%u`|AG7D~Hm)Qv=$+_-gY_<|jrJ5u@E~;|x+?k2h?H4RApb zGI)!v6%#h@)b5QkZ`8s##rNEQnF$k>!785}p*d{^B?w%}rwkpRDy~E)WfD)BF-5t~ zq;Z95t>ZbY4o2pU(Q5%zcn8fD+}pq?_+s1-)gbI_)9u&32e$H zDp9(Gp3}Q6yxtVzFRgX`mX;SQ5}csq7U~Zc+GbLyQIn@#u>)w&YIIq}ua`i=_TtwU zjzL8H>n1|@KYCzwK7x_bX}@7;4ehZEWJcq-noL;JCg%>O68)&FFxsM!Ex4UNN6E`c zbvJXf#__$@H=|&$drEes9mAhHWL`YHJX8vDrql_nfc&iVk6%K)CXC!)=R784@Hn7C z-rmGt9cPuy4!BtJY;n{83zRR#T&Fo2PRmDAWIiQ--|=9tt*OD_2>zKF(Oq_cvUOFA zr5h%{f4A7!$Wx=$z`@SGSv5AhdBbZZ&Lv8^!NvsLt?kB-e+&aR6&>|HYevo9k!Ts= z5wxu@nzmbhAL7F+ZbDBj)a+x(D$w+XRf@KJ&U-JFlUmPE-$RsIV6jzRd6x>ERa^cF>ZdyDXdUk@q-mtlKP0~ z9ORJkDMceaaNm-pVhKHbi)^i)v^}XJ2sgS3f0tGsdkEokX<+OL7{V@>NJT3cEN0Fs zDv^;VB9$PkK$1V!-(y9RKQ}uwB>U$fdjn`OHpsk4u-4l}Rq2A~depgV;}f_?0sS^W ziOk+9BZ(+K#gFeTK3v$4<0Zg{s{kxslPNPU|@jVUmeiF}HuEo@olIWc?hh6s7LyuZJ`}_WL=F z3IKvy3oilVa~}Y%LFKAarUjAqlzW@7f}IU=bJM%>-PoqAL_*LNOH{Qqn#+>bLx!{M zvgugxyTV+fMK`L2JQ{h@tOpC778`+!N!_uqz@REy>%m3me5L*Y#}sA(H-U2VrlR&W zDU_*!v7)@ju7K&IOx;HTN+{*#W(VYgN05OEP&MqL7}w8qK$>yQ5XjGh zo$sV)>#xCN!c*4p0vDQ~SJdD9;JSs(tn1-f|7*?Ia@h!hrUZ_=`PRiqvR5a1!H6hd zjXqI8Yot-vQVN+MfZ=k_Xe-L^W`@NQYovoLP3=g%HAX9`gDOl`rd?3LPLM)g%1L=u zlv3I2YJeh@3-GSZ`OE|xUmi&m?2VrMr^0nbK@*-9t;O~G^t?BuOiRe+PBq!!_^yAV z0FOBZYW^sx-2*1@n;2Qn*QckZen~dCnr&VKb4!)2o{+HjL*d^ae)?U#;FlI|cW!&P z!(2)qa95gXmP3l_8NVNN@ru_3ieD)Lf|?mUT0#EdC~0K3(}6voS_X{XgdS`;dR9D?)K{r7d?0*jvO_XA7+bEUYcJ_Ug-!U`o2Mp*v33SvTu(n zXl2P^5Q;j@RW=;QF~`A}Vcn2vh}QXDBFuhdLT-290S~EHYl2L1N;Xj_YWF>Djk;D` z!FJKhR-y7tNe4TA!zTX3@CV#4{J&~=UF^!D605AVR=6U_obtzsjKETZ8~u8TN~v*V zR#s7&#wIdw-=uhyI%*;%WqGwVEYC1qWXr+Ug6c2bdN#!1+!hP?P8SIgJ`XWk#o;iC zeKVv_bV!I{jspQbxZv!jd!iT|-%JJv+6U_BMxs`GJ0hEom9Vnp_6q3Z(vdwLEG`e> zHn|=y)lKK1Pob7_!|jmPV%_vz!|0|lprZ@7_>9O6l=tKY9oMFMY#19peQFy6lHS1d(C|p~@e7EZKnmm`i8Jj-tNXu+9U^f~TN>xkFTV-lrzhn#4sOk&k z1D!L2r_e*y!VqVES+Z-S^T*wc_R~7EY`w&6w~@((G`?#%;Ek45Gu*&MrIZU0A8K~5 zFEz9`Ygx)r8Oli?58<%1?BLNXDA}raczflP-@5VL)U$GlEMk$&tVA@DffA z1zCR=$O@m@4rzxum&UayX-Ai-4^wdcTsiH2UZHy02R|f93*AJSJqdN2K$!G zEj2DIWr7}j`>5BSGm4Z)i!C<}XbYb`2Ez7k>gzSoN7KW~nT{!B<>irhczDL==L6Ra zY&E=}qK5*1mgvWv{@T0tk>SUG_pA3kmk_`*MEXY(Od~vBOaSXQ#*RtjA)Aalx;A{) zB{|{Io{c0_=DHT#!&Xr6#^xlpqNIkqalHBPN@_^u@hq8YXb%D_8D;*o-FX#-Osb_w zqmu^5aU)$n`bj*`F-5TYBVIAMr|*1xi4NC`AICwQKiFU25g#b8;%l3D&$>)>yjegRLHaA2% zuA$n85*cNFOoWAnRV2yn>lskY`Y6@d^p^U$U?*(Bo*i)a<Jo}uK?PabZxNk7gLd}01~^(smM&gkh#Cx!0aqNqv16}l7(5X zul~y{FSw7B@ok-*p)#3@5C4d(2?4 zv`uU)k&VYiK6MZa&R*n0FNRLUliRC4d1IrQ%SGs6?9}x%i$0DIinn*$lBTBI)=Xt8 z61q;&N$cL_Y@fEaesBF=Wdc02M<)Da!i!j?7~qAjtnJw^RZmU-#-tgAl-1>e%t)4l zC@&lv`khyn&r$)(L?FX>2$YYUiDO)cnUiVQV1FMz{L;WM4y$$h(~+}Z!1(#V#*|(} zOZb#kYTE8nGJMEokZE63R;kqDd6q{(^i3OG%q6q5u$iFGC4DpsGj+YAR--a7I%uQ^ z!AUpF=vFzU#ty4WBpQI!U|)9X}7V7$vjo0@x-)4091b=sA>SDfK*1`p>KLS zb@lOCgCuuV)q5)u*)P#FEbv%gxk8*(<^n_dyN5lKiycqi2wnFD-qI@Ba*O^DOr6n= z;eF}cS6qC{)a2x#fvKI%@LbL>7vJ@PXetIy{^+{oR3EEOn(^&fs{6iaQ82boYEzh! ztgBC$LY+)okElQ@l`mL;Gm#GSq$4MXkO+mjMWyHRlR=l^{rmJMcoo;z2;Z{<>HZ@T z{10|40}S-E_(F+23}S-hO-FdNQ=3qn%-0e9&(I424&6i4&Ia4k8hp%4xedo`vsT>4 zH0rHkB-|u+BDm@9F65YpfnD||&L7)a)$F#er@!oCTCzDLC|O$V9;{|ckOX(7dcO~R zb3*X-(;|{cz5YYr>R0Nh^=&qjd#R@r0&bpi1h{cSDy7IlEHO7Xm=Wbr(xeJV)?eO>BS@Txn0ao%1t}~d zm{&>1%vuqhnxLn>q!;Tzk|fySskJ^K+mXFmYTxTw*zFdZJzi&{2XY5}DGrvGWE4^m zxyV>H`7YajVlI5VLQ}W7nHDXWbkg!(?^gnRCBQ@J`}0ef#Bfk`uR~iRwSiMlolmfg zGfaMt!t2iYRE3IQ>sL7gixC-l$E90`F)by#^J(BR>uWP;UUUO=R zp1U!OUwZg2D-6C6$Co*Oq&*$?qU1Dqj*vy&+h}S+9TU7k-q{)xC-A^redT&7f8YpB zIPog{L95*=_P8XO=)3y7sGOJ$I5a%(a)9d&yI{@37bWyKm}HgUUT<1$cof&E&qOGh znKABK<#6{$nzgjSYsjfi?cYEB44poaKlvkIVw#L!<_hvZQdzMvVNwMf-wU?he*lBT zCQaQHvAwpB6JNLRG_F#R_8%z9JZ}tTUKhN?hwCMA-NfZ-+C$%`Q*OAPYOf`${Z=Ue z0n#;Y$H|FLkpwZF(?>rm)%sF6WS&o7Li%#`WPP41L>Q*c~V zs$v?=YC`dN_CfSzC1Qha*>1C6dr9Z#>DifIMMY9Y+ZLI~e_E2mS#qQkox%j zo%mpQwwbgT;!8SA|7;%S{10Jd4ADM%bFO~JkBhonu~<0pDCt$3I-ig8htATb2t6QE zobonX-%{I1_!)q%=Qi3OwbQmXiyARy9K}jGhygq9OPn=tjyZUbL^NxW7ao)(@)DUf zoX1$uYZoD!@bk`W@EyIcZK%U{wzssjeo!bteMMg&#VLULR`Y~^T zPTlfUpmb`gvfjS(PrzS5U@U_YI1TlP^u3e%o9svz+>FD2CmH-Jn)SZ`FlSgkWyw`A z85RyC>20_=cDlQxjc^GTR=j%44jAceJ)#9NiCTdPYWhBnJmLk=(w{#JkG}aB9&~cQ zCb%3pXRiPJj#a-NarDiWqN&Ei5}_^peRv7FVK+;1;G#%-obpT^-mmMD!P1j^&h%&b zP`7Pjqaq_Ek|2TCEf&6;4Y!j{JA^1O5T+ItzT~SM$Ncbm`Ce#+>WhTp!nRy2rP4v( zh0aoR>BGCAHP-0~0F$i#cx9DZC_Oqc7u@Dh&t+vf0%mI;c!E7;(Uuee^H;Fllq0e6>eWuGOj zZ-wR`&f}FxR+_THDY10K%~>*T7N{bFl6pVLezx;-U#&)*#1yjgBvu<2&j_RhHh;_nst=u(ydc_VG!43Z_2d3RqSkx{ z=c#7m-wv{n^d?t{bJRJ!v6%3rtQmozw**xpbf71h>@RcDwtCoh?mvX-uLG5G9G<-e zkLbx)TM&Lz!b2r(jsiUHM{b>8v&X)WR`UMQ4Dwlz5VE|NtL97<2F2A86Bi?+z!t(F zhNuV>U4yMn8>?52z~5>$Fhth}Qyu1-zhd#E?7zy$g|=_|dvk`DfGAdu;x3^?h4v;} z>5s;NKvvwo0wCRPv2Oe|C1JnIBdcD9k;6%!z%_nZC(W8q^_WDyAV7>I{Rp+PvN<*3 z5$p>!=8}hjexFhfF7wdcW7?_C$^r2?GrtOd8Q}y4`ysn^vped=;j%d5x({JqO%E8y zj)vpzz_&r~s>Fj*Oe>{G#+pP5XOkvk5ik;b+6u~_ae6ZUSP`DPxK0AH=2BYhie1r% zLr2y6lsr5Mbut%{TOfIKouT#cf*@J1FS8-t$(EJYkF<<}6jV9edE@sj1t%!oUboe^ zAraLRqsyZGh58Ye+7ZH9h){+0Mz@F{@9}U{lG)iv8T~N8VXI?nxj`n=nrbIb%WFHa zf9Q(b#3&N}FNu8-wc9we!vo^f1#l4`F0g(TeYzJpT6&%9z4+I(j|~ZJu}foG+@Ik= zeA=s14)}F>BzgMz*>c8?iyeCFrC_?yURklm3d6JQyc!)RRm3;2J{3FLy*kGsnC7Je zx4H4SI)#AEJuqMY>77#fH&F@_W{3gFlbox@AFFFgbq?S}br8iO?JhnPrr}K0YCBCB zL6iqZx~_nJQB-9bAbD>B1v6N|GRT%PckW}S{a9HPPh%xv+Z}W(UmidtIUAM9lLW=; zI>+I&?XLc;L4I*lw0%Z^oRBh^&Wj42=sT>iZ)EvX&XSV-(@~S3CJtXOo)&QtvWSjW zR913IBVZ^$^OP2+$I5Y)dYo|1=ftT=c~mV6`6yu|a(^OB(%;Jq+(cmmN>1f{e}^>f zv3z@vwb|3RDxBmV6K#wVRPE?6wkNs2SJKNnhP~>R414|S>|9*%;DiuYUt~>Q;`684 z5~??~C)z*eY7f%i|5|rwo4geu9|?OV^T;HRqQ$)aV#(g^Hj$LxcM`O7v#QrS ziUv9@(;L-l#RpnWE&#EL+>s)le_;cXpP_@1Ga`k?B%G97XVMwZuFUbSz^zE=DELGL_vK! znNOiESE>j+{vHEq>>N+(vdHazH!7eqP~xH*Ru2N%9t9lVote)Ow%XYnRt;%dSX&32 z^CkyW+&?=he8z4-8CEskiY((%3g%qZMaovkaU=vIG^6J-3eK<#x4~dl=gTP%E;ZSl z$8ZJ*l=NexlxuhX@F#^(&N-`gTl|+I9FX~24lfaN?e#B~{^c$3CWE)@$MUsi91GR1 z?|?@6d&kBBH04!y;veZ)KaV;e9oX00dF~P%(NjakOolOUX#JJ#3)SacXmwcc_}uq7p+;jiC%_jb^X4@Tj( z_CVNqbHS^#7_a5dd1$q3s?8Ng^!=gHAzSZ))`7y+9J})a`46hy5#2IRel?Xi^F|&x zgwyqgHUhf=#pAnT>uyLWMTP!=nb!x%R`eU}dre8{o-)R>p*TjjD|on?(-K$6HhukI zaQ~PUL*bcEB%Lo^f{N1sr)YECmZ4SCs#+YaqC&FDQ$zWdfV4ioO&B<6j^sr6JsLbpvk<8Z1FBG^@5aByxdX$F11=Rk{B z`?Te-NHOli(rmPo`g)L{yYLv&oJX0NI*`M>=Ay;x$YqS|sm8O^lDYOIw$1Q(zTzGa zfW3T;tS0yht(SvkFi3MaE~dCydc{|*weKHyA*|8#V9a;Eu~>i*uP4alE*GiQ=#`=O zi7_qK4YAe8ys$UHx+T;^?@_^|Zw<>|{?!_h$Rv zt-AK%+~Pu;^*>@KAIKroWB~=d)zZYjGM;XPr$63dS^`W0lc#*st?(2TKozIQufO^W z9K%MF{c(`WK7#?r!;zqVb+NTcu}ndC%?a^UAfqt`b3;TO&%`&f!{P{#r>0&D#Kx)L z^US*JXu(K<+&tMF7@KlXtQ&Xf$Zm!PI1tAdrXRYnOH zU^PQ-T{0|g4WzYK?J~1ow}z371SGB&a+Jtzehub(NUJueZ00E9y~+thXq4kpgnXMk zP{tz}V*EVv_#)z&iF`k8AWn$Qs&DLy#I@tcg(rg6;u{cDALA6V){-F7cZ=oUa-9; zk-|XXk~RcORaGhyyW2JLN;gM_=*^LWqDo@!h0tEKfIuR*0(oJIU48%NP$RbZ3^9vZ zja8bX`Ptk1TT_LIPM@S0a$`6W5aKU-->h79f(wEzQiI!?K1rAFHcL)P=O|bFnQpyu zt3Rf|0|0h3y13#HHL|j*F`g*Xd)<~Wyf@mLdv1ara9@Q>zaLeP&-_$=zkk0Dvbr<} z3CzX!O6J`uS+>qDM@;OL+|jEI%h^bnrQ@XY+zKr2;V4c&}?s_Q*vGP=>T`ii5gtLH0^TP!qKPX_jNWffP!gUex9 zDgBzrj{8SlF^W&$8Fe3d9XRy0n&B~kRjRw?JEb+<7#CyWF`V>x;7VRGJRaK*;A}mm zv)=4v9&3LLBnELaDVAD~rWiSfhv^imIs|4&@}{;I3vWl~G+&Z8W4}hHQ6+$CkZ_vq<^T*<2Z1M=fr#W#>mrtsW@M zcaMJ@9R|M=;bkwzSVWHjUe^wsGC~k?i3*uV6r-|XL4@*sp$>{zvJj^BDotdyvdvin z41ixbp26S}$_Poowb_C3U`U66!fQDG7@m-3zlY8C@x8AiR7qHRKG*TVVif1kz(Wzv zx;k}mytDP@PN_4sP!gQzhjw@&kN!()Y-U1Y{4w{Rr^lJaqvlcR8nvV8VzG9^;dH9W&p7CR#QPWso zCWIwL6ZJ*y4;`e~EBm7&k5vVSE4{8kC^G}W*tg&0)Z${7*7`g!%O4woQ-CF>g9n$x zH2X0r*Fs-CT!p%p7T6(6^yGu-S$5|W-5-yQ>ug1?`ZR?Xl8CpfYA(*Q>9b#VIRs~g zrv_Tq>@7_{0`yK=;Lpd3;|-&^u(_$QXD1n{e48mN``wokSHYPw!BokOr!|uTi-SuD zYqbc-w9$rlDZrpBPk$6(Z3{O+W!14*~6j88{No2vBN_ciU zx*w7vZ+wWv6KIF%Bai4oi+F}&&^e3Xr1f1om|Cu5^cj)=+O&sP7C zG|2fAls6kxnS9HJ?`6by&0d7$*DAEfRC$~=rz_R%PyvHQiZD}u!9~KD5Vmt%yj(Cw zu8)Pf5p3f*Airam^v3cjl!ZI+6`vAuiu482mn7RDI8aPM1YJzAI}4s{Y6|qh%^dBB zeqEcz5Os6tis(r_+#zY={MtM@ zFBWwSP|`8_1N`NW`83!RFrlacp*%{9zfht5#i?E-(e9~#bOw%anZAf^_0&AM!!br&2&?>%uhv!>$dR0k5C=BJv2H|k;-v+BIbsrs;Z#ZM9 zSx=zYE5)x3i0?x~o8ncR%rht8j{Z^W1$&^dAt{uReS;zZ9q@CrR)-=3ysv~&6Y8HM zCq;4jT`<4#oe3&F%y~6!k>tZal9F`xYDH)nZkKfc)dl|$sBm8;UMNlFUK zm|ZZD0&#}x;^UQl+~QB&7bTLsTP!}nC->`H_0fcMpX$fT4)sT&UVEY`i-tG5euTqMFpFUi?C$@5PHRY!Q@=MavdHZ)le_Hnyy9Cxz^Sa@iq4L5kEJnsLl@@$$X%buE73{euUzxy45o+Vxw!`BB9&k8w zlfm}?I9R`5_YZ>5eD6AlR&!Cgy4sB>a`C)bmWsBBOzb@C7Y1&aAbFsRYD+tcEE}a5 zZs2{Qoie%}wi0ZHRDu%GaKZQu#c*P+Muvsta&R@0FZpH3A-{h%ctzV4NQq!}_R*By zd(4mSxc-BQC^Zu060Y14CVT+Hl$33swlWR7p>(2Qu%kp~c=VwG%wIIcu40B(-t32z zaPpHjT9Tnm&7|06!k`Je=uBO?cQR7#VNyIg~k8$qQB^8!Km;>pcatWx2nWQfOAAgdLa@^&f6)0fsK6g zzpwUO2?H~;ck+A-iG|VU&X(Z*>LHpRz4nmmVso#g&p`$$ha?7j#-&+`+xe+8^0(B_ zbxM4^Uc7>&oEWuAnqo_4i(=c#rJ;E+i$$FdnLXZf=Om{~}%=3|{$!swbSZB}TdXa-QU;0+k_TU5h;`51or2X5MrjRzq(py!uh8&~cz^ag*T_Cjvt={`|e{X`Y_S}?nXsk?>aUNel zl+oh~AQX6(soDBK`uhj^AdsGoy*|wUj5DT}(3B(e+NUnYx|K92Mk}9Mimw|8RA%_7 z{^ICK(~{=Zkf9i^DS!!Df;1PHg!%fXW4svPIZdWKZo2}CfGc1h) zmH3Y~K=-Or@?QVgKpza);kBpYi@L9TVt=)v|GGc#0LePG79f}j<1sY`MJx2%vi<(T zlNK^H8S2?|^o%nz#+n=7jNdii`jXHKqr4c`8CGA@%erBGUur*8m-+Gz8%y<>dk;&E z^go6Iq1Qn;STEulLx8X zidbyLWRGF#4}e#$!w1UWFZN%JpG#jY|935bzxs_&sYrWKT+NBK8XiX$BA#Mz<3$s; z-@f@ zBv8{^9P2sssGL}q(W%Agr?sit#Dp6aFxaMeuTo6g_20h^JWm5sST-rr#Xxtnk?dJ# zyaC&;p~iXe$MF}M%jzG(s%)#!nCF&j4H@wLB{%rj;rSm1^MlX_GmC0cbKfz|=}k)a z@s`usx1B0rr{G9ry*(+D*3N#Vrc7GbLIASl9lVu>GzN`AXDu+X=H(Fgvn;V?hIu#_ZQYq27jE`{*`{6fxt&W)V1TmQvC9^B(?M+|6i8Lg-RBef`B#lJ(~ z96{}_W>$E)SbAeTR;V|FJ$h!HSA%3~gq7)7Ql(gzuCrgRMQUw=8ydKE>Y1ATwcCqg z{$E+-zkc5yPpJ^XQLC0_*}`O2DBR+rKfTYO`o%SyA<^}saJNrEPwxI))FZ0QX%iF6 z-gzU4kOVVD|1>L6@b56_LFmDn%I!Yd?aU1zN7!IhI-4WFR7Jqig|jrH$<(}-8N<9= z63B@ZXT@%+j^<>zXSuGVR7j@hypD~Dg=KrP#Ep{MS8HRg0r>A3PW^XSDuiRDuu|5m z+M3?FZ%xT|CHp0hVf|gntMQ<=Y5#rg10xI?^CyGaugfWUqk~cpmt%sfY}a2z{|;43 z!RSnqoT8#?Z?!jw9yFlLELn8a(Ri@~G-Q{;*7{if&a)*9N}<)VqjXDO97_RJ(rw8P zpxn0aPgFActI7?t@Rp_fb9I2>w7)?N-q0N3?OHW8=CWwhc=8`=P`z5Kty@-0&)pcDk7*<BU#`&ReLWRv`^x|e5g*xK=@t;E^DvMjMPa$vEkCPHONbG( z_n>DFKdaxDsjs9sp8O05h>~Foz;?H?LPSGDOX>A}```0}H?SqNKG)NmdJa6R*F0#| ziLE@9&E;lWabvsZ!(gos|J3=tPT5GxYvj^ZWuax3^nq&(whvB znU@RQ_Dm~iXC26ITkl@QT|rF1Q4rW+^rnlr&!Xsx~2WLZ4?BB@O$ zd%ACVZf%B7do68cmV4D1=U6{(x(Z!mdO@R*xZ+OPpID(N3$0IIVyboZa0uM2=p*Qg zQ`duNTa6eU9YrW!+}a}B+1<5$>V^%~!Col0(?tGD{%1kvQ|GnTX5eTCT~P>I4ee{g z10Y2qz!Bmaw}n1mpmuim6ybGUyMD_g$Q$Hf2a)gjfL^(eE^y|9)PC&Pad>Sulb)Iy z-O5L3)q4L;Mpib+E2Kn>E8Oe#HlLY?CphDIAw$&M96Cba0UIoFI4TPhL^SW+5plQ~ zM|gVIsdV%cx(5tM|9qL&P$|~NKYXKllhvbYr;{t^RPf9fnIIsMe=_zm5OPRj`uU49 zdua)~jBc)j>}T)JD++EDT9vK`C@o?$`?pAlh#N->a}%?eqSDeK8uCu1Zg1^FLL_ph z5|ffNZ!0zaC0G8Bfdz%nC6Hi_F44(q6;_`qG^#_{`S_l2litY_oALGW_0wydwGh#C z@O=`jOjx@3YwI&MO^)KVnizRFp&-Oe1ScnFfVNcw#$ugy!ZWr~A-bN+HW_LVG)q$G z>@dHZV~BzW>VkzMYsyF^XP`GjG$*`07l$=KrV4ZE4;Iz$h)lx^^5^JW<&13pAtWGB z2w$$;%kFs$TAGSDv%0!hR1>xR#}2X37gxhk|Hk<_Z9c0lYYRN(ON4$=dRjhy{uT)G z3Yfnn?D}e$kIt7(HaFY5>kbW3W832!NNWdps|-+|DaW1eXU^(dzIIbZ=&I{7+Uk(# z2p0C(a$Q;Vf}1;#qQk8tSUW>u_N)nWeH7E%Xws1@;5u~~8{60#P_74qE>`Y(IZ4t+ z10mpm8cMf1TA7R!vplKVWxNll{K^&_e||FA61`O)if=-^CiQcUd2?26VUIE_n4G?u zhzkLfii$_)K|Q8^851}~gIU^85KvpVl?9rSx}|hY<#vLH=TeVicV@M-^=7Ll_0bt9 ztMfGJX8K7H%uh6yLz}UL3A@>yGx`cIH~7w*i!U;@4*!E%jD_Mu-t`b!YjhI*4MX>y zniScrU3~R7w!o03Rz>Y2q(L{`_g2I{)Ps&;l0^V0_2+9`j}9AqD_?X%Q!1}?n5{Dz zs$Hx!7h z{VaoAL&o*|JkZ2kR@t%*teey3ALtFJ!dK-LvZu4l+Gb!*g;3!(8U~KzC7Wt~EBe6m z=d<~jS)+jk`P29rFp!$`S30!?4&+xFVY(~aXwii^H6yn0IvG}tiBeI67Dgu0SN5Rt zI?TziLVEvwyso6&|BDse9#10l6(8w8!~^9DR`FU)ED zg@?Lxc7ve*=^VU;sOzI0+Tn>B$tkMMuc^WUGsi8=Dy`EM~#~_bOSCK?Ky{PpqNteESxuKj*7n`IF&7ymVFKlPYvW}O} z?tf@CG^8HjsZNfN({+>c#p#GKqaORsE&7TUHqp>FFh!`?L3G%luV7|O(^CQf=3Z8H zc<1+;-G;1Mys96w8C8MV;h52wVul8@`x;RcC_x8wElXG~9mT~RMc)2|JfWYC>&K>T~De%tK! zTycX_0O$JCe!|)4trz6fX4lz3`^eICB1dLS^rx8W4`l@qDd{i#T(1YVAJU!G@cOwu zH^_1LY}ebvJXkU}KG)9#7_o%ZhG$YpobG|;NTFo)-Eu!8L&tVJquKu8=?X!|eFsje zn=!VDzF>fc3uZF0JNC4M8ar(3t% zlOiBH!WzEIgqbF6Ye_Uc^L0nhA=G4oRtc<5l>H(2w@h}P*b5X5CV0I}SEYK?34yh$ zui3v4)6+jjc@EIUp7Ca2+15?@-z|kw+^J<*k`p;K@h4;R6K7pudI`A+?7KLlq@+ww z29Q`LXX;$L&~()Of>xgkmM+6rb=B)Wl~(#`CzW#&St&9a-W)g>7li~HD{*rci>xP? zGn?N?W*ZO3Xe%WGJjj3Cj+E#Xy-T0;J1F`X=R{LM^iE`QlJgM5=ZR!T6uXVgW#9Ln z-iE&T=XjJ56wIDAK0<$>W=WEF<9oc@b#{~95C7EFq+qXFAM0#}wuzVRpYomWex1gO zt)alO;rKk?y5qJzwzdw|3?dk=V`X&P#~CvD{hOSA`~Mm$k5rbdm?gQ)2#NQugcHq2Q=oEnt0P8+ z`Obfz?Kch}t;IFUnE(Q%AmVHN3oe_dt@W4zLtxIf6(fTi#L{I_o@}H z?wny$-<+H&g=43sr4@Vn!+~5@jXrmVP#m=9_{jDtd0M2^c(R}2V58!J)p*bq*3Y%< zb4v3L4X2GE0vX@|i zhz88~Y~~^R1BjCZv_xvunn7E=7_J+b2{ox58XcoBosgb7EGCtwt-XfA`pID6aRRz1 z=aBKjlIC>W@;8)p!;e#6?(Qj93M!yb*sie&kZzesltc3_zL~r^!Y)g#tW9^6$jIO3 zmpsM|(96(Yk#0@~05IyJm9t#$@JV>AD|B0w$d0sH;$!#HtXN?RLe#i7rw_!RoRnb{ z5?iU~%^6glH9`qxMuM=Tpd~VSeB$FVj~1%%baiz>q1E~6?oxVY(@OLXSga5cV{E)> z^mMQe%ykKtO)xM87->b^4VLGlstCw`^jWS=64~4XI7vum{XQrTzi4~D+m&l6fafzp zHu@AFt!l*_^XawKoSE#)ECi7%jSrQ+wI0+qW$iUtG*LVV+o1}RZURDuTtzJE zvB0t293~#;cQ}ZKWe+M$|KO=?@j~z*hM3!F-xVqWN8Bm+{a(z9;3Z#vH{|m@;alk- z$XphnA&3y#3OMCIf`d)WNOAIJ^}coU9BJX9fZq1qmC#=aeeXUO$$N9 z-I&qa#C&?{kPP)Lh?bT9dc&2hRb{!XmtjOinEu;!K-1cq4TdcHqch^A3VcfxWq1SB z5n=|~!I9CCth~jTq)4|ESs{u%mo49ADfJ?Tz*%!0_nk$X>Rwjg)v$y=>OtcXDgiYM^Ny!xHnSv+ zwyr*L=0SCtKodn=(;z{xSlQV8^JAym{Ki+Yl8!nv-$%a^3&}YJ$b)F5G9hijwYCxA z%oSkLj%i1(D%$3IfN4!~DY?%(l)cl_zMIx#82`^bSo5jP&e%|O2sA$z*ythH(V`<- z^7#2n=2;+FH#e~f;>z?4U90HQ_F$c|dA0Ul=%0HvNko-cTkb@7U+bBo3A=_87sCm54yyGZzA7*w9v2pPA)uXc6JP<}pL*(hl zSkyC-JX%UIE>*@REjwT+#?n4#Eituh84eWDAyr`0V9J2iC3{{}#8H(<-nT{MA&#eV1W*IL|4;D=12|FU1#IvI}6#Hr2Z@&KpK!E)7`K7@}(ql z0pzPouXxuYHN4-h^bIk{!SY)Pn71Bh{>|970h8sg?FQtz3q1p9EEmV z0(WMJGcc4TtY`g|q6T{3Pxs^;RGDlpj=PgH5DW0Ytd=dq^z;58ou{QG={Bkfxd^!H zopJwWh7RG9kQg;UWL6wfo&bkAnj1d3`^ytoYP_^0m@#;quL60hd!r~`syR(3(0sOc zli4G#PpalNNEDzdw=(JV6=pP_QrsejTKecfp4-@ipV9Xc2PH|}u0qpo6H2PP45T$c zzQJ4|*a#raWXMLSPXTH_GZuyxjxU1po6fGAYVbNhG3~CXFoQ&6+incvZf+?Y<%a6< z%*ta7p`O1TmU2z#pRe~w=XkF=TCP`Rk7r@LPI0amfqxX%|MY%ku0zK%hd^0#Wda2h z`uXFe48MI7!xK6F{{OLc)*W14U2XBh=z{ikzjRSS3z~N+xfp76$d;sWpNzTH9^63k)r`LD9i+ZwY91u7nXHMbxPg33 z@od8~e0XQIgYXN8iEiUoN(x0=r>whrj4~Dym5@+ZY_^d)wk&4zFF$>5XCQOjyP6Q2 zrTBCLu>de3c}hvlF%=|wJF@1ZjVqNYfh`z}KF_p`49&^|_(mp-_d&v8Modbhm zkRRp^re}6g>EZ%wB8xqL_Xq7q)1X!jWf<_)Go`m2Rr=AFw|qCWQ(su2Qk}69ax9x_ zp6+9wHvkhVZaa-)@g%(Xb$jX)C#~?(>Gs*eR=kp@UB_B_z#TCC!~;^VreW^7dl)5^ zWB2jm_4u{~?;hp7NhHL`(ZSjwjTt0?Ns4JP|q3d1=*B=)a2M*p~)2&!4ET zzR>>N7iM8&QP%STwe}O&UIpxm*ky7=wM;SVtm1Ro@>00=&i+b-@SIg4=iXQ=nndkh z;obzLxkcPDM@)K=B>jl|=?0({y%A@zT`-Mz%x*A(k!V;uOaWMfJZ zbOo=dI0z%vKS4B90JN}_7r4+%fir=@BSO*BD)eNX7?_gj;4AH+nbtM#;y#UETSChN zN`E7sw0}N<|EJ^~`NoTs^O@!~7p3%5*^1dNjW7JK61~Teqf&c@tes`1!&FQ|LYIQJ@ga!C)m$H$9&9HlsFJK)}5lKZgjHm6k=% zp}$)8$TE)oPw=+qEj)Iln~n2@6NaK9yKT1cu9bbeNKrn$q`91qBth2r#lrPk#%xf> znao&D&=e!-Siu<5C`9C*VI{UuLrsd#wLT7K%5Kp0wP7`ed!vR1h6B$nRqsas2% zQpXqPtW#-yPQjH=lq6{eDc8^{>$+j=HOQBASzX-P`eB=K9+v0k>agPE?5jl+kmtU` zsTxE<1>NXWaf>gMH407di`k9i&kfkEuti93!=t>Wg1PXb-z~1}LG<2E{^b9d)LGd_ zGxyf8pM~0@V&K|7P+^#$`3)J_G>?Dgv%~@7w-OEZHbpVFV~&1w|Ao=%F>1n5fzj!? zESGy<+`JR=EWa%P6)l!DMQ9Cf$PAs29jlfV5mi+8#%W(mUVNSi_BeBa#ruNu^wc{$ z1J!7##>49&)CN?QOC_J{P~=ggym+119K=HjR~mT`aBj&;y;*#3(~{j4>4N?t?xhj& zMA(XMcoK|{`e(@`!v1Lekk^4|u(^8@`}+E72ss_kEmdDy<_5czK4LGsOmN@o*%^55 zC z!CBz!OI)JwcwO#L$8@PSNdIAq?x-vJMMDjaSaw6QYR)D3nwCS3%PJrezM&uz#Om>w zVN`IpeC^_XN>qydjQ%c7$a|Fwi9KC`b$T6B#0}r;+>XcdveegKy=NU@De&}&bmDKV zKCJL8Y4c2E_g!ZshWiqwa(72Nku{v?R z7|fJSPA(H*!$rHV!$A1|JCQz(Vk5kM&nxwhm>2st6CM%e*0kJiS5x!>r)ZWOE?8RW znhjeh*_s@0><^CQwowH@{MqsbasYEhuyw9t<~eb-=@?ZlcvCr7s>Trru+#|NvW^Rw zQox9Ebg+sx@)cL)6f(xBTmt!~TjJ`*mciJjOL$5io8|~5M%3^Wx9PB%=OqXXh$d=W z@^jKRs5o92z7y@*c5<--u`@N6<2^u|UD=2}U-*jBj;gGlUBBH41OvZ72~Vp%vN$Vj4f&y> zab`ihvhVtgnL6QRKQPZZw$`Gj3>+Bh(GD$@&=rRF#x@hkF!ASEg)90{?pa|uZ(ZVs zGi$Y5q3(81$rXQtXUfV9uo^VO@Cd|B??@#WH9Tsq+sxgC*2s23?<%U}#eQ)6>w$QJ zMVj3SC#X##p-vf%bQ*%sGIPANEUGQP!dCQn514SKO`>fF2QEJ-Bt|{NWM$}*C*rxaq8ne4zV z!&7I7e#qVBwgZtTMInG(s+I&YSi3WMZ6qw@AJlh8D^18*Id>`n&HM)Y)Jq^XTuOMp zyl1u)Zl$}+Q!~+={YXv}8jJJeY!Y#zG*FO7jG57(p-VTf0W_k}cWh&~X}^ye%-ck= z_Pf>az{_!_SbGzAWqb2t3%ae*nkQ(F&?`fL8Fo{Eh zP59beZ=S%4uP8@2Ke2J~hnnZ*%~mHmk=jvw_#$?+R4(}@qaD_K~;XgAV#)l;mVCrhPP#m_cT0#ny3^vOoIQ8V6y5ta#5ZT?6(XIVtYu zgi_UeBf3sZ2uEmvam$3j{!Gd>PL(VTVNR7C56JdNOC|HO0|wqX{hSU2e>!<&QYd)bd+AN;bc8*n-2+I;*^r#2?V{S2!^zxE zVQ#_^6IAkEPhHYfd(FHTGS_->&1(!d8jUuqWY>Blu_9eqPp1Oq#~Mrw^?%ckmsUPB59>yv&iTZGERE0Qv}N5dE^%twhbzjsO#qE{t;wc@~UzWgL>&MNJ^_#4; zb_1GWlMbMCrpy&^y8KxURMgg*B2^7pBZDCoL&-g*p->>()13UV0)eCqW}| z+1C4}Op|TCkF}&MQhAtnm}G6+n6WN03sQs+xvyEs@i}&K_f;R!}o!>1;9EVbmA1_6^kgRvBhI;hQM6eDzyk3AJ2D99RLjPk% zotW?wmxn2@=A}(aEZ0D(A~NDQY(lSO?)&1VX;Nm)WvcW}FJ?yrP@yRsH(&;_p-ER0 z)y(^$X;`2M|6D5bZZ_7&O_*Dyw^bL-23kFN6iz;6Z4y@MRsmQByDraSvSe~iTWYW+Wf*h4y@?G=!8AXi7 zdJiqf!qs#mG@u~3+?4ojkp~SS$ToKB)62D7irQFd)6n-=W!$CvWl)baCk;cjSA}=hQ8`a0Cg^$#j+`>D#68PA8UJxE?=n@I|P84&uex# zSaUiA9_P&t=kw!#z6ee>Nb?~G8OaZ@n2I1Z0T6!4FPb@bbTo0U@j`nD!au#;tRey? zyZJ`!c8r}4PFBLcJGhW?10&-~$IlR9xOab>F?dx&18H<3V;~4n0M`!CJi}ho&oB8_ z3~4o{KEjuof=tb4VI%~yl{(T<9dd7cJqsr^-T#`dHnr)v&``ITU|wC&L@vFvdEF2x zJ)K^STVVux#=I$!hzdpbmr94L+=qlE*Hn~Sh)vd}{^X;N#T(Pa$cZ!lI0D0AU(8yJ zq6J5j35WnBvYsRD4cMt-^0~k2Glb8IVy1lcu<0WDy-%sF|Fa0f6&;@<+qO~=pcSIRCF-XJ?0*5RlB8x)wX?YB#~ zWYeWFgSYB{^jAoU#q|~gdN*VtHZZ`Dx!KY@Q0eF_y3_LG6*c60iPrCV+%#SPz;Mx(51n@B(gMo5y z<$PdZU6=OnNJfhW+_t)DQkEMU*%p?#9A$Fy+f=P9f>oThjj!+W zyOC(AP2A&O(MP46l<(-~lI_)IBSV#4c7>WIBd_Nw-O@_)RUWYk+M02;~(PSwR{+alJ~mEBkGsyadxQtavD#|8SD1Woy zW>5S<-7_^YBuJB%=peQwaWk20{1|U{o)V9_+t$;;MZh7EqaxQNB6KBAnCXHoK#(bG zUe|6;8Tonxz@a1`|*V$iLX1+*6(?TYCr%26!m?i$Oi%TSy6$vA@-19_EEK zXy*p31z4gRcK%V9^r}#1J;E)aDPZCMNR)VZ-)RhuJu`m*TdFW>7au7H1`VrTukm=< zCD40#nv3!)&}MJ+g(BUSubkI3j#*FWq6F@^C(vs%hsX%4*ylK+9MzH6Qq<2So(A6o zl^O`u#de?XKwcO|2Bnk!<=3SgO0L2*Rf&>p{K6{c0I~Q*uy>HfiqL@gZhZ{;S)R1< z4AB5A{7oZEL$i}dlWYu2Rf}c3LvN>#<_qu;1vuz6B;d3zjaoot#eTs1@z7n%}Dze_?epEI&?MZuNM6KaQeNv7X zi3u7fB4l%SCGNm8;@oV!TB~Zk#^Dr!o0JqnlVj(mHd9?Y{W+eQtQy4M;-?6Y)HvrK z8s@NUC`XKw5=4)z`ab5^lDIhR)3r9p#!&r2_Ha(|Lh94l$$RO&X{j+quh<{`#Fh@41Og$jZxsXNL zMudsVtxJ+`3aVxT5W!h5a-HQfT9U3%y>-<@=&FqMr|Vi_K=7pb3wrpBwi~rw42}-2 zar&kntARa`;xP2>OUkuDPx#uLNm`ee;5h~HhYyt{S|72o2P$&|O|78y@WYxKZf!6P zpJAs)18&2L`@m4$;nl)PxYJ_kWAmk@br;utSp~p1H5NJ0w42I3xol$GB}7(HiHcxT zc>>Y}TG?#6rIyNYV)hy(k%jPrhTO4P4*&4(tO(Pvdc%VQl=^7BbvWs z`4(b3QEfs`>d$OgTs)~;D`5@zgQvqHJ;K}zK4@|u0aNiKkj;)QXuDfiAO@Ya zM$ULh4cn!Q?cTq9&}}whP4y=A)DH6qlD6#Wb6rQz9)ysgUiS4m)|xKITZUYL#dhbL8{7|c zWpf=JXIF}*?6b6DN_DIHqAaEf4kWDo1%EK9RprS_L`uE+CDV6YRyaV1lSUH#6v(cA z3AtS|vOJ7b6Q|uqosp7GZOs8qMl~RT%kb(YDwTEj&(qD9KsaE}e$F7n0%*qXIE}|< z!?*Ze_mw7Y_UuZsWQ0nt^32IHD~fZROE^0csxRXfCrtH7aoXvaz;XMtQoL{O8LB4h z$Fr17lSwPr(@l#RDFb4=d&_CRSLAoqYjX?BSs%^r+ig)hch4z3z*2fkmURQc`!^L1%MZ zOCCMCV6#%TVqPKmyKC(JsLP&)@74WrJv^J-S3%Iv?f4mq6W9uNeD+~T$I>~cZ6aFf zq&7ykw|-)7IT>@~3fZH09QWm|>@i(Mcv=IA__QV=EZ-+l-3S+lYzj3uW*lTv@Yt6h z7@cN=gP*0xlpjiNF4Ek!id#us-q|kni1;9R-Y3C6W6U2u6ANol?NIc*x%NPfNM<{0 z#YnsN687=ccGVVqv~JJC@*vQ4nMU6JAHkROITS>3#8S#o@hII#; z(o1KJ>epp9b#k3!EON6YLD}NHCCM7?(=<;ZZ|$ABrS1C>>O`<{+2MhO;tnO9o8okh z@)aMqqiEV=;kIdDCYcayt)QmZpPGCfkcJ)N>WA3XMsdUib;$;Lc~Bv$(XAFo)Pp@T zBDFGz#t?~W40C95F%!8?O+b|_>qVtPSwww`e9T>{i%)A zOl>aw317H>vuNbaFw#Cdce*yo6wd)rI0${r;K?vRD}MI@Za3OqjR>$THJIQJSWTB3!FkTbR@gzygRvsS<~PUah^k zlP**KH{>{QKI8Q(twJu1;d zjF_aPou3h#dZsGI7Ql3Ry;Gs zb{4%(pj^v88b(_(*)&{Q?o12lwQuDfPCQAII0O_CIDYEvHP{S!Tjs`rIiFM2VoF8V zMWXJ6^r4vFd*+6V-VJ^xxVl?@)V1B%ghd2iAh$fnd71U)ea<*Ov&`k?7x7Jd+0oP% zQJU^rpWfrauwu*IZQ|<4B+D1hnuVVeUoHsg7LR`xIk~7eCu?-G-O2Uj)C>y}e|e+s zi1pKFk3sw)fyVOVLKaTBtgF&n{O|+7)ep#8=NPV11LIbGfG365L#K0vn8M1}CeX#( z&7(-xCx-Bmq?R|wEl5rSYfD}>Snp)BJ`q10&76S5_2KWISJenZ_V9XS#CI9zN59>K z-KR03zW-SDcwfpsp?O`oVG>Mr?j@u@EhKP}Oe+nt_2M`GPWAT-jF^i7Y>!)U=j&yP zlT%bqcN#nLq%WoE+vqQ4R{4w6<6>r+x#V+l;GS0pqcrF#VofH^`Bg_(Zs6N%C$G`( ze*pi(MM?NEz1Wh8hm*$VgHkspMvITViB5ax>~HX2@(Hp15UO_J=R2t-FV%NvonD?+ z8uv*bD5l35Ew-fHOU_6rB42ak=(BcivkBRLMFSD`h1t6x_DqF=Q(%FGn-RP_a$OFZ4KhDTsQP%5_7&#-py113_Va_Ulri%*H8jHspVf!Ue# zSuYa^fA#mf3L1kEMk_Z&G=KhCZjQ^EqT)}BPsX+|3re&|jYdJ)8`*PjA#6Gg3n)T^947Hh&j_iEgKw|(){t* z0k*E0bqJ%LbG%t&`p~W3J{d0_qZ61QhaQ5xq>Arq6s5)$r%Bus80Zs{=|JEj1q^-< z4{i-B_|477@H+dH&gpubE=SJ2C=MJJUQIyaH#xaa^YTJR1_4c~6EPVk4Mql9L#o__ zBzQWYQdikaB?eS*MZ<2WY}#j=BewY@gCeI|>eeW(RT}Yu--yFvOl@5|RIy=$x%QXN zhhmCNNIWTjP(~H2f%6Ti@)nH+QDcUuc`U+G-(P=c+j8;yWwwi^5JLL}OnnPp>+A`R znwa+4-we_-8@)W;e~YNZc$9k)mxqtWr?5VFELn&bBnrUPrALNSh~60Qn=oh-EMe1X zkbHQEkj>}z!n4ET#QLB$+CLW?1BmY3x1F1%mng;yRHfakXXh_m^0^eui8PwK&s+$m z(o?top7dP_;-NYHEifXb&E0lKmzD=HgwuVmpwKcg%H$j18hJs>5J9$MVS`ybmv+Ru zE;{IYLc5$I^K+8Kl@XQIVqHR@n#X|0xNDjvkoMdlkKF(#hpG7Xp!&i?oz}S5zHG7{ zdoMImXLtAI4^8-S=5f%)#R}h`e$4oG7_`iifUo*s6{FibIQl+>Ub{;XcCIkcJYToZ z)QSP+V@FV8u6$c6S0`ED_0d-nXr|Q%hh7DHpq@8>Y1Y*7ytPXBsDD=ygVgaNF4nyB z20Q}bT-a5xe|jq$9PIBSFQ z*#zcer0N-E0d6&!MA~g`M25-p(3!GjpVHph-p){6DQJ_L0%#A5z?S(8Pr{Qy(6&~| zbO=Ef7V_?CJ%!_Dc&Kw^r#{OFKDgIg-<}38?;3ybq7Pc#Kd216R^dH;eh(X$$<)6X zL@cjrot)ssZS!(se->|Yy(l|O2o(wCtau}Cajxx#`HEG<{O|bh!zbT2xhH&d({<1H zJeKDkM^Debr?rc3wfV_A+nf%1sIkacL)=JpZ>%Lx!&-R}9`V=%1)iQVqIl8rC_0+4 zgw@wgNCi(8u2)}gq>o=6piefrY*ckWd|{H&+tsSoqM?cGe>^1e5H7tvcA}9x zaw46@{U8!1@42UgG#Ch2U=gEh-R>0&5^T_&GgR?m35fAY{0g6h_rUc;PaQXD9@>l2yCmf9pouU8ch=;^J zCVehR*4&3ze~eyNK5^Qiq6`3+06%oB^A0L&byMk7=9Vvwm=%6|KD#A9+K+10$umj@} zT0&(F;XK96gllqcK(t#&cdwJ4iX={Z<&V;j<<6O~>Wm0XB zA+c4fPi-`t7&a zUy=tvnwN~rw4nVK(VyvJ5sR0fynG6|*RDNwu``HLPp^#p0M$Z9MIA$mXu|(0^LaIC zbY>ywdnfAv62Z6CD5EM1dxp?fZZP}a?(^k6FB2I@{SPCh2I&Kmy7$%Skyf@+lwy)~sHwR|Jdkbfu%?M(^=bz=Cv-COloX+c!P2BK=xh#stQq zqzgygaFB1q(S70=}CFBGIE_~9$ zVh!mslLG2eD^8ahNlrmjx1ElMrHU`PWO>8}RKuaWewEKd|Zn9GWepH_SNu=wJ zgSP?soxW-;j{Vq<#=80vjhta-Eo8|}c@$uf<#{#tBjpKm0-`Mn;6l(8sa5q&*2(>wvxBJ9 zcOkK$fS&O&t%8pot(o7Qlz_0v@BW31`cWJllZqxDIfm$PLB+@1Oh3U-YAQ zBV$K&&B}18esg+b^S)Od4EP#yFg9WVU$A7Kcz3`{s*~{W$;rCWWG2(-w?jyE-s|t? zBbjCi_~fQgqR5*$7mF}x17IZk6Ct|H8Mhb*nmz2ACL;H7ltTYZZbccJ_j^NUa%YuP zS(7x7GauVzsflMZL3cjUo-U$|p&>KAST7%FNa}e=lduybSq>*dNkGp6lB+^4#;WqL zlRnId?J^=6v1^xb=eO^EPe=6*^C~G(e*bPt;?LQ^F3vk8EmQk0x)5V`DQ;dtEHMS@4cT%geMb!HcGSrXSaYqkk$xE$%YZk2b zU7L$jh%K$m}R%f_`?zPcdivY}9 z0KMD;qe6-{aO&|xXSORPdP&kxSs#wg`Y4%nHT1}--O82@JT;;1mKAk%^uJywjc-POmzpvp@6D|r zC~L%tygGt-_5D}2LIH}ucH7=0+-9Z(Ox|B{0{r?Ut1b&_zqoGMUb_MZttV#JqANvY$=XU0qiB@az4mW1|;ML~{`GbnR2aa*Zn z;2i*`xN(}CGpI#)Nr95|sY?NJHFDh31V1pk*XBKW8M#|0ygg8bysN6fpLF`J!#~|n zaQ#YBWfGcW7neEF9!v22GuHjyq_Yb9(kk_aG zGZK>)V{6XJxzF*P+4H;(S8x-O@E%)moqVr{P_9^ zdkgRme0mZ} zxe4+tQMvNwo%rIdT#ZMM0+eC-OGe&DSfBhFils$pwa>av>yfPYU4Y1Ad%>X8KhWBv@zYuKVa>0A-?bBRbbfgAS9t74SWy&ND* zs13a_bKeb-^j?njU*XJBAe@Lj7F#*L<*?Xg{DpM<*zVzc)Dc^fyYiSo{UUo4_OxCj zx15y(q>nTMV#ZI|-S=6ozM1j3xnOYb@doPICUTd5(<~q{>Q~CB@c5=A-KR`>XC`@^DX( zsOFXHts+3Q8Yb*?GKYoE88-MVMmQt8k`+6e=ow&%M> ze;w^F;lU=0gr(8Fl+kfzN#uV9Fjo4g8+Zo2upzSx=?K^KF86mDcBX|(p|WS9MJj-R!%dQ$(OiPX-7X38o+~?18*p<$ z4mpIG=Y-A}tw(5%y@PU;Im-zTu3ds90;8$IVY_vShUN05Uu9Jfr9b5o>g=nY%TO=0 zYrSr+2#FVT`XE(L2W)nL_u8?Vvt=Y-rH`js>EM*}8y77eZ|Y>_{*51L7d1-E7sBXP z@q!Y)kA8r3C+lt5fpl-bF2@a8%-ywQ-(|>V7p|B!%Q7V9Ojgj%xa9Phlhv2VL=lCP z#R-2w!fd|f2*v6tKjfHt-ofwqfHNpZmtDqI)SQ>f=lL!{6;nzMRP}-h%6-`}NyPr_ zxGtoxgVF!Jr~ZL`(%WTaEc5D_dfW=ovU-O{I98YEMG`!||A6j!!{ZfJaEAW3F55m` zP|yOf7*KOasXpDK97xk*y$Zc>?ElGU%=R!C!H6ZBLw9ncyUgmiD|!_ttd5`5$d9>t z52n3flY7s>?^52b7Mjphg)~HjG zrA0@NceA847GaQ$p~xm%H|;EzK5csXZg=`0w33sxJ3oYeP2 z9vc{KAjF(@l#Uic0P=$ciq4ZPNp>xevF!ioibsnPV`c>a2zUk-lM~xmAIX!xs=~&? zMn-~a!EaNO#M$u2IyYT#!kO4_GSMd)@(`=Lp~Bo@;lqcCe*_Bn?F4 z91kVDSSH(g+)NV4SyyrK@7$>#Ix5Fn+K-@H#?!h&72vwLd_QM#)BfqA1}RN`ZNm@R zlFf|yymzmv)N$$pSE88T6yNss>a)a66?YUl-13Wmp5~}mK-ffFzR2Zi+vcQErl!t% zIoiU|<@3TuS9>Q8!OnRIwhV3PYzh77hcSPLnuO7+FMoU$8^;#v{J<##?)TKWO8%XL zvK{^$g4+KMwbu{}=_40g0{MPr`Ax&>Fe3s>!uq#1h)GC%9mTqlIs7$#jS$ZE|COfk zqpx5xEU0OuK^PO&XNVJP=vLECaNl~**M99cR0(Vxv58H^G?SGQF_boeEaN)=wUTTdsxcNUPrxtMdg$*Y2IvH zM9{j~-kI5am6#ufSC5VTO%Ltd-#X{4yG|2_h0!f0vYcveJU*=Mh^A+7@olJl&>Wp4 zX{z@CYRysC0r1-DmeB3(`TK#e?CN(G0_Mcgq{QMjrrrDNPbm@$lGVH^xFq65q!b;wdhpVZ6JWtB_tXG%?0#>0QQp`%^Z#`LR! z^R8lc$ZO`a14F`sE}RMmL>q_reP4zyr>Ly&th|c&DhmI4NTueWNU6rB69xORM<xQQdzXvcxi_920i-BfAq(-eqVUR%KO#GO5|>RBFu+DO`D~#0Nb5z>bl)u%@ThqEurgEKE&<_JuM#iRj})e zlTFCxclf-y8HS`&NoI+ZS{7!4B?w;p3Ke=uL)BSEn#J?q&{c6Kr_l__Ao3Fay z)m-DrA9fm_QEi)J%bRtf+7AIROZ>A(WrsP{pp=VDua%)jo<)s@9E~p5{FI1gTmMa7 z-&3Ul{jkQ^v+3xx_Bxl0^!x6#4!5GeZu`Yz4!t)bvJEDe(B}M) z4ivP4>0rI!ol4fY#+eE*&bkz;Sk}t4ulBNJQJ7NgnG+inEIY~vw{oX?=S*ElGz>|h zey6H8U#lR&Vb{r)SyfvOiBG5~g~Z^#emVL;oWJof4A^JSKW~*An1^KE|4RNc9})XsTcuYAPnik2uU{$ zs=EFO!T+Y7^ze}D8cw#ZTTRs4+&rI%Mon<^BgozQ$9L%n2i6JIimT89mZA1$NUsj)0eON8 zuHgZ#_picDeJ+SQ+1u+t`rBSxe>8AsM;6!aku z$TA$M#mq?~L$c<(kSHrFV+55AqUw#Nm>jW_e!GTBzf@h>jXzv&V-s0ke)$~Tk|RNz z{2uK!xI;_>+b>iYS%q-ZOVu?-9lNjU+B2pWfekAH;Xt_oqs@;Wds10 zs;8BQ{Z#XWm&8kMV`n$4N`bYn5U9egW5sTIrs8TC=EVIE&{&;j6IDhK! z0!IjmW|{nbaC_cS#JHgxbWjE6j~J2H6jO%d*}OHZl%u>Gf50Ell_pAZiHPSb6u_0)xOi1X&0>{K9g zQ^kgc3*>%HIqMEidIGKh*f8e=9*u#Au{pf<(+Y8pu)HftCjCnmu?D*cNCRu&apJRe9bMUc62)Sb zZARDimxUq4?cDmeWCGu2Yf6Zq^Y#j+NOv`slGnpU)4SL45`&eYjnt!nYxV(iG;u`C zgxN7QeS~(`YDrp9Al$R#Ex+5~cG%k7zvjtD;KH}RUswrt zYCb1(-mF)8IB_dm9T9#mbKb4j7krMMIi1KGUXR@lINj*c5vQ_}M^v1HUc5{?Vu4n; zZ( z9OChi0Fp6J^SH$~UZFfiZ6TW>Z}XbBC!U}>fl8B;!NOUnGxADw_Z>Jy3cL$?C^~kg zoHA=iLDMw1O~;k{wonHkzvSZ19&3q=)dNkF-Ewcmufx?2=ZjlQ=WWMdql*FGT5qIe zA8#MaO-tErMODY&xS_posJQN>t9a~wpKWL}wrTy%!3B$sAA0acx(+$divsu5&5M$P z0`pbp#1<2qg862M`Lp44Z z@kC}xSkd6H<3AMugP-S%ZWWyghqFE$+TYwqB#iHSFC4c&H=Q2xx#v0$E<{#B zwu2po!nfszAkP`?Q(HJVSGt0M)L9$_U+<=U$(AZV8?xK!_xO5uP(_NI8oGQji0EiM zseiuyik`+B^tIj)sk8yXLwj0&jQQ!&y0xKru%+?Ec5%`28XT7GQUb#g^td^zCHK4K z1ITC@Bc0~x-U@~j*^xXQ>8|!Ux#QGc5%xznxNFrd+PV_w{p#_Tp}0ESXR6>{Sz4$q zX1VxhF!0|VraA~SD_6oV+$h4fKo*C?*&4ixU3Q$rZLZU+K9kg+mC{fBOmr_~mNspt zC4VtdzooN^HE84KqMfp4=m#V$a(s&&bxS=L>33`7o;MWfHI3IRKdS?KopfAY+2dtJ z#ko&}Ol>D;gQmxugt7I=7Biyzp};7G z)}O`2roc!+2X5Reoy>Di!Zc(?pire>|bN1eAueI+!KQ#A$A&{Q{QreZRptN@N)@$VFmG5Z?d7zP@5Ruo-bh?bwoQNZMZmXL6$M1UB9$Bt5pI`i(#zj zk&S_r@orkyHuMPYA7*K*6SIroUgpHo0pv>v30@uJVof_NibX4B7#!mdLPks>WAA0H zzrB!hL#a}mYEzo=wN9k&teg7&z~nJCksM9%m30vhBu6+Ox}rs)00q}+mfd%d82Hns z(yrQ)u6A)LzFnxEIdSRCrZalvqaRUBO7&23^i1t>)%b{`Cu_i(;m_QgAV1(!d(9OV ze&yk+OxZbxzsjG@wbGHADFkXPFqe~-^|jma_E;jB*_mXumvtlR1J~T3kdJy+ z>9{C)i3XZwacKa*$0PZe2*GYYlE(>C0^Im{z3OPo&BM2dF-dH` zv){Mk#+TH^JnZF^R_pX-Xk4(PdesA1cHxi%g(VPNg^=D4#>kO9gD0z8N4C_FcW4Y+ zj)bea_U>ya%#H zbI)42dD4a!2i)OJ-$_B5O^+c$o28wS3(72=pw%{HT6NXr;duw%$zrlBWkJ8|)T8uaX`(?~i^YAa~7yq3K^-*E># zHa0Y-?Y4`3z;!@zD}Ww4+#^2J_%r=@h`e~ZpNWQ2*O*+y1f0!+cQ8R04HtD9yt`xB z@1sXsgCDml9#dLRcEF#HNS_LKprJpu{prx`LKtni`H)6H{9W%#DA$|E^E}>J=6Eh3#hWR6 zJ89-~{(7sQ543JpKW`_?Ct4wcyEp{u(0uxWSin1E$)1Y}(+P(yR1=*qcMl`3DdZEI zqEpKj>pwmgF(VLo?hQkB6x{$w`~4P2%pP@<3& z7$9tzi4og2V1Wd%uk!fCamZilk>)M52(LMDr#VMbSebrtiETav z=hsC;MJO$;Qyge*83|fX5EHuU*2*jI^AyXxc0>KZmyASUXvdH_dljo}YK4KGe)7HzXI|%9bh*!ḅFb1Riw|NfE4^U&^Y`LlHQxG^=|gAX+mpG;&^ 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® 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 z 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

pv@PCl|*QJx1^I zK)A_jXH$4B?UMa?uH1Upu|%5f9dqlu#L={K`PME?dB#z&`#hB|_7w+Sxm&URuZL}& z<(nIDvNH=5yx@DtsCY52fnLsJOFGbAtRBg-Wt4E46Ki$JWvDN!6mWkBqIJlz;Xy+$ zM4%kGbQ~9w*P=TgaxJTUh|Gpptj~BZ+}Gsz<)a8ApYpx>0=szpbmqHtx;MHy^vz80 z4o=v$FVIq}TchuhFQ=VPDfz6dI-vSjO(%Am^vm-VdhOHF_Z;&saj!dwzZ?Fh5iuWRUkg&gpNUm>**6Du@b*HCL17bwXxa+_%7OK6PZrJvGJ)lWI{z zCw+MZfP|`&lQOzS^E!vuxpxHs>|1zQpFLmQ(AIkFt$-Eoccz~jx^*$QYF`ii=@4m* zR$n9?@VU?Eo@UuA%(KVR)4cQ0BjY*uiB?~N!s4-Q2xhpgjV?c(z$Mz{L2_=*jaK}z zW{JBs_gVd9rY`h>=FknVGIyeGq4(dQM1GNVT%_gF=)US*(idKYwoCV;J}^}->S$kK zD7T&C-FSUt$mtf_AT_GD6Szv88+`C7?*E;x=l$7wOs8q8$YYU6KhBq?c zZs|p8cSlG;0h#yHp|Erwq|YjU)o_;Qyt@S94zqkkia*^6}KOL1P)`K8z*{wCVCD~^+&Pm3j`Pt~E-&9$zCnzW8l{4boPv0}@ zDIDS`@_kY%+_9g;kRUx$cesm%9`kfpNi{p7 ztxu}U)n!{f#2ZI?Eb+6;^dlNMf5a@6obbt_PZzDBZtm+le8F4HzxoHxH;>us`B4c| z+}~0*o^dmh8}@aMN-&JN&(sOlx{-&GiHj^1(NSzC#jIR;bf_y|B58)#Hv~i9OXx4b ztW*wf9<|#Av6o@Hbdv$pb#EmvxBP$s=b0N)In(D#V*8=d@FNQD8f@7$q;JP`Q-Z1% zUYG)U&uCVi8QwvrNF^J-h_iw2OS9!LlK)t-KR}0c(PZzunan81$0qyWu0ok$v0dym zR8=9(-;E-Z;zEwlv6horSs&2uhr){=DG31>&L3YNr~F{#Y#B>;^r=|*6%(LatZsw1 zw+wazZO@r(9t;Fy=a;2v48#{rA8Wr5f28s5WtK{=N&9600u!BiNi0+F=chq)Ag@z- zaeXm*>MM4)1TIc~YpE6cD)BhH>+<{|#eCl8YUH(r%$E~WZcwKq67fpmz^$L{zH)K2 zcPN+Was_^T?twig&aM+P2zl=5wA^Pt)br zEzYU8a_`d(vOUmc%Hl#jfypSL#soFbohs$i-}~{+fgA1m7t8W==UYq!E7fhK!FxPs)iOSB zi!@Z`&N6=O2*t{CqnA94*^VvDU z#*59z8K^InB1I^TIm5o;SEJQvLXmyDhA-yVq$hgl9X9jH;54;Ki|Fqi=^LKMOP3HidxTVdy0B|?Y zjEe6_j}m^HnPH`{0v4{dIe>4Mk{W3V zMd`ayKpU4-ergF60VLeJaW0U96J-s~4*Oy#s(@s`b4cqHZp@#PC4d;ViREfe z{a*+W5wds@=Cm#nff~_IA=mq48jpHnD^ESNHk^F*7*rWN(m53hIA&+0{Xb>#`lHMI z5%!2Z1TBzG!zR9MpE@`iZtyzo`y=+jhYo6+Cv7CxbeT0IZyBN$gS=6N4u|x&1^Ut5 zzi~j%mFkafKWaWlkBw#NZnAxetZH9`P{7IT`VsEQIsFi2KJ$H&|I(>q->aq_NgN-r zSfik-NR;EN@6YL17XH+jG-o%g&HH;Re?{+I2QBPI7b~oyZIx1L;P&8GHR4>R6Hjg1 zfoTfDX&KM&!%`$49hV5^!)J?I=J4x0WO=%LZEMU0LjfjAf?^@SonCatH~XTQjxHf$ z&4SbQDL#EbE_N_YXEg!7{$r3L9P)hMf)>*7;bw7*?$KCd99n8vZDiQCS?~7*G3Mq63%R<~)Z_wG-dCvt04AK<1eFaK-2uF9tr{BXtR9B`k60}( z>VSy(nRFv{_%Ky&o^m#)jV_;cg|7>tdRS{;ZtLMfr7rW&;OpvGTdu}NArPQug28SG zm%In3vN7C}Bh+*-08x;dG)YkiW|>a5&JP%SkP40HJVeX!bvR!hPr0pZ^3_FgGyP`& zGG3#|tO3i|4sQj))EpzZuv=~La|iq36^%m}#5le=@)PFvqJ0{ddO0n2 zdUr5UVYyp?AXEFj-vR5vh7mE2rY374u|=9%lNbJ^O61Kha<%&)`(elxx1Ra z&MC_2PS42wRSr$osE$cHeIQz$^1ChmA=348A4GT`Qk|)t4{uC@ATiwo+!u7T;^*K1 zGCSU!&Z$^QeGll62qVH;g?9Ks3c8K+Z-@`wX6K-mr77-Y+v|Gw;tLOkOe#TiuWs{T zPr{8y@L@$4F6?^O)Elm3;3F|k-S#czy0GQ$+HytWNpnmv1=Rl%_S#oXqp#W%{vHqwbdT$ zBR+;ufShrb5;rGA;Zkh_U^?F*rB-?St+ZeM!w%G@KrVx=-PGMgKwG$Epd7HT!)~^l zxS94;)49?I+Bl>A((r0&9|H4WoW&)~hJq3<;%SH40klx{#2AwArZQmu&ARPlq@Vj7 zUH##@)?idVEu$KZ5)@Yk6Ze;4d+d8Fda|d>YTMmO1P$|vC zC_$YJI*ewSEg)y)UKwp=N~K$nV66ZWLJUSE<8eEx=Rdx%*!6CITR!L96fa5%%!FBm zUIocq&WfJrU&K5L$cJWm)4VdZtevkELOz9;y8W12JQ0QF?au4HR1=bjT&uRozBBFsEO_%@|=Gu}4|S%v4_1VV7YBScvrid^*+<|vWf=Lgdlr`?)#&_{JB2Ko;pIAyKlB|6e~n}; z$gVR~^-VtkqDF>%3HeJ@dWA4@G5|-P2c2A9IbKgUx&k;iywNvaesfaV$$n?}j#KsR zx{acCYHUnIPmid{W`zv?0s(w5qR1ICo{y z=(DiWa2mlK@KB? z&TiWd9@QmW_xpam&u3%Che%Yb)HuC_&Pj2V0Z<)WM}dEZl03$u7A#aWV;!IAVe@g?b4$M6vmQsh9r zTOPt3BVJf4mNaOa%q0u4!_L#ncmlWw3PzE<%WDmnq;tP5(fOYwnb{2s!Q0jdb%xnS zbK2ng5Y6h$ubAIv!WFbqOaY!$q-sY3QO@%oeG5b`=|(GQ7B>qZzsw7NOH7VAAs;XhyB);A4J0CsKKETurYoaJBy=|=rC)RA;6`^rK+nyTO*haeD}>swUy|%%Hb80v%tMTpn-QmV&O?YVwbf@L@_1WruE6&kx3aEtoNudi3W1ogPa_4|4X357ix7d9T{L%C; zB?fqA1gQ%zDd~KMnZH5>E3;&2@oRnJ5H}$C)(t}pd!Z8Jx@z&9_6feZQx3b9ugZIN z-o?j>9){Eoc>KGme*Uj~)RDBD`qw83UmuZ;STI+`ws}1&A6yLQ*tAF+JdZDQsqE*T zQ|@Vsvx_w!?Lx?=*^7Ea_9N^`^wWUGrrkyn>!`k9Jo}%2~OTqYBIsU_*n}$x~!2b@aNagKTmx^@bg>$)!@+v$G&^xzs?wJXjAQ<7gcvF=2nhuL5G=SzZr@~T~D^r50+GB1fQj+5ip=y5A`H;U2z zUQDmw+r9oD*Xc~VHdJY8=~_^xR1slVoWK)~i;Ii<{n{-=Okl8aX;MN~mfl0-4Wkdi zivsZu;vrpXqLD7(!xL-{V9i{ECAKNKug4q6K%##RAR3 zEeRHIwXWcDXkjaky}%fIhbTr8I2I!>B{X+g$mL=nX!i5rb4}ZkOgWNK_qHP3&yah! zxTRZ)(NQ5^->zMUp2L%PzINWx`ln%H`=kyC;h3Y`cV}2XQZx){YrgzzczAd`qz+mC zOz5^MthW`jyTTuG^!AQhNGUYGxU^I>{368seo;NlMAUOXyE`%L0YNM4{ZTofP1f1~}2bo5CP ziWJY|Lo~)7KXL32l?llP7gF-Fu!rUWRa*Vh9{!fkXU_9 zfK-Lo9Rov~Dc(nC#$Dl`VmX}2u}cSO>1#k54QOMi z)fD6I0 z0s^@(x7C>C4UY$jJuL`6e?<_OU-+>pq`C zvY!<)p)5>@5?)0|w^p*QJ?jKR643Nxd8=VBNy~$POs8;m%TDb|jsUT`XH(weH}iAd z%|g2Kmp5c-s%B{e5h*x1D0tF$a^WyGO7O3&EhVbTQD98B5G_Xyn@U$qxAOL1QNM~^ zU8)T<8pzaYF`EZJYKng-ho&EqmusO2g%%;92>$fvtNPxaeat3*rjN?iB>gpdKWgn{ zH+9R;wx8vZGxf-)<-PBOPt;|NFE{ppnzNB!o5phwE-wDxUiCOQDC;K;1{ z7RqU1HpG1#wC|hs8f_}R{@gX}DlkG%YRL2a*H;#t1PpnB;&meR!_)ia9OvBEOkmU! zzk#vP6XVoo=|%xAEuRx5BX$8nuC)LLpU#vp@uP}o-0dyi!L24|C}q3rQZ-P|jzGgJ%&Bx`WDPzu%~<*IK}EmsqENhX-UrS` zEQd9+IZH&kfLoM)dJ3#l_s>G`6H;p%_09(sPL|bA?&l2nht5CZ1*j{UOfHI_vmV~O zszgPW;yOCpPMI`h6BKiYPq>EhWn&+r^t9q0G52T~7=&N9piY+CV$Nu<4tjac({G2} zz0QYAJD2Lry^akTS0c$gU0bCnqlJdn-a;|r?%OQJ&y|Iuc{)4iv8#BgkKHP7+nj73 zawS*IEf2!Z>nc}sz>Avz-n-lZvM`ANV&w_FD`>NquavP^-wRl}p?L*1{GHnFe|iDu z)uQbtiUgPDQw)-(yjHw-Jq}18<}7FS_H-atna)JQh=Sr~zhUF7(kFFMj2 zoce}u^s&vvd9aI7{F>y=MsvD)@i{+W{?6g2FCkmjThVA)MzI)xS_qv?Xb^UPM*WsTmXbqA* zTFyweE-o@flRlg;+n!g6$KP~xqFIf%dusM6DT{To(AJ6h9#YVLPG$3IL`?pXx{qCn z10}btS^(Cl2WQ{+o!Cqcec*LH>2a)hkFe0HDD4~up*$CYsYg7(IA?9gOoN{VyLXz`^;C;8$Jb(U8HdJJDmb8aj&-Vvi z;;Pw0MBb!`ff9)>bej+T(l>P{IXJigVX?dt^(9eR!EJyp6~Bck($ATil=PwVZ7AWSjrN!=`PT; zs&>c^(PxK?sHrSR7!&b(a$BLXYYoyHlM9D^0~2&B#f4{j^HE7SxOb!wsH;B;3Y3V@ z|Gp4Pg+?M4*v1Njg<~rwu308W+URz- za-qRvUkvc@zqO&)eyOX>s`Q%ymk~Gd4KQc#Sr}}!Fi{j!9yNKk@c6*z`1wC6=o(-1 z|I9m|0skVBbg?n@Xt6#V>(a3M%X#`XkeqE|VZ*wT=MZEvsN9`TC3AiYLUa63kX`zy zu1a`rljSc%8k96C$tY=TqIquRJlZw9EAe^`q~1zt|GI{!&h?jwY7T#|$M;6HHf~^> z+ECrrsdH}5kwfusE_tlvmWb9>=Q@l;QsmPgxv$Z_>Egm~{I1N^ZraL#xI*NiT`{hr zo2NB??e6e%$0@oa{wDpJVN0_Co|z}7-o-IySV2jQW0Z8)FLtxrE`EpSQ}Cg%?eM3D zpS>`X-O5O_H@%lah>YBA*!atwqBvyA6G4$phUsy*<-EIsMXuBP!GP>Kq9lCs6UsU18@$V@da|x>MnyH}z$|yt9<_%p)UH9mokNB*WZy3an z3uq$rT*!7+_T(LOij9Ga&`{_XMk{gS)MNyNIA(Ej#Z-?*;yJ}nZq%b&Z(LsqS#^8I zxip^k+9N8Mt~_C=%Xx=p&7x=M4E=nI! z23g*@14W!ACnf10tWKtl9Ny2M=1SOGV8`bmg28HvoElQcJGh^j zZU}=B>an{FRg+_5eUQWPNW_a3T5(uHp(jPe;&77J<2OpBxTvVF8A7g1=A>>st?SsB zKGg(sl?sGzJSEN(%kbIRv%|U`#SoTC{9m0RV`V^rD1=>qA`G;GtT{wgh21jcTEuq$ z2UOIww8VnoZBmL8vv=IQ#q}gzb#)N~M-vS>(o6?oDClf55xXn!IiPX2lb8Z;_e|Zz zot?t~!HWHdOLz)ApvGxqvn3bz=#u}3V~L8n)8@5ErKbsS@AtT5dQTKf+!aItN>j4d z0$93U?tSM8_NDl6Foj*$qnTVras~9k$v{nr;g@G(-f8F7d+#?Uo8?+%UJ6;#>2qkY zwDt4wVt?6yzj9ZXfPUK9S%)1PmMF@erS7|VC^$c$$L@)PTnr03ou^TvEQ>hrPEmFc z(ATn^k$)`C6fydUcZ=Oga?_u5id=v1lrwU0+vUF15=AKxV_mWE@bJBfnm9Bq{as0T6us4jk#u07?=X`B#4^CnM&Z&beLb&d zJ4bE|Gf@}YKM2CwOVu+F7c20b(3@9ok$QK@vNqS>$_A57-%uUcf>jAS!5WM4W9d)q zx_EVq3R%pzje(VEW3wgPIuQ~w9OMg-@v0XMdp+%Wu8Q`W#nG>Az+0W-iGwxDw8d2d73NgE9E^w`|sv@p&f>D7>>c}{YF zNjo)oO_ma7j;U?&KzjLr|J*tJKo2P)q5pE@4ZNZ7|B&{UQE_%#w(tvq;O@cQEx5aT zaJK{k1S_C$clY2H+#v+_;8wW1yG!AGmDBg!?{xRucl5pev&MLyJ)XU5@3rQdd#$-> zotS4K?9XMW$TLPH-nv9<$mST&x(2lEX_Jrp&4Jqf9)y~LFcGq}>~2sE_HP-O);4Eb zAlYA6r~3BYGo^11Ti)ZBD$IIcy zQM2FxcD54CexZ#67;=vl;f4Lq5=e?OWMmvx3~<7%KVNPnEi5b?mTQk$nNv_u;WZrR zJL?XFtEaMde|AeNOIcQ4nrN-Ku9Z)BKOf_H+aN&sfCZER<7ibhwUKAyW;a^obmXr6$K zt9rb$*j7$+b9m-nP4PM&>b`l(;Hprzu@OJ9N$@m%>Hdz_c;Bo+x;X0<5_mp=guzDh zh0N|5rZ-wi)Zo{)MAy*o{*A|TZ&E_-x3#RwSfnkdW81$K@S)0>YU}w{J(LT*mLyi`FKkL4#2P?) z7z+acASJf)ppYhnjryx>OQ*wv-17j1kr|K6BTemTu0ofKz?d0D98R-5*+vN=0pg9H5>wPZ zwjEy!S*tv<+);E4bTH1oQ2I2JOn>WpmYbADR4S5OVkk^$L`Tj)hIwB;reu4_+}(BV zge9;P2fku>ZiYV4JFz7El|?fc1s4zI0p(g4A1Oc$b8|c-OC;z3YD2t?~nK?SFfNUyz!^ z8oTzIzSkzY0j^*)G&1vEvEMb9_+}Uk5^4|u5zxp&uOW(K)Fj0$xV`=T3At_3x9!ij z)#uy&g!a8j^ohw>o}N#zHTXnLqNuylyTjSy%KIncJ|oPH8-(lk?{`;Ag0@zCdqCS2 zl!6W$3J{rw4{2#>zjmIP@9(!Od3~On@{_xQDhN`&UcPCNFiJnq-vuCtDaeXyZejqwu@(V(FmS$nQoaC1eU^epCWjW2D5;#%_$Q!kr&ZPRyDB0o z;J@iDo!^B%Z$F{zl#|UtKYqR>6_6&Br|TQCCj6*$M><`5vr~vbxB{n}$p@102soB$ z+&zZgkM}o9^ zGxs)lo8*@BBqq!Y!Ad@?GeQy)C!FcPa1kb@8tk)t@*WQz1z`#HPTn$dSc2=$Ky2Hp ziVK*i{MVqZGx$o@t<-Q&MmV<-AoBOUV~oUI$wp?PW>`+K3l@UH_^z zpif-K|7m}eoLhj)?1nk();aW}_K{N>DY zwm8-9Ac{sYe`VNvC$(-vjB4^}=96JqJ>emFumXD=Sz7|krUms9QlEo541sanY?I7a z318Q)1cjC=#pwm?t`s&Q>kpW;u~4Pfs@`r$NBmmay9F(ZF780r`t@~lZ;4iY`gEkN z+TF$jkDFVB=v43y$Aa(pPvxMB$NP32OIK`5HVR?N$znOR$IQM#63c>DUnF6jy19p! z8lqn%17S1GVWUnKE16-o=gIs|v(-B*aYvYB36x&rmPfPub3M0q)*07_UiOrE?bfm6 zh;rLkwN{pBBY?=WPO#4GP`s<_IM`0}a5n@JCd^XT@Q+m>rzQ!#ThKjfmv*w?mkjb+ z2uXN3Lvwdm*(q*ceIdb1$`9Gepy5R%~}+$HfS( z7a|ru-P>RDEKRvzOLLBP@}XZ5p?!TL0Y^*iWx|GO_mpTZ{7RPoekcrBmiAe^=29{a z$a&#~vlwV z_)32n0%$b(SOaOFsz)i>E-UDnZIk8qpjR7c6Ys;ehiJwl^hgoIP4~PV%(U?D5 zlRghpjVip;;sYU3?@}qwTX@Ijn3onOqiamlB`jca21 z1j(~@xckNhJX!EJACQ+-^ifXkp>RdrAJ0@9u^3QvvrRI_3g5`Ex@-Nw(1Xu~Nx6-s z>iLKb{SNx@u3awjzyS^4#FEF8$)p&_l_0p}X$ z=ZXlC5fG#b^oR3)s!54p8`^Ry4FZI)H+`8ms*q*f-1qaZ4VSZR zCa*6iVo7J716^d4*sNE9zvkz5*1#oFoW{i*0~0{t&tFIUOHqz2)6vQaT_UH46+vgD zl+l5VQBl-sRVnCMh-25kN7On`hDCI$dh72-6$jnP<~=(&%lFz{KU1cVB&9YwV4PWc zk5Cho#A?ou@qhFQnAekztrbY{5IRW7qIR}*(4_k4o<9D%7PQD?{y3|f>NDojbhww{ z{oQD_cr@uS^(~@EPw;2904${podBfqmeG35X|P1;`nW{4C>yYX5-H5 z;y9&PO?|7h<9&CEUGTeIevAyL#kU(t+9Ax^g8_y3#0`N6k@fAh%yaK~CW6NGcKFEi z4k-i^?}7Y3P-s7IW$Upft!h}hAy)kSZH{U_zTtz$<3sw{@Jh#A>p8o(tFt+8?flA? z6H&6lP=_V`S=RO~Vljhh%Pl?A@Wd)<%I;?C`YQ6OEc2ewV-(n?pq&8p*8aF6plJnID!6kvLwPHq{GMranfb7U3pF3lkMvFBWFKhk-6YzDw$tH^%M5AO9=rbWkh;P9GdDqg*4n_*SWxLm6or_OTx zJvi^erZ;SJC&ouWhstL+nP7+Ql`DMoS`OPskuMYO{d+o79yZ11G#QA1*Un%(CqeWJ z)BTve4_3Z(GzHuZ&F8pUQLnbNm7)9tw>WuiU0tdEzo2;CA;B#gshYSWkaZs~azkG) z9fN?tzo}`GffP5Pv9Xb!18NS%!ony#D99~}swZGDRVRqo0IVA)Ou>ShFBgdafgs%B zBLTj^E+S^pv=@U?bXXP}lsZlE*3{+8H^$g zL?+Ud+hT0^?5Yos%s3EP0y%?I8xp{yL1!4P@6K)39wZm@1C__T&=suGWh`rm`t&`s z^anjJv6_5_RpHjqw9T?*;IgbhDi;St-Xsq??e#Osav~K3ql<2O>yBl^gMA#a7OgA% z2gS=(u5&HPkmR)sP}e(E5u=S24Mv3P%jxx3n8SCK1#6F}S1y6hdWGM1pK4oj1Wrr@ z{P~Z_CdIE#&U+*}t5Kzj6Q`qDcyqo?oK9=mQWv|3Wah^Kw_TRK>7tc2ooMdRss*;NWdzL6y= zymntO<3jh5xYMUCUzFo1+cGZWB!O8M^$ftP*phJPQt7p=*ZA7FPyy=}A}LJ_NrD%A zdxrizKH7g>o^y#VtYb3k!kS+F!o4Tex*sQD`*2GfZYN;K?6iEk;DD#!tK8XLzA?m6 z=)1I?W^>-4GItcDGqdj@11ILj;?p8Hzb}E%&N!=3);?~koov(j;E|pNQ2t>PsyEWD zk~8RdOP*+wfQ-aCsTxaT*lByCk)Ab~U({dT5u1iZDR}qjTX%mhRi*gO+@S}0+(+5( zI05Gzpi?2NxhKC}+u%}ttaGtIuXEtIvTq^MHn5wMHFNtV5&lFimi=8$GSq0c_{`O+ zo0}5Jn9&mqH%@a0UVjpiVBJJYR9PZ)i_2Fe?$f#Gt<<`Uw*4l!-MRzISYFEoP1Lzy zmOzRL#pVoQ*V{D0t)CZL`H_P1D!mfptaHtTiC7mQ^)JE#;;*LK?dTi`3IblmLS;i4 zv(=^&{*fYPQ?(Wkfkq&)MV-gz=~S7jF|Y{u!&y$+0y)Q9$3VNlx@$?&k|WmKH!mnO zW&^)qr1Jr%^UD6M&*$u?o-a;9Mzw2Se!}ptznS!55tD2UKU~UVKDJhQeShaJOzbOA z?x+%Td*-QVo_3zp5|MYu^yAnkX22zja@5nAnj}3Vc!gSJqCF5Vj}GCJZ#&y;GMo)ci8S!6*E6cYe(Eq5&FHtw)dBw zE5#nFTSuP`vRB0(147%fRRDGlzVMoFeBB`9=GBpYkU>x(kEb9yR=Z!-wQkFJ3aoy% z;rjfNYnHG(l#y2!i1y}jx+TTo?WQX6p0U3SrNt(;JBn2BEfICSd$iRj*u7;vF?j%S zHNtn7)ws3co%B|#Nb`98sd;qPh{*GWM1{cvg^}-z%eS?kIQE?{mTllQPq*9I*@Y%Y zN}aaX$7B1AXr4K<>piflOw7(ndWX-82SkkCzSd&wLqsFOdFLAxDlvZ$MBm)x?e%4F zWI0@=gP}|NyWX=cm_$QMYb$a5HAbZE#kT~WGgpY6AVcIKgTZpOh36mqmhZzz>&9)p z&Agh>TK~BZSiq&NrUu^F_k{~0BWW9Y=G1zyQj7e_h?f4 zRuzH_1Gu!;1D<IwrtXsMS3-w_!HC)#}zvb#V*1 zMQ&2&qZ8;{TrG&$S+cK zb5guFngr#Hbq`%a*1AbZu4tuwLCz2fPgc#RWFxNO(4e8QaoWU!fF>?1 zOX4rS>N@oHJ1=IvZ_Hs7>Nu6i!VvjsKaLpsAMW}A=oeI~%D;mR=Y_YOZ#mSASC(z2 z!zEj>)acdkM#HLYpW^RbEX+){GJkE6k=cVco9N2_1grW*(XO@$rRQ ze44pMlkO+WhP77C(-6MH(~A>com?OGE@Z8gu!9}rmy_V^KhVK9OvK|I&O6+yla138 zHPa-`%bcbacr@0o-BWO z?9)k1kNl0r#TFAT^C`fp>#k-e zFmFf0^D9ZBz8i|SZ@ump^SV9rG5b1G+q(D#_%MojIrSzS8&aJumUJreqwyPY4Sv^3 zpL;&b`uW#={({b07`YfH@u^Di_S%d4iJ+gD0P+?L?XQ0^ZN>Zp(-ONSBvxBF6?_wxRc*tQA51jP@2k3Tj|> zKbw61n86+nYON|qi$;_36x^9aJ9j(>fr-0|R=lzLTkVehHYQVVvobE0I7op}Ckxvt z$Cseuno|Kz>8}lm9KD6x4?M;an_@ubqT{R-n@4@Sd6t~n<7Iy%pV$$ej-WQe9O(w` zNWf=`v*P2&=PdyCckL;c)u}R4#GdK)}5?sb<>=bk)>D+?DwX|N$n@j6YVFy$5*UP zvFO4DMeIWll8Rvt#_#$m&1hB zljlR2{GKqBKm*MFn5os!CFRZ2x0gX?q!S-hf&D5`+_#2&bZnu?j;W!yr1Gl5bu?49 zi4*6_9W4@b<=>@S62pa=q!Va}h|*-YosxYqQs&;wsHbZ&G&aQ9Zd;BK(^Zf1Of#fC z%KLaF?`V>)()qcFeP52BOeFmL{Qk=1tsyo4^eH}-52dKq+?3Dz0~DtO@p&x1obu^* zzd6;I8Bf$}`e4)s^sY_0U?2zez`NJ{dvf~3%RuVPj)@_4|%qKw^`zHm=35?rcV!tOSCRRgn zLvV4dDp{d3vJC@l`(`}LU_E|+q^BfaoVWA{oAQ5-u68+y+WG9xDiVeQcgs`ADVw-8 z*rSwmCV*Dy_VNk*WHA3A^HR{_59RG;f83AHVPTLHOh9n}>K&J3_Q`NtW1^T_cX4_mYaro~|uR zrY*7Y5jjxKXv63XRix&E|CP1)w~!z=7RGI(&X1^R$%VMTd!`rzas{k(dqN{${L`() z3OCskX&@pt@90E#pB$*XZ&j{)QiWGoSNEr*Sk@(kadx9sjo9~*{K4hjnG!Dezm|@W?3murH3u))XK%ORYZJr<9~zdu8N< zX|LJ3b+tr;xscrC5*5#u@Ps?ICV6=Gi|N}j(>KpeVz6K-TFNyCZAR((RLRm%KqP86 z+Ua4OWi@bTvrweD74w5!Q%YKL%#2aQRO@o}68Rcvzb13d+?$P>io(gGJc?v zM-=y~_>pFKOUoBecr|}Wzc@J8v_oztPjVI44t6qEU72|k!y<2;)qv198$t#-lWN#^ zX%83s!ig}u9%}qd!ERc#x$|4^k_J>7n)WdWA{7Bx;~)TDVb7-sOHx4ig`s;>wadLv z3n|df<%9jP`ogCZ;GEX}fDWc9HTA-H>wAyRB0i^Stpn5S;_z_&Pm~D7#OC^TKb&*D z_TLLOtJ$l}h@3lCkAwB<9)I18-@48Al*bttzO!MYaA|qrKf22$Fr4NQddVFC|1f{& z)$u0OvIpMt9Ce}ZiwM;+?d%Y8o{d&gE^wS-`uvmpdsV=*>OfDY+gK%r>(n=xN8MCL zSNkKjxt2$EO!nh5;)FexvlZK>`5e#2vb;X;>n*#<_GsN`mFf1J47#ii-<+yG#A*@x z$48;N)z7QTM*<1g@V?62xstxD3OSxn4?zPZt5Sz0`S&C_SfH}b{^hLMnaZ0A@0OsH zUF-GE0gwgwplw@m*I@AudKJmdsP4e)qlBS?I^?Az*YS@B)q)I^>BRllMsr{1Kyr{H z+>zq#N5VuH=Mb+#$9TV#pHd$5;n38yWjsyU;C4TW8;SePnjYxkf7L&}-Zkmea-5RF z`)F8M$xXCc_l{D|&CbT|ciwp8mQFVbW@#gxnun)8V+5*K3|6r5=5w?BuSD{{;Cvi9 zOH1XNOP67{>+d%LnG2-g#n^A_b)3yEYSpX!_`DfH;t6agL4rgN&H^B94LW~M!sPK6 zRwgY=iSCf4Yr56Wl!lSyNm~gCN@2kIH;g5pNp!Q`A<9>Y=);vyr?Hmd?O@RL#6H~B7uPSd z(B*X!PX&PTiLJ-SX!CLgDW9|sI8g;LzLZ__2QZ}McCp@fjB-ZHIx;)-d!~WvFxam9 zYW~`gxPNECOnI8Z*tH!|z4po~yG0Oh- zH#bUt=m#kNWy1_71@w8$J4w5haPeSWxhRm?RYF37a^(G0R|aX7_ZE z63lAc&XZmG+4C#bLcqYeJ7UJ&_nsmw<(AY1Ro%>3oOQ#fS)*XNnACc$l)l7iI-x?E^2o%X~o$+QupypWU){0bdJZ`3cS14BSg^7 z6l*+M*>@^Lgfo558l4@N|B(h->lcP3#h$*ae&Z1q@%o@-)HzUD z!jkv+e8)p~{PV2|-}mLm=wea4dUZe1zScbBt558;)u;)M_qt&Y3z&bQBAKP%d9cl) zqZK{bg3}GO{9tx2FW9O%KSG)w=1Dr}GQMK056imk@9Txqda$xnPkbXZ`sU2h;kk}Q z!qU-#nA9%qKJhT3P2$YLu-J|QUTqw8CD8+VKa*W6kyb!A>lsjarj|KvX!5 zHQ;*-z`VS?f^xl)NL}W4&?2iyaHz3EPHFzz+V)z`dDiKVfDv(eYhDJ4~hB05p^uxC#KcJ=oi-#v}4TL;UF*UhyJuWFuU zkZOT8c~87$jL_e-kbt%Zv8^Pp$xjv22nul-d+AnvTFJ2kIWBKZi*=iDn!sZa<@?bV z&(f-(nDX}571z-tiu2k$2cFtnpxKY>sn=*$*Vi~5(vE@0kmGaGjqO)4($4M2_e`yp z1bk*suPcFPYBPLSM(g{szA=qY_FgUKHmv<5HqqzTUh}tyJz$-j=6(0#fle;@+9UQy z6tNa$<8;Jqa!~=9syj!c?WfFhVF?b*ho+QZe%kiAO3y`5(^9&DYcyA}_p0|Xl;NmL z%iYAwK*;K@aFtMRy$Mft%Q2kJejsBFA!D{1D(NX>s0v?DRd~VZC;k2MaWbmWFs&m( zxztotEQDE^sS4Ge!9^m7{9JDf&2NkDD&IW@}!!Bbi;d*_*l-+2a{dBWzSZOoh`EzDq*TsIh$NTHO z)hU-BB>g6NmjdU{u$IIuoI>=)_4U!&ejZsY0m43N;2IW8LwEx_7-`AA5{8`W(w3Dn zAGISJ<&nN$l9clD%(C*FChPlDK2>MBnu=C@smWh|4L!IDHsAG$j#YoFws_ zymCq1Pdx%@wV}8QNxy@eTpVofkNQ3ZfT8XG@iWw=_IkrV4|hf*iPG0T+q3wSJ;Txn z=c0&Fc<8Ug_HVm7j`NhD(pQhPFV%^#(p25p93e%;KbQ`#%<40xCBB5ex`&YL5JQ=J zG5n^a=NK+;&qJ)YjA-(;I0z2I?v09;G}I)fP%^EV5RHz0zPEh6cnWh``JQxoF9amL z;4a|4agdArcYu?H6&eJ0_>kxE>Lh63yD2W9#5Jt$O;2 z4_GU_>HZFl`6hl z95A25hjKZ|S+OdeW2}G^L$Wxx&7PFa^Lw4XgxJYqqPY^0E0>*_DU*hXzHmxfEpHrCim1s8(qIE2l$2rcf};6uBIbk7n2#{O?o#3tmuETa zoSUagnsLk}Yw~$5Jvrg@C#yYJm(`;}T(N2KiS};}L|GZ~u9NnGQ&7J89k-;co0Ei? zC%X+<-4XU{k)6nH%m%PW)k11F$F@0V;DWm9ACa#^PrfxU_LXl~%^8t_nUN>Et+=>A z$EOTJ!e)DH-X_bZ&Z!@9Mp_=Vaft$oiw$upOCwIp`kA0D>w%WK0<)}L>q{Z=76&fT;3-h_F7>hUXBrb!koe9mA z*^n!OgQq=!Ot&W6$OU zZQ-v<-kLLdY}Z3NXZi+>BPy7GxdCFEL2!26kO?{rJWizeebasGBX9F4E&53R)UWah z35uNU2A;{wnhV#MV`=T8-;AmKcEC`;5lu*O%Ir^Gk?1(W%B#Y+r^#fH^ONtBIn#?m zty8P9wqWpKCz+{-Sm$@TG{`6u<1pW=*Zl}6iB(!Mmjg3lMb7szJ#)NWpJ>%-m9*-{ zX6NQ^JJ{shhtSbYJ>V{zSut8@R_0tNQW>A+DWtY0sjm%f;g3?>P9r}t_6GnGPb^#d-i#Igi{UIZZ8o!8O^Oxwb zDb^QoB_UT-3&C5Q0BroGxx-86GvlXE>MNL1M)l}Cd{T$bB@dhol1XR%vfTf&PLR3& zhkzMB6J}1RmSjMm$QDVVKfhCtjhB$25)&Gd7J$s=|JLRnQQrGVsl%iC!&$rZCk;$c zmkGH;PyXPHF`q$+pXku-G^&P% zm6>CK0nhhpRE;+w{n9hDi^VPnF1u8D|5l%1parwXtRMbR%9$ryf*~DPev~Z0W3FCr zqd&)D4DDYeJD?Ff6VgTZd51-^Kbmu_svhUPIgB{*^o%t#)7tCz^l7=}?}h(b>+m1u z2&sZFxxl zu)33~PVI)rX~-BJ*$f(uxk-7oxRfS)F_60R384Dx?snd&f6Dg>jhA>1PO7{B12V!* zupjAcmv?DM0dW}&L?KX3Q7)X9r`dg~}e@)$A zOl2chWT31dsM||%TgK*9UVMPBEox#{qdlmbXg-w|Lahl!Q55rhqTT$pSOB7UR~USl_`Xn zjkq>Hi;*y;*qayZ8Di3jJ)ruy5U5f7=e+uVcP>MS{9Q!epb*bq(N;v-Vb3GGlGvXF_2>KjaD$Hz69eIBx`gs!^Mqy%qCOb7n7w?JQXmQ4&kddS`bHk>PiIUv8h$nWA$i&+x zAi@lZn{coM8Z?rL9DaBg7?4{#i-^z7Bs#mU&O;!2%Ptig65iyru^rKz`f7dfna>ZV zm)-j>Qw6m@+vXpu^zXj=zx@NB31&&pwv7I67q(s)xkuHqG=!c3_w>{j9wkyVupSqR zN~2LDhy2p50MlVUOC+?RK`XPmR9xSt95bNtlh0VRmi)Xj^z|gwE2>m^W%AZy5_(&6 zsaUe9jg_=IR-cWH`a>;xYg&VTdPbM~g%2}6Wxg!F2(mwvKh+Yds>{}MvoiBowEQRt z+G%aTfBDC-sVO)ZN#2V@^2a?*nRa=lR6Q-{C`k_N5w|sIqk8xny^^;fN_`$ww??rl z<}jLsALfixCQ=fq(}oA9`Xb8hKD`L#59z+rkNWz0=(6qrBchb!FE&;`1exWLNx43v zMn~T!xzg!Y;NCD(4;&A!k#Cl+XyP78DZw+kX9T z?UlbQZs2|LX~>Sj=Z~GxW+-iuXlUr zp%U1b@U^|NyDVtCl1j0fy0*2lFkW(Ay0vK;BUWmK>C7(oW-Xw8O`PH!NPWkRPsdUS zr#CAcGcIn2Tk0g-ABI6C+8DWB-^R-v`WI%RlZlv@lT%y0>vnb~ahQ&X{47;?6WKPxuTTPXNHTrq<^7@gj+nCwi?9BIWI}ljWo2If8lcSMwVF(h%KG@(p9iURkvU6hj~k%U7~jK( zqj-xzo7ZIcaRl04xd*gM1YOb=H?b*iqAax_b)w;`EHk$^T$(Ah1w|#Q?SJR=$|Tqb zr}+-R+$s7LfFZhDW8Q+9nfSzC+%9VS1xlb50^b(tjcOfta&Z|5uQH0M1%9FB;{bj4 zof%4wV9*sPn>*EwV(upFVEv`Qqk>^~jS2Z)O&-4K8lDS>h5_jK@X!>Br0~O^LjIGP z`@cKu?=k$-j}S4F&}5Wu3F^Pq%&8r-#67tp1;{F{ic=guUhm7|dyDavFJ~C#XSNd# zkQE<6bn9GuppURxa6G7Z07a@$zJ2zax{eNoGU|<%YG6TI!+ggV03$R66p61TY6y#qnr&5gM7zro zdJ0^Hji&cuUolhQ7+81p_WKlonrLQlPL!&i9qCs#pIA=Bc1%FHJ15yBA4oRo zL`0iY^^cjUZtOH-w$hhdBgoz$uIhjb3Zn@8A&crCAn5M7tfXD%n*X9n+`{050TP1Uu+;?^}L zpc^@nqahq{K!B@qg=W)UKH4|BCA&*}cf zDh6>cZy4|w###x9|HJ(VsV*QhiNeoIw~E5Af;rI3SX}kmDPbQ@&IH&0;!KS6KyQa; zU*SZIj&^}~A62`3uV?Wm*dPMK<;n)!-2i2R3sV56y##)9R-pY zy$9r`o4^6*8BHZ;;&u0n5Ba z;Na{69O(biUh6`qQdKw1TN$${8!!11SRX@Y;8zd&Vbl@V+aEp9d^Eiiw^sIJ;oI28 ze2pm-JO$77qaITDSq4w8 z@<`(!)6>(xeu%U17^V+Xo_l?_r5p1G_@4PUNbA3Cf{;m|(`8pWPO{_1KdFZUF$*(( zn922{!i3hyw&5^+v$wJnRWyJ;E$-yTbZl%)AX{bmga!})mq30Ud{*BM(+w&-JeABH z4bA|*DTSk(0I`ksZ%5qN<-y8T(W-+USxHdL=?Mt5^$-%m-x|mt4$}1-{NbiVH@;g# zQyaepF*>TxreCeBCI9LRk04PBa86kJ1Op7P%<~eM^@f~l&Ek;9>*2*!=_P60Vz|%{ zdMN(=vD=-t`k&D6P&A4RKa02tV@xIFDgObtFIXGJcW-CO>+zz36DrN_Sq}rK@FKeOq|Ku?7Q$kFGnB7J+n=~@5B>=!|nQ>_cgKHJ4t_Q@hoCMmGul8kT z^-@wO0c8Ngp{o<`0+EMNgaB?ym_CHEs&=lDv|_x4D7o4SPFM)j$H|0z1D3_k%ojlP z_N7ug+Zw*iSsA){0B$^?tOJQSv?ogj>$wUqL8?BbaYH;@N=N z`uoR`aRHn{I5;@-=X;o>BqCZ2k8%KiHLdo|DnzDXA3Rsw{TmeCfW8!FWnK1_p6ML*jHI_am%z;IeHhJ0%h!kKJ#G zdUX}i#KZm0P~zm2IE81KzP>&oC`+h1AzEHO=plkL^Wo7Zb5ta3Lbl8}461umy0=(G zYITtz>0~wVQu~Wp?*VV7h&t4CYAvKx$h%c1tM{5xI?8X6D6qeu1{;r5-8MQbOtj6t zf`Kxw_uR64d~-BS9wt6lXcQme_`yj&sG8#7wU%s6R{X_dMAs#AItD^u6R1yLLTcol z*}rJQBMU;DE1IAa{Xe5f(Hw*VmGNNune6D@LEIf}FrUKEe{Hh50!9B)>dQ<^lbe>z z(1~3mhqUhAKA6mhFyluKObiT&(?v>@G8L$y{Hxs^25_iEqPMz-7l+tMME`{|XW{n` zC*Uxlc69&9ylCt7ZHj7UHdFJrQ`O4ms;`88ISK;8C9nGx_IK7dRt;_K{L)ec+{j?b z4ekgRC{xo-StX^u5EMdHNEhFdNegO45uYt8#rVxs0aupvMVzchvjys`;Dv$MoGyqw z`B3GG-@!qANp-dMfbhc(mST<%SCL{`MU3O~^}bCO1eZSCUv8Unez-(?bD%6z&WZ>L zd5<~QNSO+=DMl3};&wqMub{wgcJGi`U8z~MZ)ufroz8vEjah_7E9OSXgj4Kz*Xzis zs$VqP0mWTreE919m3rDgeY%)!iYQiX8*5Tk*B@!l!|TPR_M`B|W46o93nwS%7H9Zb zPfrgUgB_D}l#<%-`&zlu5?&+8n6r~TVPtOWH@2g4L~<=AgILaJak*}iOeO|Z#FGu|>Pe$=>FWlTOWSWju@L;}zn&WQ|VG6W=O${3Wl%DsV z(tDPclM{wO+akB52A)27T^P&_Gl@O%Hx&Z^W*r<#vFL=_NN;zJgnX_v+2V8_ zHHOqQcm4cCu}N2=fiiEh@O(veM#nRy(?{e!bGDj^0{6j4cs1Tnz~_rlk**kGcX=`p zftUA&Q?klkJD3ja1k?}#Rs^l|6V`fy?Wkx~$V}Z~nyZ(S$X;#^r?KCludb2e;@OiW zj|=4uKq2qc)F?IiaWkBR1u54c;usERD}0#!jk({0_L)#cyzbeirm9pa9;T+Y<&jBb zDO{K(X{pEpZY(Rg36*_Z(7ASZ;VJQM$kN$aGr!jk(U(+KNbc5}F^5NtfR0Ty<}EO{ zm%mj;K)`fQ^c2B#$CR=o>#v5~!cr($-*x%AJ1$eI@SE{${+OVdQYuk2Nm~~jWnzJ- z!4frI-?=jiQaRK!r~S1cu1@3q`225({{FONLK*MI4dfx`Ef?)isRBvWX?@$NHaeKNT%g zSP=dzm(pYaj~p8#rqc_r@g0Y;)?M~1Z&fP$@?k0o5mD5#eY#!#Sb3r?Tw zQJISMF(ZuCEtu^2 z(k_A<3q9(oy?xQrlAmFK-W>|7lJ`+ea3O5|UP&4YacAghlnX3P7G#I&qd+x&dwfM% zmA|e=+$agx(x%Q3f677*W=^kWYnmXv^4Gb z<44n^#2&s*-Y5zog2?9PbLkx6bfU?{#jGdGnCf+4?U&rOlSmH^`+b!r4C1_gk3N{7B9oO zOlrjx;I*(?lU69An16~(kpJzBdP;+x$hK;|-opE4ds~wrE1W$l05sKFS;`jVF z${bMS4r!S1JWHz+&5tKuud~|5E?SfI!n|0 z3)$TY5;>Y8930@hGf-#WhyWBBe7gU&Ur?FVn=|lrn-=AS7Q$tn)7B*Xxe@WE>|#08 zE--`wemGLv5X-#}aH?_Eu-S< z(zM|~Aduh?+$E6U?k>SSxVyW%yCosGLvVL33U_yx!rk4zqI$k|KT;;r+^v%l~blQ=s;;AH+0;!(5n zk)Yif!;;gi)|88)qp{N@n+IWu#0X2REc?fvB5PVT@R-b9G8HPa^7sQsYdp zr>Z+g@Lmje-y)pbNu2rg{`mRtXqE-bf7Fouu!ThRcc@ z1@FTllcABj4!}J}DL#+u64V$rwt6B`14?xbEBY}@XEQT1 z%4NT|I-qc>uRkjQ+8i16KUP5Z2jwbzjVE~k00Omw4YA@t7+Nd}21eesbn-8W=mS4? z`_0hg`RKHnc{eZ#j10*`LDX@X&J_C*3ZmOA`KU~XyJ)tSCBZIo4#jVx8Lb4w zoG%#U18v}8qzX6jq$iSHX-JQ6I3|bbv7N9hv6?SG*OhpDNNGZ?QKY4z-&pB=f#EPS z#&V2>pDQ5?U2Vc1Ej?JMm*7>4pqRZa3vg>!biLmuqa6CNvW7DzVoH*({gmuc2+>~g(Xyj+w9I9- ze34OFCo%-X*gzq5JWX8d)49uz-rZp9-XZVIAIJjdkG3Ou8xSA zkxBMBESb*(j95fo6(mlj$FPlDnj>yi8359*(+NEAIbKm@4sb^^n zntUP&c`Wf;+nA*PZ&2V#KzDV;3otSxG1;hUDuK}oVP*r&%yT`9$L3q!#=Facbx&}% zIWt<7BhN(BntY2^8A(DqvlTwFSn`oo#E)#I!sxqL>WzGb(l5u4PNH;e7o#H~YWeMT zy?HNWo-xugz1bP1LibHds;vy8Zheaq6H9kRQlkd%45*Elny|{rC_t?`Er)J%m1)r- z=`ZiAhSjZ>bFc-Y=uHgQE9-SS>oC*1iqdkAQA`JQBeN6y77ln~#IXxM4%XB2P%gn5 ze9qlUNYITug#9vCvI0R@>F37xOh}zK3@ngD$dtJNit*R=t2I=Va z@fb0N1SCps7Te^6dY{&_QdiB%eG73JW)Bfp5uOVMbDS*WO?z#9Wtys#)j<7{%*g4FJ^~FPxMi|{|lMa zNr`oOV_)5$44_{$lz%_~${}*rh0P(@-$sTlE9D%*|tzcZlB_nEZs$b za28ty_Zd3;WcTp=^x*Yja(KIvC`S){p)a{1FE5X+TRb_7KeOb`mUMLRyRXD75MnX2 z?=94Rjbv*GQRj^(Zi?eXUgB?W+@TX>JBI71X@^M^^QJ*0fvdHjmQz0ahFAZ9t4CKZ zO^^PNIAMSK$itys?65ORaE6?#NT3wAIb!4&wYUlYb(6c|jwZCb3i6r^xMdQa+6EA_9jDVjP>tI`3rTT$KP?56;Xi9f^mXIO z%DWrz6j2uInwdIL4P)^kRGY{;EY8k+i^2N;5;Hyk@%&CIZ-O@rK86*bKM>xNu4U=!+7QA;4zjQYN=s&HeEsg> zAu8{V#!!X&)+UR~=^|d{`j1HtV`zyIib6U}2Ep!HPSbJL*_Rmmv-9;fIx!+!{mfd9 zz6RvI%KIsYg%w&ld}{v|#%xJtR#l;jM&k)MFmdGs#3Rsu=V+VNITk!?U;d3eA4URbh4J^CFCwOEFA-tTvb0mo%YKaH;HwOPCwO_xG+(D+a0jRyi`AT%Qg(0L&>o~$yLF&0c>u1{<<9dY zO1!oOEbT#~?FK-t$RR8b0Q`HV)3M7q)yi3=I^ayCqN1bqed*_wGYmw$&-TWISUybK zOYuQsy`=u*Du%?4T+)17p?VMdH?AjCCXP@tPbN#eDe1v$W17K8D!_g6ntH&RebsfNBLR( zd+mjyh|~U;QlT{G1(xq<_sg{7Zn{h8Vxg{>Mw|dI-Tfmm?5x4+GiF{d3-ls9J4gcu zh6AoyVs(z{15kg_AI%FdDlFFaEy~F!LIQd#OVdmHuA4IO5u+>8{)$j3gNMp1w$-j5 z<&XaAh0ntVl5kdS)#Jr@l{sgeR_&+NeC39#WNIMUcW5C6$WL-VPqo(+P2m7mUveG& zTAym_b2I90F6sbVG&D4TbuU~~x~xwC{<)u^magB1#E8-OHg?p#@g?0qzb=}x4)dP8 za4?x{51D?AH|&qkUELVHO}$7pc}h3>y7QR6DgRU@8EhPRj72a_-0`(3azJ=$5W76}it zUM}4r=cRn;IQWJvDl3Z_xX0hwL-Vso8}yyJRDae6^lbI1-T89Lk5Rr!!tL^muXjiN znZQR5S#6Q?W}SyI7~~NfY!6>tIG%G`5IPYhK-Kxeb{pUkr>gB=igx08V~pojrL#Eo z9BYwTJNN4&;!~RZuQG+pjd8vwCP(kB@`~n6X`AI%Nzh=>9%U|S4zAF|oXJKsbcsv< zlw`MVrGWTwNCZl)iuWCw3vSn%yyt<7@GtG2L!xI8o8|4}EUz*a7E$!&$vy0;gqa-w z(FA6Fe)n2l#(O+EaP8(#Mj=^HQUHzXsu$0lKMjp3=CTV=AkeC0+?e6fFcx!m|8U}J zsmBpcUFBrlz{~Y~+=uqVx}V)|60cCiX z=$>@B2)s{&1+|M=-}_Z&(mZ@p^Xhfh6Pq z*GrNVIV@1Gu8(l~{N1;(fi&8DRv`c@*bveMONXl~-X*6Ujnf?s4`lJPty8C5U50cPNHjdi`D@EB5$Rfz59_HJ!faT zvabh-I9!@CZQG*7)yQ#?phnDK6dKF>^2H#6jCAgx)(w~|ghLEHtMMFe(&!bR`z;Xf z#=yAGEed2eEYkIIeRG3SBje?{W>$lQ!=>aXsjl3!^R=c<`qj5Lxs}-@6VG$`^4}|Q zC$2W&G9DOP@99=2cw@XbpgUWss?EpnM-|t#=2|PsOp#hn*;}>AC1$G$+HRuXT_L!- z*Qx9|*xme8$(~%-*OokxIo$oik-5jkm=E;JN5X510n%l>mDQgsc$h((R>eWIi28UT zl7F^;6PbN^H&Hg!I=(^oD`MixJlLI~3~#wsS0t9bAwdu+d0!Ip$#nI7q%s!=2_SJ` z^iXMFfCcsS5&ie8K?-tU3N$7eV!Jy=+;Z9h$9_8`ASEq}8AUf$-Gk5NOkIFslspa| z@hXK2|L)GRN-TitufhOcu?TB(7zKPDl|2u*Py$Z9d3kv}yYR%QibrI85QIdBlGslV z$6q3Q-J@EGwRjC10WB?goXEodFPB$WrPIe%I)h?s1+a~))hu+&*2}fHb^i1`EG%Tv z>j2oi;}FrB@$~DXIcwUm-?3*3q|P>139Qtm4KK3KA8gnXix0SB#c{bMye#{BnH%D4 zT(5NNmA>#x-qYX#Zjp~qM(T3~gy-5Igos1NxSo;K;TCjcZ>(+~fjq%&-Flbl+ySw@ zIz81vnzM673gW8(ICcLmy;GWc#Bq7%ayVJs9IvW!zi#pos16m9%olRFY)AGeb$yw zI)FYK8lhijHC5(`!J7icX1AvyW=eLD$eFc?{DEC zos=Xq%XOX!1^K<1U5X|L=jH50WT9;*i1zC^2ID4pnpq`-(5jwZHk1?ZOt+y?Pj+XGi7Y|?n@cv-bz});^{Rm@G8j_42 z$uGObB%OIlYH)YsN-a^lBO)a<#;3h&H?Q3@(OU1oIa~P2U&*=ZVe`wO7mphVkzQtFa*T3u80r_m9TE+w`YogI zB%K5P)c`9~`0?o5+O2xsm}h9LI$8{WHLg~A-YrkU**!iE&Y|y4v6m#o!AqrJaryCA z@dU55)k?3C0xzl9?ao;Y89{iT*B4jsc)eeccr_G%J$nFeu-&{Tf@FQ}T`J8c$qNLY zdn(Kf*y?PW5u06(x}0XM{06tCoM)%mI@TRW#mjfDZXa!%_QM~Rt=Wzno}}lRaz$l3 zK7sGUh>~e=&**2!0DiK?Dg3gsNKH+g5m8d%aF6_y*BN}^Gyc+Zg++k+v;kZ`QXoitM;|T^o|Q1cc@i7XdGHK zRb;A#ls!zl$M<)ci0SD7)72X2BiyF(6~i|N`)xeHQ_0)ooEJ@}wa!n?722r6pioI2 zC!VHBQd~T4fOa(RgZRI?Sd~=YN%{N5~HHAgG|ynK35M)uZK~zMummFe;gWJ3Q0;rmPuvzQ>D&3!^XxJk{GbCv~0`6e*nAw z$}AHY{dJQk0|=SPRkm(ly|jp;6N z@<{}&4oQl4HC_<8KWPwr$Mm;C$`~#Y#FCF&9Dt=>Opmb?XOBiBGpQv7Ip09nH5Q}lfgYH@TG=?=!L`F2VQXswo+k`<9~F)t+6XrkkxphN3JMNZuUXe5 zK1^P`HHIrqGO;tqn*3R(giEj6dA&>k&*$)_^TJTAU#o5=W&NfY?NhYw2?|Q8DDsg9 z%FdLilI3DB00}_2s18RF+l-4VBI09BEO>A!QRj)Ckj5FK3nFmEFN#ujJZ``)N5WU@ zMlhcI>qeCsLF&0>sp-&>u7CO*asgmF?ygjciE|Q9(!2d&HWh7H^~fQoravz?`X#PU z3kg${c7k0fq#djff7QmeWU|cn-Bzs3&W`O{XL^SnxVt>(kQ4oZGpk}`;e=1SYTS>f zoykJ(TSU)dWZ68jmEnm1bun_0P}(gW*C!$yhwGG6uU*v%Z#y zdybH2rovR)@fz1=kheMI1m()q8{pqU8^C{6e8u>|Q27;Is7ga6C#O_6>>!L$IQ54M z-BX3=_}SCx6Zv(c6`b2Ma7MKX3bb!P2peg=2VBwf$k9gePEzEsolqav)_?*s++at2 zjy2rR&y6O9Zl^-H&W3>x4{p#irEG^kJst3;pH2XTJfE~UApy|PURm)-&;2K$EUloK zuPz&FqC4&(gkF!Mc9$!?b_v$|tqt>qgAdhhrDhwMD3#sHvE;*6YDRhh*w8d^T{Ksz z3%Bphj^peH@nGT%4*q|O#TG~E?hp7t{#^&&7Tg%u-1 zk@6za5AN;7?`_(D#c+RzbPd<P(?u2P!QHeFM@$Wq2|g0T>GQiQX33#(_*9<@7Mqrg)%0EgyJ zu%f?xRdfiFh*xEx%C{ej#+bEJuFg^C5(x!rNQDNCNhXS}T@a)$2Vt>0n&L6va1e z_D#L%$Y#7TJw9ric>)HuxB9dhc9S7UH**aXeI}!em}FD%A{9G2p`|x#D|=Y+H}Sd6 zZhfGn9t^rp`gZ5m%7_rYb~(;#xmX@dDQ4>kp0BZ?$9)F`hW#w?!L`2c_E=}zi9PlC zgEXj8LR^ttPFa-eji&R^r<~VeI@_(9o0+96{&tUZe}24k%iv;-r~rVY)rl_L^ds2# z5zGyO|LT5TVSa`3`^d|*@g`Q@-;2EQH;(r9AC8WWT(^@<#ugWglcKhNz4Z-bGC6mP z;&^_J(3xPJ9&*f*6Z0U*$yec8=rV0fmCkyZqT1zhQ}w8GxM)o|J)a`d_5m2~y0)G` zx)Zv6WFoO=3kFZllO`gBf5$PIh5|n;u8RUD0(79L$v;7$HaNp3ZW@i#)GxtDG-{?5 z;8EVK_&Oe!)?{!AIa>SRR-4EfkCSwx zUnC>2@Z!BgO@U)&Gm8WrDy^=V*-0P4S-z`d3m<@7;pN`vv!^_7W7kifWx0J;eR{Qy zf|>v+XJ;>WSOlDGkt^$OxTVwPS^;S33X@|CD{26Q1auFKav*EeH4nm_0v^rW%NbwK z<`_|4US}dW8=|rhm&Uqtv|?TWe$-_#ERu*!|0NHyGY|K;x0!7zxIl^nJpTD-L=n$cHwc`OQ1;Vtv}hQ~iyugWimT#)Edt3ECn9H@$z!aLjdCaMguV;T1jMADq``ND1!e zjte^7(G?!hcWoU4X-l{V*xD}g<{`$VG zUm5C)SH*0RTycDC4L+2vhwyp6GcYhnmT&WU-ifI+=)GzH_jq8rx%!PoO<8{h9uGgB z)umfc#de*l9FJNjD=lqy_wevA`>?L}BCabA1s`7UY0HHCZ%(lmYUsSP6YG~4K*qae z2y<%i_hU@dor2w}JGt#|KHrD>_^u&8;tk0zZ*4NZMz;^6K6|65P62N;az9VYN!VQ6XL+_!37KDhe%^J6li8)5-niZ5 zb6lqaI^kYYb#BKwFDaCMByzuYdmP^wRlz_?(NtkY$yTw5O`qGQSzTS5w3t%FN?7e6 zm0b-QZ7uGapPW#)G~mr8T(nt$=bp6bn~S0I+(&V3y|p`}B6y3dUT;0a8yvV`ZhrgO zJ3pSimGO+Eo+9IkqGjPUrJ+!AYDv8!yRcZ4clty4Mx4zvlSI|AxmomDZh}o`^U3GN z60QT>%!KsOao^}N&d8g%=A==Y;qde3jirxq4Cdz4DX`-^Ts<->ZWgH{xlcpXrYBS> za&yOM%5>R#oi=_dvU+ye)%k1LWxaNP!OdX9H7HEN*x2JB@MOC{hnI5*_ogV}lpD-l@TwfGA3_C|_lNLfCLXtV0t<1c1VAu=0#qR)^|7mc}?<}ojq zDBKawLhmHv3AjkAC>Gb@DAXJju#${=mb!Xg|S?&YmsHp`^ftFidzNk~-XQY8D z3~9o)NgWQ~XKbO2@FPisnj7XGG$W1%fj>B`K|%gTO9XiMHNh9?BauBpk-b3$4mjff z&UyXAQm}~e4-4M3BY7j!CcxD%Uz0D{^&YtnYOIuSq!k~}OuLIo!fIL*zEq zTQpawVPw|>)Gm9D5)q5F7MLrK#&M$&X8sfnyTq} zTI{8P$4#Z`fO*SzvpPVneeY`as(Ns5UFo?Rvq_xa!?Zuz;)pXx@!U9SX=)R&*JRv>litel&cqSR+?UHjQam3uY+GR zTeC!{ER5Yf=LZZ05=bg=AC8xUXn(|ruET&j+0Q#JYP&aC!Y^Ea_%0_`1_gZKWzK7T zOfZ=}ZnWH%81#>Gn+5%Wh0f$-kwO$g*W&+P3pca--*OI`y|N_|Gq^z=JBAy6Bhn1ff-^)75Oy9fH=pho_jW<> zXde2jI7*$FVio?jFBojsuWh$vweY`;V`QOGZUwgpDl2|yadTGY!G(?{^uDe)8mA)M z(kR?y+4n1~qWLEIq}ZrMGwf-0rgn6*TqN*J$^%|CFk3ShFq%l$6H&zruq{Mzb0tq6nw-4n0#&b zcd?|<<3s1nQMs>{@5h^{?6tzrkmAFXRNOox8Ju|81?HH|aXZQA|I5p7T67IO zpVfcb+;7=BWOA=7#{05lMhs2rbc&4#12Nm+!dX@1cX}*O+U$|A#ViI&P7DbHu266M z!McTMdt~Tr4wGYm}je5*0l#UTi^CJJ}z5Oh{^XHu$+#dUdoJBv}bQIRFf&ypr zZGOcEgaE@-JV|A!(td2Kt&F)wuqP@U@Y^{&ok3QFz2;UL12(*5>0zX;V;d zdqN}$<0%?=u|I8;8>GI?!W4)T|1;P1X9Dc*J@?I01bvd!pbotx_};3uuMea)Bp3lq zLj7|;3S=^oI!6m-uKA|5i!0kQI2d=uhS_LRz2?6FQ!_hw9 zN|w3ul>G7E`d=>UrXk;gFrVLr=x~G^GB(P%4_Sjx*JBK6JO5@U{y+!)^^6F>>Yl3?+OuifL-3%?MBSTT;)dhlgIU;06mtl$+*i?F z-TKATwE!f2XV$#jN_86gl;PcjgUPN9373_H1n^R^w&_=z3f`&c@C4V@u^ukg z%f=Ty5_#Wtnh0xpLsYLLqmF-;B99F&@i>XvZSaOsD8fUj&?sR|ELC=NbTMeTfq&&p zIb(1Uy!rAlh$?^+y?$3Z7pe|nK1NrW1vYj3aM zfbIh}=MiHq2(RT(dD6Ic&yQ|aNmAr25O+x4wr>Ig0&E+XNWRJHnwv{Z5OlV+y=gs* zve7?T0kGSF8p!1cad2i*XL3kLUe01N0#Iu;sFmRn5Z1v(GbEmbaZds$X``kOIpbJ8 zy%fv>EvR*?V1z|t?6T3gliumldZAUSJ*`qa9954Cv^`VV~o~K^y&WBjmEq3MXQ9xpni`WM6Gz69qhfl(zUm_e6nb|JD#b0*fE};cp zf=e@st~*?-UqB92_YV&unXNEdT4{38d*;9aOxVbr#zyhLz0Tx5FEG?IH9fT`JGxnN zVAHR}YFXhli$J)#x=POEP8l|(-RI%qA^CnXGr&(t+;PF|X?1k!;!I5HMD?RdByguJ zjrVtMni^)9EFR@f2Sg>`jm*|4bx-B=`gZ~CRgUiWS5=OUWycrW^J-U?AKATc=U3xJ z%008s`};(B=!Y@l%>fI}r44tWt18;sUzD|+QG1jdk&E~D3h_PM7o{r4ii?y5tTP`j zj+nO9OgRnGL7e!L5ug8WnBreF3=A#_yl;uw@erkCVdPa*LQXt)xa4T}bzbf_U_&}x z*Zf=z937>EHz_igCYH5<-%^CQaZo5O;h#^DUXYEe#Rr*~m~wLEv)%G1b2;)})?i?| z@V#Jdybd(R=NknEB13VT&;bAwmUVX`K5#W8ILl9$G3g8pVwqL0y&kUn ztCY}kUrs|t*E)jW2FIP^1t1UNeeKtb|DR6nfBJx*5ou;1X!W*-t)}$PB3cM8 zoC?VClWM&xwYsC|sB?|g!n@+-EGrmDgT%D7>8>qB#mU5^_v>wb`L*`<_xB>FyrsDj z-TGh_F<{|-B&~Vv;;zQ&38-p`ptM zRSik1iQc>C{>Gc=7p@eJ?f)Iti;Iif#lRExaN+|)tKAZMd`xR61{Baxd8o5$2DikK z2GyibcOAYKA$thKOm2P-6TIZ*w`w$kUt8$7us;&!f=mvWpu zaoDZ*QkA`cVlw{aQZ^>u3U~uJneN(n`}Qq6xQ_LgqC0Iu=h#?xl_TN(SV)D*s5STV z?S?wf{Rof8bzhO%VE)pAj{6=mcotJoUS3Nk57y8u@Mzd2+iTHzNFrI7IsC`0PG?se zw5CgMik<`K*?r6l8V5?-L6%3OP3@;CU0$BwCEZEf( zL^D2!{r_6KNGHTrblK9Pj@K2|!oos@%_^^2(Rsk_I#NbExZqUyJHZ6h-ax5V zP`buy;K7L-739vS!S1HGS28SN z<(eSLmJL7Ee7|A>2@!d7LrRQzL}{q-rAwrR0B%@UIB++1VnvfSVy&-&+*3AxQqJG4 zcsMV2$A_#U9d?YtiwEE8I_}l?#|y5-%dW%t+#$~W5H_?#=6jr7?Z8Y|mk<~d`d>(s zZrxm_C#FN=uTZ5vArvCCbeLHjKa2fTmN0%RhO%e8tZgOZ^!PDgSEj)`R!7b~Lq7C%wy5Yb0(Z|G*kUEY%Ig;$U)TV6ZZj z^Hil8yQKL81dEk}sA$M`W^Vc^1)4ZGTa6f1x!1x@01&D~$6LGeE2)Ha`ttVn7W6?4 zrtkn)y+(UPDt7oMVts1joB8a>F zW>)_ZugX$@@_qfBH-ncFB&!Y*XR_8ptEMSz09sbj-i+e!;d+ro_F4K^i^r9^beSIL z>nn9Gli@NMN2jSBkA$>#xfgnNa$`T3lz#9d64S*;Q!U(yy&AR(eU~qSoUZwCS=MWx zjV0s~41&G6pDtf0{I9E3ZcnB~SZoUnlfleZy;d`n@zmDV^pYcHoN2Q*ryZ#*p*uz&%=Af70NrGECl(sTyhXA zcG6D~o#s%S23?bRAFn^nDVJ~VIUhcZ<)60t+!=W`f5rG3`&YF0_mwtvB3%rVelQGa zryEhvW=lf@ok5MHa*!(W>!@>=YSyz3)J(D3O%%cJNxc&a5OUp!Vxx4iO98vWHjwB} z9)cXLXkuF1nwahi+s|pLiuP3i0`HMyltIl2_s@hYi7I!RTvfExRvBiNhw~%aqp=y# zy10~VG;!^Kk|W}aa}CQ7pogkSu`VeIyW^BBsNYC#<~G<~ZAQplq?`&6KMiEokeD4_ z(63@Wwkm#sZ#t)G*&b2bfGvl&;Z}K$)QfsGuNAHDEt~g-D>$^kolnFl&`kFZ+q)gg z&1kpwHTunKEy^~)v37dg_v^I@86w=^lh8OABG5CT`GXmo2)bveoSdB7=bMa=6zAeC zM^+ErC_K@z6td<4&$Dbs*XdBom=IfS!+$f;#mT<*qziRcxW`QgwBTBEngvHH$`Qk| zYs!Kas^*)+p6jEonws^U zXK*K1;eTuVEaH6!w>o%kmU5(TG!MjoPwus8CpoJp84O`MpR7ccYSe#2&n@;;j(|2d z-@~`sfr2`~0qE206D_h6^CQ z3r_bY&?qgI&sA^LwY!z4aB^=Mw&ju_0ZGpCSFYw_Gju<0JI%5aN~URY4WCZ2TS^b$q_Xi9aMEiYfmx8@ zN3GAl2*vaBhFCDWjtJ^;xttH%_9pWq_8Jw$*UY#bK%}>GGzbgP(p)xiTa$5N4d5KW zKRV*qWWcu8l$-uR>0t-;16jtnj?1Z!Kl?x87=0DJl9GqcJ(?%UcGy~o`;|}>C&05~ zX+h^BgN+!3@*!lc^deh3-Df|mu~9AE!dcJMR4fMc6ADATEx75c39+n<2SIBeWX&dR z1~8F^m8EnzPAgJ%1|4mGp}x&z$~%7p7FtMbi`sT7jDIOtCq$Xq>4vBlbbRDnT80pH zb?5GoMW!D%1@fQ)Ma&zzKYQw@$I5JrU|vvcYNIx=!X_SFnOYW(vaxans4`di-^5H0 z86vDMDl=Vws)^b;M9pM?`wudY`X_%Gy{7wD<97Q7Zn6By-BxS1eGSgF^Lu&@#?PNd z@C#H`cG{a)pQ=sG%+Ot~sP!uov65H9D=Qh6JTHcm<(3ah0|vLcE-y)NyEnlPl1c&$ zkI}maJHVS2FTu}|bh1>d=Z0-N$>dpIRRZF)3eqc_HYTP|5)mV{Q=W!Z_svhESh z=E`17IxgiWrWE}2`&68WzUUTue1zp&wR!gllEu2tc^vIpChxmn?VbyeGMLw zkhjFfT++xfYlz{ST=Wi)hP&ys(m}bH9*l_r#@!63CsV=@e;rQgZvBnO#Yx`9aN~ z_>~CA8EWc?!hTbkJqK6~<4bI~nQQ7e;2VX!`khzd-hzFcpnK+SeZFNwj!}78tbEy| zQr{9q^e&$ZEtLQCl@2MuBsxI^oL>K!X}Q=Supv*1P!`*^PnyY>tnNi)5CQ&{85W37 z)T3JxNaYHQ>c^mN6k(EaXgm44D8*W+9!R5XM)QUe)?6@qUJ~| zNu%Vty_!#5>uc1fQjAm!+9_5Ttq#2CQaw~M$!5zNBUICj`_6Kovr{G61T$>b;2pVr zsH)qA&Sx@v3$XH=qf3(FDsxbz*;8+dG-%-*ogefu(dxJBZXMVm5bXK8xRnS&!XQ0U z96CR69&$8GL6XTuwE3qmP7MsXzCJ6}FOcRR;%(VW8k4AQGJpI)DJ{~l1{et_xpNaF zZf4nh9gz2NEjH6E3gRd71tUc>v#E%j;Nak7v*IliyniFoU{P;dAkEB+Q}%a6pK=%w z)-MwYV4RT?yy)q9gb%p7YRYj43vp*PV;+MY`31F``)zE%>~sgZX@9=pp8k7V_WQ(r zxsz!amM)aAxOXztE!1$_&rSO0Nn=uWUh^u{pdoFXdcUI&Q23ZO??qreX09Lu`7Pt7)@$-fzrELZebKz*Y%MW}Q8 zY?;$)s6EB()hr>WrhM6jTM74jR{i2Olk0j?fkoKYp{KQ0aQh__+SSnGZEk^R?>sys z2x)NDb^D7L-{nTKr?w)Pp3Zg}yK<$93o|g;q5SB|9YHVNvJS)$ zdMk!qq!JlVm3TO8YG&cvawcGD{=wJ=*VFomJ7I&K*EcEftu!N5nIzx#{6~L-C)nYc z-GuqDrh8@AgM%6eahrqO5j38()|y6jdAb|x`oT9!BOpWOz@$BfA@addTplnwbJj^n zjio(Gtr0t8BHckLR!Y^BYz;Pc-9MiV*7lZZ9W>6N0_P-@np%`5C=&ZXCYA>Lh#G&UyxUgV6Fw3yu8d%D6Jk~F*+WDJCByrdRvXXmCVwFhAQ?7!kc2GHcmm}^?qB*8@m z0{kzHKyuDb8L$?V&_If6b5w027AA=Bao*-gZrhk!Q#SoB#uO*MtL*wWzVkmIS&Q8@ zLcyq~K-fr}KrjK=d9PTHqInWI!R;bwVE z83`(i#mfNH)wX*gG8?sLm1xobi+ImMuMYpGfY_ruVfPh0*KKD4=NMW$j)_a zt`TA6j8`hqu>Mn6@Dtq}yq&w^3#@!<+TP0d|BIcs_1e8G)sZkGW^F_)cic zd>YDTkld9@U$3rxwGyE*YZ6vP6V@0d*V&OZVT4C$1>`ot9MPt`%I&X8<$1KY=91tr zifQD(tQdoF_v&s67~y=g28xQEb&wWPv=(@eQd84}vwI4SFC4RShE;0uVm%XnMUSd+ z@UjHnD>=|nPmq<=UW}dcC=Yz0*1Ug&%Ty?4`qNS64i3k0}YzT*eFYN|ad5^=)`eI<+_JoZDDO^f1V$``=sI@nb71v(+1f}y3np%@F22iUjkvlV>ZV3-aqN#@%iqk`AVzrz%?)xBDHX!Z{q#X|LIh z%Pa1d@tqZ(Q%zeUcSUJ(^}uPkUN+BjEVdoQ5IQmWr7OF-<9ChDC&zlnPPL=b%Km_O zY4q&NnufE8epxVr3ccg3>#%TCq^nzFRH5Xe^hzu(;L-`;l-aUMX2R;5i5&SL-{hU% z6{R*zD~)VXp2w9y_1il7vld=hcN8CLR6<(HNHA?p=)s-7Ke%pk3r+rhtWR~?V*JoF zg;YYed&-Sautl){;9w4N^n>cmR@afb7Si2;L0!oUVuRfxNn)=G(fbB=t zffJ6TuESJ^Z;}Ngxm6Cc&@q5>BCQn$ZL6J5<`*?(FK$%PC9JyXH1D-l7Te zb*y?qxt{^HK%L4Yhyk27gum@DII(ce3&{s|XXHjcv2{fj>N*1o9!hy_R90wD^EGJf zrzFfTtyj>sOIZV+G|*g(>umRN9L%R8`;hI?n^VUSV2hjs5Bs=ARBwJ z{%t5*Hww98@u&h*cvmI_O$$V@v^4eYFpUwgdvZc&jjQtOqRE}WEZ!t`e{WOz!MbC& z?=!i`<-yHErCva&A>1fUoMo}B_BP|I>sG~;E9X0w84ZQAZG^Se+u~Ta`i$XU0h_48 zs9NH##V^s7FNs8MSI!##O)(LVGp0b`(fr0**h5mF!3JH$^@cqU0rJw)9(AKLwwrwJ zX>n{N(MHF7JG((!H2eXh*u8LbJ&Jn`Qmuuicez z3Xywg5hZ;tml$vJ%;1u*aMNnFjUli^#^&_Qf|h|O+5wOxc;6jZ6`B%~@P|Q(tLn(L z8sk$$y{_4hSP7ifHMJ~0HX1nb`enCMZy*-{Uyr$#7uTsg(Kq$cuy7DecOvqS+?n0Z z{T=h|mlOQHx;HEtv=oh~RU-}4yvx6Igv~i`wjpi2xFIyclMS zp!c$toFXk{NV<=t`~TSc%HX(`B~1%0W@bwkGc#GtOf6<+W@fUOnJi{zwpbQ3GlRvn z?fYh8-kW`QH+Ft+L`!kHJ5KefN~p@rFEhOk>e5heM^977&%{FSX@176Zhl~Il}=4a z3_<;u*86Xf2z4p&dtl{KNaQ#**ip)RU}aQR8F~{_Q~T$}*%tjn`1DWO;nVC^N7H;m zH^7sqqitsYo{x8HV6FM8QhzE&X)U~OX`FT<+{vcQfu+4V!jkDul}k=%#ANw*X7_u#nW@s~@aWA> zxVR6U7~LyJyQ&A#*}k|?d_^hRRJiss4c7F@)O+cf~G*=g6+ zA8KDrBvHquX@3Vwr{k07RB?dbCUnY@138_&;Iend^oA7{B#~8Us95Bi%6SH=ktzaj z&~Rdy=H@6pbG;!}*6+Lm%Ieofw-Y@K{bv|_f=b1Ddp=OklDTCS3uE^e3!89`hn+3? zK^mAHNq$bhFjwjmn3A#)t?L;%;jZXl5YjR$p!y7(QPE;!^p8`()?3IX^wYa$?In{= zzU9(7ePA2BcKD{~gSj6#9`uEsOjqAeLcPlHO-q8>*hMhahDmE!-QUoQbxNbX8oTHV zz#dzRINu3B0FpBBXh1{VioHj-h4)c7hybTUy)A||`U)3vY+UwtQuvGt<4A<3W;Xu^ z`9DYK{F6xJJ<@9&oNJ8!@R<4?xQU60syD8h7+81g$J?&!u9EHPLb~DQMr@$mnx7E; z8(PU^=CI+WkB2i$Lgjzs#{YWjZ~RrS3e5^oT}zk{wNKLT z226zae9!+4L$Rhs1VVli0lLG|hyHCG0t3|5+ndpx0*j_fHwhhCgniTsbipckMis}9 zEpqm5&_Ca8>VSqLZ>&q&2`vw2VXl6b*yDHO{(6D7b4>>5Ad_lYESs8y14lCgB29j| zwyfaU8rN4cRzuM**F|%AC!L=;2}r}y}t2N$)--DHQ_Ki(axa# z5K!km0Ae}L?M8(b>rJPs`WC9I$h==Zo}C+B2nKyyi)c4%+St~7Ho;ontOHX~^q-Z= z%Yi`RzqO{d*!;tIG?k~&=Wj*I=V3~upgEFKwFdm0om+0JxUUm1eFG9(O4J~`TTVB; z#wOA=+q&dWJ{oS3Te<26P~S`H$(pNS}|0S@5h7FN%WjqP;q7r7e^R0N|~^b zAz=b+f7!D}998r>ucTf?RBCS7Ee%LCrPpxNE=IBl&&Ek|xgI;03@Rb!$lZ)1^OX%i zYC5aK8&_zRIA~PHsZasYDE4z}+N8tr1qayb31e8`vuu{{UBzlfOTo%+Fw3K7m{O!$vqhv zNHr|8K!YXEi32VvDlB1#GeY)9U1q54b&LHf<35M8l zJ1u5bDd*N`Va^rni5|_b)eO(ro-!KzfRQ}sX6J?RSQvS zTVL>D$OaA$PJk1Saa>MMkA@f;rtkMtf&=}(4E4u|_|KQtEjX|`NoNJ(Xpzh2#LM*3 zbnf8lAh;ngFbG6R32SgQ);ccA$~aXmB=KE4Q(C&Ysasp*6%>H6pLGaI6&NLyWro|^ zZ>yBKLZYaD0%_jda^hp|^uu#ZSUO3MK)IUx-SB8w?ZtpSxT~Vv2iplcdgn*?m;s-> zK)o5A&RS>^!oZ~A;8>Mrmvm9nDuu97s$S9bUDNjC8)9nqdjwsjT}$F42Vs18VHdzT zO*TS&Ie`#Ozp>m{C$(xV{k9e*DP{r94+B;k1{GPN++O}RwE{CzPK=I7Z#7^6Qv17g zz$~@w!_7!&6jsC(5f5|BVO4p>iW2<~lQk zmbCB8ul~n^#K@=kCmSp#B+;Riz2IXq^#*LWn?OpMdT?U!hvmXu@iofs=RN->8RmkEWefM2{tclVq6xL8sOGDXyr z$84W%aZcNI1qECFaTNT!mt~3{N;IMSKGcT8q2`v$zDSKuj;m~Frw+Xq2ZUl23JVCdPID)>t zRu{?_QXrPTOSXLUz@?W3pDIo2@EaEIM|vK%>La^NX!U5u1Xa3=P#2(_^x+IZx!~#5 z+TvoKsD>zn?1jUc15t7&(ma(qrM{65n@%4HYptDyMSwN*t?JzAO*A**Uq`QX? zTdd+SMvGVU3OT1EazR4x3|$pEG|j`h-$N7eib{Rm+OXRbHyN#Rv{s*Ykrf8WF0aKC z?g+}im>7D!;AK2r8g@ElKrAegzh$nSo2J0P)MBZ@_O#c}lDzyxNtJl?>F6eObrxed|D!o$H__V9ivev6wmT74s^v98Q` zbFx@!5eAQ7Y5$9NelZ0-`J#LyS*lT!zoM7h8BeicX!FQLC{W8k2et5gpBYYqb4CrlP>_GNOApw};xZ z*0Pl?D~D&qTp6i?3>SXgU0Yr@m13S_G$F$!7|P;o=-=$5`N&W!*jkhKJRBD03no?K zL6=V1b6JzV5q%wYj)vT|9}A)zje=k%zVB>MWKSvgrlWyCzqFRhYpUTX-^Ze_XiO1L zLQQd!h=1V5#B}O+U0%!F-*ndK$26cTpWO7K9J=gpHD(C;Cn*4iYVrJMbPLp~WEcJl z=26QEaKfzv;gc)MCMOzq+c^Y7<54_*1}!|G&1WK^+VsTX1s|dcZL)zNSJq=$mvKm+V^kXBP}QhhY;JUo;p@P*!Rn5@nwIsr=cjQ!m5TMsv#UE_KTV<#@V%F6W5-&e>p`)o7Yzq> z&lgsG?`4e(IsRp2&5pF4t=Z*2A^`u`IV#vez3N&wVmMx;Ku?4Gl!}L0Gn{j<%#=1& zPup|}`j#u6KDVDB-q;=X&1k(HLb%3r-09_jI+pkzW~fwSN|R|6-ly%hFnaL z2puA!WmXQvYZV(f5yw$DN~v*^k&`FM%EL-pZT$KbxB25ym$Oil=IJnv%H57jJuV;v znEmEA@(Zf^y_lY{k)^~j;j>Q8I}LBJolNb;+A}>j8KxiwAbzw}bJbbsluBeVd8Qcd zn^{6LSa!Z!wIrh|;ToM-68^q|=;wWEIs|r(?ex9(0>Z31jPy*qiW(E%j3}I-BZ9eB zOJ%b%At_T#0C(H;LL-FiTPBU=)%>P7xj~U=OU70e3@(_Mm9pK zqBW;~(dI%`3_E$&_j#v%OYwAkYWm={s>eu)$hlaGd zS2-tu*~H3a6d7@@<|Yk#uGW#v!)k>adfiPf!=YTq_pHr-?S{CEQKiYcV*-mMNQv%e zhy$xzF4W(W(q5K^_P}Ut_<7fosHadbgl0mZE9rCa&sk_dPoe5@f&ZO5!;&RX4eyg6 zq4>LtX0%D0948pev$RMC*}$C`&j7>M`$dYBY#8O|JPMMHK8tKk?8#g?5(b40ga59Y z(?6^ob!PCsIJ;VUgm!#S+cnL#1vL*3VFvZfS@y%QnRx_K)hYD7ZzqgKQ^^E#?xzv% za}i9-OZNRS@mu0M28@Azbu_H(;<>^-=5}1M;3aT<4T|Yfl^Vji<%s=1gURD4jtA(I zoHg!;$-qKfJf~~(>dQFRPb`GI;bpX`SVH1|F9eYxpSD$meEtYdPCu71+gu7hh^aKQ zrqFJm=Zeo}O*}Hs);-gy^cxEsi+FKn3~O0n7elfMthOf68Wg5(h=(>9VzBF3-6+6~ z!KG^GTV2pb5iu1Rx0xozMbWvNm$t$y;)I|v!(jC874Mj1vm{yJy0N(f7}5Cs*tVm1 zxcym}hqejH;`W>RhjLVb&V~f~lp1ml*%%BZsj{Upv(W$}BTGcQGWwOPD(1`KOnrzy z7!XL3)D1REZQl|BABSn;SPjd&?m+7}lA5Q@bX8(~CfsH0F zl4;}8yV;07VXb|1VOC8ESw-W^xZ2T78?pebhCjgAm40}325hs-Er0QFP74X*0TMY+ z0_F=>&oMswV6rR>Un((!obb<3n+ihETX)C`LYOm3;4wCx|i2wON(Cv7{I~#f5#HL>Pv`9g_W9BoZ zdD$y%2YIq=*a%KUY)u>(LYxr@Pn-U|_LUkxA$wrS zh<7CeW=BQrkLi#KKS7i&-fz^{e|*=gaWBg3AEh9W6KP;U698}Rp_^&8>;@LUoog5V z#nPom;}8>5BP#_C%AQ+49U%$aAN_6IWG*+p<2w3rJYwn1qvc!u4n&qHn`!X+xxb8X zO}}9RI%kSLGiSJ7Su2IreUojV%ri=cOdqhwt8J&LNKnH(fFJ`)aHu{{J_mgQ*VVwq z1f_liPP(tLDvy9I5FWt6ph{L&rFt+QDWzxf^{ebbupsnK_U11~-ae&-F!K7E*3<2W zq>ED~YZ|hlLxN2wC-A)AY>zO9h0QWSyR~VrR$yeXnRn54xN{lU*c`~rR1@?NM7*Sz z&1*+ii=X9|rdQ^}xBa&rnwF7F`mk9rFTn1f;g^og=el&`DV@(bw(r@Kp_LPu1q*VX ziU4&DZ>``cOdNvz^e4i2HV?wz(U?msj&7}G5w&8#Md`EzM&0n~E1M#;ID>}8wl|k_ zu+EGF_R6i4}9O5t`xduW$x#=-6p)%4*KC6%|h6*?@Z-Ero2^^>WR#R(e(WnITKNP+^$diZ8-=jkh1&k(5O%6N0)P^*R>8qWgu+fi@z0Hq*8Tf2oS*B zqh*)cxGH=!JHrziGBcmW@7q;8_5@5Q*t%}nPBKlP`f->jxm3lM^o5Fe1!%jeh&pC~ zA0Po^hx+sbCVficbRt{k*9AJ5S>a2x9!2Lfu;+4;u^)gCal8 zAV(pnx3n%#JIkkgRL#s^dni22$LA>!>LoO^^60yxDq)0y z{m=Hkg@{wNa?a>*|68ecU%K3Vpkn-_cs;3@y}&Z%9A(Tur1p>*E!W|1KIROp5V#$c zbh@-Tqk|v}3|lYt$j@J9Y8gmhSlc`y(0DsqY~rd&>ZARa$^FM?4GkK?c&3)mweVLW z_?Q?GIejP{IuNcC)z#(mRcU_RU}ndL#p{|_$7@?;;`m5$zw+TN$>-*oJMwNa`0eiu z8g)Mg;&4tygt4qCPOzp7IwBg*0N9? zr~<>n!$LaTKba>N!escmsL_&~VaXLNFEEOQmrY_-t!m)ahUq_IHh-%7by!>!wXMjb z@vH?82u^OPMTC#ew@{m@PsQU2{52A9X`{OK!!lTlNuvO<47129O}N7%p+5W*Bt0Av zTIG8-DKl>G<1}_uB*~p*Xv4O)99;_CJ#`9Y7Mcd9T101=1NZ!7!uGH9LjV)bz*6um zRJft<#P?{u{0|zkl7gbPsPI{PaIqH#4xAsObEyrg0gp~O9H=Q=dMM<^IRy?^eoz*n zy8Y?`kR@{#HrpM9SlE>+DjJT-h9umc$e3be3U5)!t~bK)Ho>FO!|ogRi3pw=OwN-C z4>`jP;|}t~X43J3RvvJeFCNI{gA=K*Obd&9o##w$X0G_|?B$_W#ZJja^+g3qF)0_e z^RjFEe1BL+B`|I;n@{zWYtsDiwB~g|xgL2AW<);6WnJYZW}NgJ6r665taI08u)$NQ zc`G7Dvr$hnoL*%06@=lBnDT#i4=l3zk9O;%%wz;7GwQZky!^=!N&zfB(3_Y`moJoC zFGkGH(i@dRf+(RMM(ZmRYhC++v&cQ#*qXlndb*UV2qJ4@P{YIbMEN)JO=Krt=(ERfmRKUwt_#5Z= zH1>oW;>JpiF=SmOQd<6JBr3Wm~Un7tRe1PMJ5KGyw8CJnvD zh}8xZs|?zo64=;*N3}fHq)mnR7?EHm`&-oKBPO#_ZTIvFQWNWBk?^Yepb1_dkzq>k zMy(ckKUD_8`&cuQ4IOEHjiJ>t28jl23>pAc=2ZlMQ37&tBv?jN5$xF`= zN-Z}gB;MYgG>GtvO*owYxa5Airb>y`;=YNSr^b?I&@6&y3L+}unR8UT#@Xq#4vu-b zA=oYVp0v2j*l(w|3>i!;<@{mKmkO+t>jc+;MXlv0uAOJy!`Lt#to#OQ35S8^uX37BdL25~e{jw+Q(^E97JP~3l|K5l z6mgoPE}qEI9bRAXBlI3g@Q1M@0R)8r2#gaw$h&u)r}fl9mCWS^{>#IG)XuhP5x2e3 zN32M-xL2YYKc#L^k}b+;frsSg!!;qhBq~*tK8)5nv(;8^U}jRr!(m1zkW##WdAe4em|X-zeegFtR$vL=Es&ToFrmO z{L`QB<^4d>azFj`Q2%k+me~VrVMq|i#SL`s5W1j2Y39}!To z*7I&XK=BZM=$ZErJA{^0J0SyAs}7SZZ!3py*|~wVlcK!|Q7I0~w??AXb5-VOL5aGs zIOhs#+<{DUs;XQQg&b^t`C6OP+VKJi6FtnRP%T*E=Yhv|tq4bXTt6`^8ELfE2oT-x zjgR4STT|(zlBMiApY8Q;j9cPsGptEEo$WnrNxC+R@;U-J?u!O+w5DB0ktzyp5hKS}gGqQZ8~zm?w&32gqvD~A8Ws+nu( z->t`gu96wKe+ca3&TFtL-5C>|a&m5CQ9~Wdxa_~ZXL8t8DFQ~N4k@Mea`cEVL-KD>!xF2n?t`KfUxg>CCA{ze!%j-Sg%ukaSV!dfK zl6qwSljm(~{RB4K{seh&q5x#Hupoh6?iUgTxUs*T;NLyopV?->{5~r_9h}eq7k>Re z-0{EhHjwfzC_p~o7Ib9%Z*2enGE7_fpIMzI?|b~2)&FEJz}w8oK_H8pQCTpBfOGpF z4wKss!@$tlZlh6!`CqL5|GGN=e@Xr~68`@s`5!NdlZ-zBug4a!antbCc0VJJH3zUa zYe?7IbCa8KqC*H7ymLxkqA|WjFjF-CUp(ss>d$>>aBE5bg}o7VE?DJ1#VHpSdM#i+ zgUw(N@#1K}xob>&*tBZ`H%qo7PM!6S#H@=FwXIe_s|EdEL{L~h*K{iT=jdnv=_F{u z)pc9j7>D;W3l%lB5SaQCq8FJpP{ zI%H8N``0Q?kAPblI_ibrDUV(&5WtjkX+UUX-6KB^@%|LY2}&&-bn{k6>8iJqdZB4< zmBN03($Re<3JJr_dam98>!@vNGZ{jT6M@Yl$=70*bUNV< zsX;EGp%=HCs@FmuKJL5pabybx>_BkqN{sZ6zVk8kLWnhjkzQUNeG^m|sree-*p3B+ zDjsl@Nk)@70#HFETtBdOLxv#=nI0}99|yp{YF2Gc#PdUrU*4m3y)m;=XltmEa%2HX zKfM5Ya|gTgtg<{&T%zhfQE0%dP!Ov&`@*fBBHBPtz)UY2Zsf-$t&Jt4M%v z=lPb0!}UK1k@aU&&T1lC3aJT37(nuAx*Wc5 zsJ(m}+-_NUf>?Fjw#K9OMWqFU$9d^`>cqlKb)5Co{27+N6^)w**N|yYi_cq0i%*iX z^m)tN1$B+yIqFY>vsTM=t}hUqfU9r9std;`gO8xzVBIjnM%e4!-x*VXU%iPR9c#>% zofZJI%xmcyR|aig(d6#6gXcGKj;kKNLp#q#3do|DIuYvX3L~+<+c~vvLHk4Cg$REcv{gHDbPWJy z+pFN>9f(b1boxP_%f>|oL&;ve^;@jO+5Gw8G86>txqOyRyDjKplRpR&IkUuUH@bgu2;ug!i_}=#jXl_>7)NupEghwjo4*~69 zQeoYtVo*-k6A7$yto-8@>O!-o3qOSp13f1YVw3Q5LJQ4+u=aqzZlx&Ss=URfHIjjO zGPL7W|C#U{_3E&SziwB9U_;}Yb9)TG8vE^YqX)Gj8_nQKXOT8odj|gSIxzA7Oqeaz zut@9)1tpHuM5`RJRRn%QP*fB&*Ne1OF+Abrb}bO!r6_n%Bcl{Q7q2%AIM2e!=LlsCFd7Rz7#FlcC>mvFgUY5ZPW65;r4eL zfS_X>1;5p!t|J^Be3V#Lzgw!aymx~e*hc$HZwvV;q^=usJJ3>0(?XyO#xk(4*?~Pr z658}33L+MUEBbtultoCjzbl)u;o|-q(Uac-U>+IXH-uDiutap@`aEujf_yEJ%Msnl z6&^_C;ctC7qZCncQ$m!HM4`?1d~ZAUvE02zoXd404M+Lm^X!CdGug8I#y*`*e15lZ zs&FGA(Q^ZoJ^~QjY_EBGiuHZrkx~@pmSsn(6~bpC zsxUv1RVu0nns53LC{@K?A2{#G$$ijNH~^A>(U+mvMt4ngblZa^c;L|xhNUhov^Z8^ zL48Wd%&dlFzo-iTCr+B9bIXwbBE6anL<~Aw?=}+&?`%jS`1x}Z@1aEESyrI-HeD6( zt#kcuOZ)jlwsszpY>~NRq$#0e(rWcFk^1a+mcpXQ9;YJ9hOH_}iy;jA z*~&FOUo$bM+f5a7G1QTy=~QGq<&F$n{8*)nA??Y9*`B>zC^f4g);4dyHgWH{$ye{P zt%%od%Cj?|J?qcA_?V%srRGJ`qhhX}u`(${ZgMFRMk7ET=u}Tnx zltJ63ca78s>iMkx_D3cB>vl0I&uF>xE)51nCF&EG`x1M!_uoqF3i@Nqqv6?V`_$Xh z%XT;JHwxc=mW(_9!*^)hY6}G`=aiFI)Ar${?m(RmH;F9Mi0j6Ua@n0v5FMb)sl||) zkrJ#T>L-|qRbSU0ZgziC&*qOxFP0eAH3!M_N_D_5e8r`?&QrvmnuRDBi;Eo^i7pXM z`)AAabVeE~*K46EA)&@sP z9IYSnrx+W4BAJHkhs#%W&0K22lk@uXeIe$q&!CecATfP@xlTn(ukg>ODei^v%M|@nM=BWIgv*Wn~A#?kvoKVj+qzl?}JV~dy0FP%Q4!-6zj+bGu$4lM`g5CITxp9 zo5{Lj&JPg82tvN3GqgqfB>6hE_LTWHv=u4k;7KJLmfrGhi=-8vV6{yOqn+Unw!dyz z)f~|(mILLye<%bp7>{V5bll^%z$%Hl6XdEUYrLjx=5ve(w~v-1&r@RnWgOYpFx~B} z(KyS!M)0`~U;TZFY^f+i(b6MA@LRXU#%XI~(V=;_!Jfi?OOvrtL6LFUVm3n;_fs-q ztD|JC-Si7uKcJ71 z(D8XXw#VqZl{Ix@VzyXMT@1XAB`gS2s^+=YIPa7uo^$G~zvFOE z)vaW^Rjs7AtYToiL zT`oo0y3;YPMNx+$*mU-~$A;Xh-{O3K-yiY!yUImr>G4r?KJ4H@p$A!2V zQHN}!hwzNLkKD2seSIpc>m$+c^-&Xp0cp!vj7x9{PSjgvr2^aAUKLAv-`T&dwp32e zi=JXT0A{kpk4uUuR$e@<2W)?SJhO^wb>F~O={9*D7^=!*CX_H}h1>WcOEhs?##O3zjq?R;FIZhhJ&c}r;TJzab8A9Fsss>>xK zr-Ipd>b_zwr>U-Y#*bn)M?qk%=Bie>HM5g@tdI9$}T)U~4NL;A(kfZfhjiQpFJL*7HH98L$wYjz2TuTK5lUMe)l)|)dcMLG9Z zYW9H+06W*5-5%=g#^j4hx{Ha#Hz7_Tw%7U!?9-%SIXyy3141S@ci(7!l6G;cpk)o%W@}o@`?iu9a2RrBqdh=0?Fp}Y zgQP#cLkMp@@2jE5{LxlsQXt0>Ysr!N%YSSd0G-|0QEjp*Ox$j=CX;@|edaxm@Yai1 z318n*t>L%5EtZ)|8_@hdY$q_t2S z!K_fiIl6K##!4^~Tnc)&)6BX@AMj~Lty%vH$oXBVA_Q@7jflMGeZ_E7zq=Ka_TvTI z76;r?{lXp8l3+4Ez`#2=(x(EO(y;z|?(}%+dcezyI^iH(&@mGV2E+f$Xt$p%i-P$* z?2zgV9R3R1dERh%k3v1Y8;>Zs52W%>=3b-wc@4Z-`)2`BBlS4qnl*RB5QFRVN^w`Q z(ie2Hn2E&NgzFRP@QW?y_D!p)BO{)>6TBsw5N3VZ8e-1_JR@&XFj#m%2m9oFU1@RG zn;we4elN|qH|UgDDT&R(=VB6!w{>HR?s8$F%yc+z(iR!s?!kc*&^ABtuW-n;ZEb;v z`Ejq&gob?#m3Oj@J=wo%;5wmQd7lmOyzVe55K(%K-cv5OPn*L-k)pU1Vtf0UukW6Y zIj&!vDflp{a?dfMu&d6&4(0F}sTcVRC$m5o#;)G$OGYBv zlFh^8P9V&VWo$Ot{$<=Olt+Ez7+^|96ZBvxmj z0(!%bTNl!HbB-QaL#cTCZrtg$-3?20y=(Lp%6fOwp{mK7Ritf!!;WI_t{jTAl?_>d z7Eg=Vt$PiY?9POC-LEulh+HG*)OOIehnhg!0EvhLjk15h{$OKb=lk0u*SI9}QpgS< zIn|;+AcdXCW&_W=#`SBAp}BWoHvy)>V!MkGZ{iuRtvciGvB*-RUZZlGsa3is4b_5$*l)vlfkEyrGJtIj@%x@ zJbzM{3+5T?6J@*Z6lwbIx1E{+Q^AkQ;yz$1jm@q_TmOE`yi^v`Xp^hJ1CBgW1=ye< ze%2;%rYHB|TBtxljK#qV9Hn+ly!~BK(%jeN%&U4fjtF2q&-^q%x*o~eJrXc)RuD-d z9pk+SgSHsRDo3<>^x`jWgtD1ck+yraXUnd?DK%F6u2-6@f>Sr)g(0_*V&jGP(&gJ3 z7u=!Jy5y!jdPES_b2rv49;5U}y9j}t)8|{aAYsV-35OIwprE2MPQM7n-E3K#OO!r@ z;$OGW|E;zd&p=A6Bv&Q}FmtHM9A0f0=jfHYW+%#+0xwEEcox zTo<@u7}4f%*!jNQtqK}lzt42rK`B)!q2wAGaNEpNyw%$spp*H@`O4XjzzER$pd+s$ zbmiN|j{VkkKuYkC4I~E|Fm;@obtuLNpHIy>guj_aqsoS63KpVNVz!k~-+JY6VV2=b zQdj12?_SkTyT2Yj&ky-FT|Ywnf+@C*86k!!iWJz8{G7>!7RS&VGU!P5;vnw*%fnhg zzRk?JxdRkENtQAT%1<XewoVMkaDj+_=_k;>H0#6O)&)C`qbO37~Q(`*3$k7mhJT z4-V-t_Oz$pND~P1;RJY9WT{Y;_gD|M;1K3@(w^d2yYG2xljuU8mGKumhQ};d&`_XV zm`{;B9wxr+y)?A@kwtl@3U_)srW9L0?D`^_{>yfs4a1h0LzOHBe)D?w^8t$Oi%Kl+ z{-eT-_ck2V+{*oUBt@dmTpWi!4o1|xn(xJlMt1WjH}aHMchm()=){>rt7CO)nYBnI zfDZy@m>t{iz>>u&29?>e^}z?)1+RbcAul> z?JjAjsp`bSHq-aUpsw(l;qV|>9vlT0)gN^HfGu{)9vSX~2gtj8eeeXkKuFuW=}aPC zn%QSp0+%8Ikn0c;Bwr&+s@Goi5QucyUx)ONm*To2a!IN)W;09X^Q)&#bmj-c3Xaci{u-*Or9au+C-J z=F7xPo$GCydhI%qdsWYm!nY}zk4OZmA5nH`;k`ngh~!!rwo{B0d7Cm1yG@}f+u6RX zU9QYOQ5Yym`R3qPSt>Mwjy>A`vlhT9W+Gjer&`!0HF}$;BWj(=qq;(V0dc8lVg)CtK_w)0xIFc<`!RpFV5eW(C9pOki zzZ=6iTUqi_hH}Bb^NBi9fwb;Bene<@d10r}S%4hfyw;oYqxT+#%fE}3zM?zq$&lD@ z_dz^@F3@7YCbIL2ikS1?QQszFEG;Ya=o0-xDUfwgQR&HxX>{rdDe2;uwJ4nm7RpcR zomZp|WKOQ=Z>ZhCFp^RAa@9eA(OC#sf^p@G6mzv0%esD5m6o~%Pi~P!)Voi>ZAhEI zM*%rUpO9HaI0pJg`XiD6^4-p(#60Y#nJXvN&fgHMaPRZv%Ob5^=;{g&KWp8CR;WJ) zB$JtQsnTIqE_fIQ(->Y3R20%KDUzY1_zNCh>+V+W0t6Kbx?(?HTnRU~@Nv@s6z7|Y zlFPh9v{VM&4nJ&yab`_%NCMI?LK~Y+pA-UZMHM&s^QAG_Q$lJ{l?q`Nwv9H}yp#)r zo5`eszJ`KOx7h*xGxlP=DZ&Ry_lDkz5q7~ysSmu*@3|9}7C-J*IS7IEOF-nV9c!La z5;|X!U~Oq92Qj(@w061B4W7CWx94>adg{m0zS9B@`L5Q7*J*`UO}fKIBmgxjC}C|z zw|u+#0M5ocGC%8L4wsH=TS;fF{b2RlEsgV~kw6? z&oLiJws-Q{^+2Vn74^_)W+~yyFWexXSuW%}`hGuVnk~|GxfGcbl2l$?erRF*GA;=q z&nhQz#%q4}sHj+MI@A$<9x|@EyR9g49;M-l&k2o=h-A=Y5P_M(e7Oc(HzBk}F8R=7 zuJrb=`lLrT?A4~BeKLdu^>C8 zFcF!MC00`DlHZS-!%;8ef|guC=(0EQWjIe)ZYqD*mLPQLZFtM`b?k1ty7o}05^&=U zLYK0A9^E~|zm!L6?I8}$q?WuYAGs4?$Z`7%danJMc!&ucECFTf`FDpdHYvw*d5Qg6 zp-%W9b2R%-lNezDs~Po)j|f(jDtc#Vpu78tN2(%0U!o_oN^@^PSHw~`dO4XSGBhV@ z$D+KPzw@E&*7;_4Y4R`I-_mQGj52MeZ0dH?5|??8k)IiTau45mCtO0s-O0>O!Y0Mv zA}&BWd|w-%5VrWq^c_}+xl~h%RvVNyObW03`-6#3KUD?oRHHy&kSw1t-`20Lr=L0e| zC*f)A$&{^yfqSlCR9IU(o(tYmM(pcDg#0=`GUbSB6qZGAtslFy^pM*zGG5<%bI4Zlh%BsdM@j;ED|@VBMd90DK`0@lAY(+=J;npxVH12u@EY5xyybGfCe@n+!*GcsP>uT}_8ltBqeo zS1N2H;#a6p5A$M9aJp!QvOnU0BSf^sY`-7hm{O^B;n@Q+?fWilIi6@k?ZKqX= ztOTi3WAN}wMI9RaTA%4Uq8YU47Eq>DvJ55GkB>HY*sAzZO-G?!x-&wn{y6JBQ@aZ- z0ITwH6=UcfF0^mynF!rw$LL+wQ!DmvosR@60+u072E#D7jNcJL0am^to1*B%b*0;j--86W@wdn}<{xdj#$n-$ zO?hmM(IEqt`hBa#(BfSRx>G;+pnqm^4522{m01FXd{Pkc`B3)_XtWLdt=C$ra|pRp-64;)`6ZDqeOohWH==v_t?rFAeCU zjTXwQdiSggm8&Kv+J+ew4Zr=>yI$9>wu-lP^UYj0(Ef;Oa`OUfHY2uPygfsvG+-cD z^?|KC(2Tr(%eRm$p$KB1u(rI?j94}3b%YGt)gY+35kM;Si@QBaQx(I%ICRuY@FPFz z5r#HV9-!QeN5gNA1TSjoQU#S{Aq-&I5rHjtFvX`6)TQbVN2K0gKB;-T;%_)tA`e)f z<9zm~2jFBKjcs78s)JXK)W&!5_Ba15e!kBdtJx327%-Y_!R&ssj^RUco=4G!EtE-G z&VPzykQnWQI@a)y?`)4c)ocQBcj#HDK|^-It$@AdKv2ze^|)=4W19&rMYj6E(SpDF z8o0K$zpt<6@A8_VH1ma5Hg}=0zquBW5JT`&RJE?DfFlx7f;M%`nR;NTS*j7bHXN%u z7IE$%JkQbBbNCVd>u0&Xs%&BD8WV`kRip!ZykDoaA3|^kMjg+ZzarX1Lr{>Rj%`G= z$)|sd-`>9zj~xRj>+~DVhHGz)_*}5@hm8&Re`SYT)T=nDTFPk(lWs)CQ9hp*)@_9- zb@#6lbG)pt?<6#TcG-2a>*p$KZ`)ogCe!J?*6vUG0=|H#BpUfFvhHXB*W0&H#T1+ITmR~04yE2_!D!fesZ7Yu7M_|liIl?}V zIACIHRS&LGs9N_WFS@kwn_PWXCvkY2 z!I=2+X9GmWyaHA>+JV*c|KlU%k`!>~wGkbfIEfX)9Hh3B%SnF!zM+7=>+rXGAswxq z3QLmD*%71b>7lpBgG;qk_q(ESS%V9(<`_q+FH-ZG11#haqOhDUOS||i(SeGpa)f{u z^Yh)Uuq20N<0qj~ECj_|Xb|QdVS(lw`kF}pqHbFYHbqEFb7|;fH;ZG*0XG*zU1Ha6 z0`EfmRycEq!q5Akus-Svw0^jlRT4i>#T>Pq?5mw4EK8k8$nKSHOPa>LMe95m@2k?N}CsBceu}5$qpGr3#|B>xcqc&1xp#3`9s|Ned z!HANMNOE{`FFSgTVoR~V zmtuo?I#0ox%K;3O^Leh^T*|<-WpCZJ(d#~CG&ZqKX(rrUKjnMt)n$ITWC{S{tX-lm zly>*!3hb^ehT?23_3_56ORF{X!MP z_YfP+Epjva=1H%PaW;|B$Dp`^3cJjt?pY8F6cN3tYz?{FOkAPRa(NfPEfSXoWRU5c z=YoW%?1p-}qlPm&8aAI#5ozVHklwCg_&p6ZgNQV92i;NAagt5NAK^hnjqGD>0ih~{ z{oihLd2rEiT!8x2RrEAVC_!i>2CmvZ)kn3;gZCb70&5to7R5h|%zs%Jf50@l-zTC;|l+*ZvE-WUNS6K;PUtfQ=C83+~i*~2

uv| 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

}6T8u4i&;JEZ(1wpo|o=>supy$SV)7!!*y)! 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

;Vd6H)ttQ_D<78& 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

gvZ>U||B~9j%f5&ym356A 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
-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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/rancher/dynamiclistener/LICENSE b/vendor/github.com/rancher/dynamiclistener/LICENSE new file mode 100644 index 0000000000..e454a52586 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/LICENSE @@ -0,0 +1,178 @@ + + 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 + diff --git a/vendor/github.com/rancher/norman/pkg/cert/cert.go b/vendor/github.com/rancher/dynamiclistener/cert/cert.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/cert/cert.go rename to vendor/github.com/rancher/dynamiclistener/cert/cert.go diff --git a/vendor/github.com/rancher/norman/pkg/cert/csr.go b/vendor/github.com/rancher/dynamiclistener/cert/csr.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/cert/csr.go rename to vendor/github.com/rancher/dynamiclistener/cert/csr.go diff --git a/vendor/github.com/rancher/norman/pkg/cert/io.go b/vendor/github.com/rancher/dynamiclistener/cert/io.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/cert/io.go rename to vendor/github.com/rancher/dynamiclistener/cert/io.go diff --git a/vendor/github.com/rancher/norman/pkg/cert/pem.go b/vendor/github.com/rancher/dynamiclistener/cert/pem.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/cert/pem.go rename to vendor/github.com/rancher/dynamiclistener/cert/pem.go diff --git a/vendor/github.com/rancher/dynamiclistener/go.mod b/vendor/github.com/rancher/dynamiclistener/go.mod new file mode 100644 index 0000000000..a5e6d2f121 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/go.mod @@ -0,0 +1,14 @@ +module github.com/rancher/dynamiclistener + +go 1.12 + +require ( + github.com/hashicorp/golang-lru v0.5.1 + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/sirupsen/logrus v1.4.1 + github.com/stretchr/testify v1.3.0 // indirect + golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 + golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect + golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 // indirect + golang.org/x/text v0.3.2 // indirect +) diff --git a/vendor/github.com/rancher/dynamiclistener/go.sum b/vendor/github.com/rancher/dynamiclistener/go.sum new file mode 100644 index 0000000000..d117bd21c2 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/go.sum @@ -0,0 +1,38 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 h1:rlLehGeYg6jfoyz/eDqDU1iRXLKfR42nnNh57ytKEWo= +golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug= +golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/github.com/rancher/norman/pkg/dynamiclistener/read.go b/vendor/github.com/rancher/dynamiclistener/read.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/dynamiclistener/read.go rename to vendor/github.com/rancher/dynamiclistener/read.go diff --git a/vendor/github.com/rancher/norman/pkg/dynamiclistener/server.go b/vendor/github.com/rancher/dynamiclistener/server.go similarity index 98% rename from vendor/github.com/rancher/norman/pkg/dynamiclistener/server.go rename to vendor/github.com/rancher/dynamiclistener/server.go index a7b1d64ecb..4a7877ff51 100644 --- a/vendor/github.com/rancher/norman/pkg/dynamiclistener/server.go +++ b/vendor/github.com/rancher/dynamiclistener/server.go @@ -22,10 +22,9 @@ import ( "time" lru "github.com/hashicorp/golang-lru" - cert "github.com/rancher/norman/pkg/cert" + cert "github.com/rancher/dynamiclistener/cert" "github.com/sirupsen/logrus" "golang.org/x/crypto/acme/autocert" - apierrors "k8s.io/apimachinery/pkg/api/errors" ) const ( @@ -66,9 +65,7 @@ func NewServer(listenConfigStorage ListenerConfigStorage, config UserConfig) (Se } lc, err := listenConfigStorage.Get() - if apierrors.IsNotFound(err) { - lc = &ListenerStatus{} - } else if err != nil { + if err != nil { return nil, err } @@ -104,9 +101,7 @@ func (s *server) save() { changed := false cfg, err := s.listenConfigStorage.Get() - if apierrors.IsNotFound(err) { - cfg = &ListenerStatus{} - } else if err != nil { + if err != nil { return } diff --git a/vendor/github.com/rancher/norman/pkg/dynamiclistener/types.go b/vendor/github.com/rancher/dynamiclistener/types.go similarity index 86% rename from vendor/github.com/rancher/norman/pkg/dynamiclistener/types.go rename to vendor/github.com/rancher/dynamiclistener/types.go index a57939b636..87527bdc68 100644 --- a/vendor/github.com/rancher/norman/pkg/dynamiclistener/types.go +++ b/vendor/github.com/rancher/dynamiclistener/types.go @@ -2,8 +2,6 @@ package dynamiclistener import ( "net/http" - - "k8s.io/kubernetes/pkg/util/maps" ) type ListenerConfigStorage interface { @@ -48,9 +46,17 @@ func (l *ListenerStatus) DeepCopyInto(t *ListenerStatus) { t.Revision = l.Revision t.CACert = l.CACert t.CAKey = l.CAKey - t.GeneratedCerts = maps.CopySS(t.GeneratedCerts) + t.GeneratedCerts = copyMap(t.GeneratedCerts) t.KnownIPs = map[string]bool{} for k, v := range l.KnownIPs { t.KnownIPs[k] = v } } + +func copyMap(m map[string]string) map[string]string { + ret := map[string]string{} + for k, v := range m { + ret[k] = v + } + return ret +} diff --git a/vendor/github.com/rancher/norman/.dockerignore b/vendor/github.com/rancher/helm-controller/.dockerignore similarity index 69% rename from vendor/github.com/rancher/norman/.dockerignore rename to vendor/github.com/rancher/helm-controller/.dockerignore index 2e7d9023f0..779935ed56 100644 --- a/vendor/github.com/rancher/norman/.dockerignore +++ b/vendor/github.com/rancher/helm-controller/.dockerignore @@ -1,5 +1,4 @@ -./bin ./.dapper -./dist +./.cache ./.trash-cache -./.idea +./dist diff --git a/vendor/github.com/rancher/helm-controller/.drone.yml b/vendor/github.com/rancher/helm-controller/.drone.yml new file mode 100644 index 0000000000..e1b782c867 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/.drone.yml @@ -0,0 +1,221 @@ +--- +kind: pipeline +name: amd64 + +platform: + os: linux + arch: amd64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-amd64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/helm-controller" + tag: "${DRONE_TAG}-amd64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm64 + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-arm64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/helm-controller" + tag: "${DRONE_TAG}-arm64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm + +platform: + os: linux + arch: arm + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-arm.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/helm-controller" + tag: "${DRONE_TAG}-arm" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: manifest + +platform: + os: linux + arch: amd64 + +steps: +- name: manifest + image: plugins/manifest:1.0.2 + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + platforms: + - linux/amd64 + - linux/arm64 + - linux/arm + target: "rancher/helm-controller:${DRONE_TAG}" + template: "rancher/helm-controller:${DRONE_TAG}-ARCH" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +depends_on: +- amd64 +- arm64 +- arm diff --git a/vendor/github.com/rancher/helm-controller/.gitignore b/vendor/github.com/rancher/helm-controller/.gitignore new file mode 100644 index 0000000000..860bb3ef89 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +/.dapper +/.idea +/bin +/dist +helm-controller diff --git a/vendor/github.com/rancher/helm-controller/Dockerfile.dapper b/vendor/github.com/rancher/helm-controller/Dockerfile.dapper new file mode 100644 index 0000000000..e9af4e12aa --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/Dockerfile.dapper @@ -0,0 +1,26 @@ +FROM golang:1.12.1-alpine3.9 + +RUN apk -U add bash git gcc musl-dev docker vim less file curl wget ca-certificates +RUN go get -d golang.org/x/lint/golint && \ + git -C /go/src/golang.org/x/lint/golint checkout -b current 06c8688daad7faa9da5a0c2f163a3d14aac986ca && \ + go install golang.org/x/lint/golint && \ + rm -rf /go/src /go/pkg +RUN mkdir -p /go/src/golang.org/x && \ + cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \ + git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \ + go install golang.org/x/tools/cmd/goimports +RUN rm -rf /go/src /go/pkg +RUN if [ "${ARCH}" == "amd64" ]; then \ + curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ + fi + +ENV DAPPER_ENV REPO TAG DRONE_TAG +ENV DAPPER_SOURCE /go/src/github.com/rancher/helm-controller/ +ENV DAPPER_OUTPUT ./bin ./dist +ENV DAPPER_DOCKER_SOCKET true +ENV TRASH_CACHE ${DAPPER_SOURCE}/.trash-cache +ENV HOME ${DAPPER_SOURCE} +WORKDIR ${DAPPER_SOURCE} + +ENTRYPOINT ["./scripts/entry"] +CMD ["ci"] diff --git a/vendor/github.com/rancher/helm-controller/Dockerfile.dapper479579668 b/vendor/github.com/rancher/helm-controller/Dockerfile.dapper479579668 new file mode 100644 index 0000000000..e9af4e12aa --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/Dockerfile.dapper479579668 @@ -0,0 +1,26 @@ +FROM golang:1.12.1-alpine3.9 + +RUN apk -U add bash git gcc musl-dev docker vim less file curl wget ca-certificates +RUN go get -d golang.org/x/lint/golint && \ + git -C /go/src/golang.org/x/lint/golint checkout -b current 06c8688daad7faa9da5a0c2f163a3d14aac986ca && \ + go install golang.org/x/lint/golint && \ + rm -rf /go/src /go/pkg +RUN mkdir -p /go/src/golang.org/x && \ + cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \ + git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \ + go install golang.org/x/tools/cmd/goimports +RUN rm -rf /go/src /go/pkg +RUN if [ "${ARCH}" == "amd64" ]; then \ + curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ + fi + +ENV DAPPER_ENV REPO TAG DRONE_TAG +ENV DAPPER_SOURCE /go/src/github.com/rancher/helm-controller/ +ENV DAPPER_OUTPUT ./bin ./dist +ENV DAPPER_DOCKER_SOCKET true +ENV TRASH_CACHE ${DAPPER_SOURCE}/.trash-cache +ENV HOME ${DAPPER_SOURCE} +WORKDIR ${DAPPER_SOURCE} + +ENTRYPOINT ["./scripts/entry"] +CMD ["ci"] diff --git a/vendor/github.com/rancher/norman/LICENSE b/vendor/github.com/rancher/helm-controller/LICENSE similarity index 100% rename from vendor/github.com/rancher/norman/LICENSE rename to vendor/github.com/rancher/helm-controller/LICENSE diff --git a/vendor/github.com/rancher/helm-controller/Makefile b/vendor/github.com/rancher/helm-controller/Makefile new file mode 100644 index 0000000000..d7d72a16d5 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/Makefile @@ -0,0 +1,23 @@ +TARGETS := $(shell ls scripts) + +.dapper: + @echo Downloading dapper + @curl -sL https://releases.rancher.com/dapper/latest/dapper-`uname -s`-`uname -m` > .dapper.tmp + @@chmod +x .dapper.tmp + @./.dapper.tmp -v + @mv .dapper.tmp .dapper + +$(TARGETS): .dapper + ./.dapper $@ + +trash: .dapper + ./.dapper -m bind trash + +trash-keep: .dapper + ./.dapper -m bind trash -k + +deps: trash + +.DEFAULT_GOAL := ci + +.PHONY: $(TARGETS) diff --git a/vendor/github.com/rancher/helm-controller/README.md b/vendor/github.com/rancher/helm-controller/README.md new file mode 100644 index 0000000000..d3c7dd0728 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/README.md @@ -0,0 +1,50 @@ +helm-controller +======== +A simple way to manage helm charts with a Custom Resource Definitions in k8s. + +## Manifests and Deploying +The `./manifests` folder contains useful YAML manifests to use for deploying and developing the Helm Controller. This simply YAML deployment creates a HelmChart CRD + a Deployment using the `rancher/helm-controller` container. The YAML might need some modifications for your environment so read below for Namespaced vs Cluster deployments and how to use them properly. + +#### Namespaced Deploys +Use the `deploy-namespaced.yaml` to create a namespace and add the Helm Controller and CRD to that namespace locking down the Helm Controller to only see changes to CRDs within that namespace. This is defaulted to `helm-controller` so update the YAML to your needs before running `kubectl create` + +#### Cluster Scoped Deploys +If you'd like your helm controller to watch the entire cluster for HelmChart CRD changes use the `deploy-cluster-scoped.yaml` deploy manifest. By default it will add the helm-controller to the `kube-system` so update `metadata.namespace` for your needs. + +## Uninstalling +To remove the Helm Controller run `kubectl delete` and pass the deployment YAML used using to create the Deployment `-f` parameter. + +## Developing and Building +The Helm Controller is easy to get running locally, follow the instructions for your needs and requires a running k8s server + CRDs etc. When you have a working k8s cluster you can use can use `./manifest/crd.yaml` to create the CRD and `./manifest/example-helmchart.yaml` which runs the `stable/traefik` helm chart. + +#### Locally +Building and running natively will start a daemon which will watch a local k8s API. See Manifests section above about how to to create the CRD and Objects using the provided manifests. + +``` +go build -o ./bin/helm-controller +./bin/helm-controller --kubeconfig $HOME/.kube/config +``` + +#### docker/k8s +An easy way to get started with docker/k8s is to install docker for windows/mac and use the included k8s cluster. Once functioning you can easily build locally and get a docker container to pull the Helm Controller container and run it in k8s. Use `make` to launch a linux container and build to create a container. Use the `./manifests/deploy-*.yaml` definitions to get it into your cluster and update `containers.image` to point to your locally image e.g. `image: rancher/helm-controller:dev` + +#### Options and Usage +Use `./bin/helm-controller help` to get full usage details. The outside of a k8s Pod the most important options are `--kubeconfig` or `--masterurl` or it will not run. All options have corresponding ENV variables you could use. + +## Testing +`go test ./...` + +## License +Copyright (c) 2019 [Rancher Labs, Inc.](http://rancher.com) + +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](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. \ No newline at end of file diff --git a/vendor/github.com/rancher/helm-controller/go.mod b/vendor/github.com/rancher/helm-controller/go.mod new file mode 100644 index 0000000000..85b4ff052b --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/go.mod @@ -0,0 +1,17 @@ +module github.com/rancher/helm-controller + +go 1.12 + +require ( + github.com/rancher/wrangler v0.1.3 + github.com/rancher/wrangler-api v0.1.3 + github.com/sirupsen/logrus v1.4.1 + github.com/stretchr/testify v1.3.0 + github.com/urfave/cli v1.20.0 + k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b + k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d + k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible + k8s.io/klog v0.3.0 +) + +replace github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 diff --git a/vendor/github.com/rancher/helm-controller/go.sum b/vendor/github.com/rancher/helm-controller/go.sum new file mode 100644 index 0000000000..807d66fe41 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/go.sum @@ -0,0 +1,230 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc h1:f8eY6cV/x1x+HLjOp4r72s/31/V2aTUtg5oKRRPf8/Q= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jetstack/cert-manager v0.7.2/go.mod h1:nbddmhjWxYGt04bxvwVGUSeLhZ2PCyNvd7MpXdq+yWY= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knative/build v0.6.0/go.mod h1:/sU74ZQkwlYA5FwYDJhYTy61i/Kn+5eWfln2jDbw3Qo= +github.com/knative/pkg v0.0.0-20190514205332-5e4512dcb2ca/go.mod h1:7Ijfhw7rfB+H9VtosIsDYvZQ+qYTz7auK3fHW/5z4ww= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 h1:Xsxh7fX3+2wAUJtPy8g2lZh0cYuyifqhBL0vxCIYojs= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U= +github.com/rancher/wrangler v0.0.0-20190508234038-148d437b510d h1:a7LRgBKNx8USp166pvf4ijrpZmUl8I4Gl6qfFyZpEeo= +github.com/rancher/wrangler v0.0.0-20190508234038-148d437b510d/go.mod h1:snD4YYjLOsxOwXNQORUkKr0y2TOVk54yWjgZ7myL8es= +github.com/rancher/wrangler v0.0.0-20190509213517-cd48b2f2b218 h1:4oOkdVjB8JlNX/89BwMX/tq8h+N31C0egp2XrLfj/nI= +github.com/rancher/wrangler v0.0.0-20190509213517-cd48b2f2b218/go.mod h1:MJVnlQzIsxIt65C9TkmqpYB9mjJW812s2jPNjxYPHNA= +github.com/rancher/wrangler v0.0.0-20190516181950-a7cf48fa83ef/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.0 h1:AIvfe1KLVbj7vsp/pWXeBrjxqP7hHZHHECxsniTC78M= +github.com/rancher/wrangler v0.1.0/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.1 h1:Xz0i5RtpWaqV/83xisxESOBIjf3JnsPExukR+3fiD8M= +github.com/rancher/wrangler v0.1.1/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.2 h1:+oehkcBDInF6dcnG1ZWczL/tV/c7J8ILP3qEFCme7lw= +github.com/rancher/wrangler v0.1.2/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.3 h1:WVMLj7kxTOx2pQyAnUKbbFhuFqhAuzkrsSvk37VaYwY= +github.com/rancher/wrangler v0.1.3/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler-api v0.1.1 h1:qzIgDnURHTlJ31jMTy917L3y0tAjYRaHhMdmT+Z393s= +github.com/rancher/wrangler-api v0.1.1/go.mod h1:vholckBg588JqP3M3vyEDUz/ERaB1M3ilnCuV5XxPHM= +github.com/rancher/wrangler-api v0.1.2 h1:PKWfgxQKNG5v2R7Uo+NYWk6wRXShV55WymiKAFk9eIU= +github.com/rancher/wrangler-api v0.1.2/go.mod h1:zD0Xy4pu2mTUE9pabkOwdzhwms8Yl9AGvDJzGW260Wk= +github.com/rancher/wrangler-api v0.1.3 h1:W6FPEb9cGRNpidiw6S5mu+C6iZ4Ji+wBobjybPOdxQo= +github.com/rancher/wrangler-api v0.1.3/go.mod h1:KPJcBpKwfzsfBL8BO+3fU17NBw8bAk3DUVnHIwE8BGE= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff h1:VARhShG49tiji6mdRNp7JTNDtJ0FhuprF93GBQ37xGU= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190318221613-d196dffd7c2b h1:ZWpVMTsK0ey5WJCu+vVdfMldWq7/ezaOcjnKWIHWVkE= +golang.org/x/net v0.0.0-20190318221613-d196dffd7c2b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190411180116-681f9ce8ac52 h1:9RlW/mHPSeoxtqVWkJ7ZugoTFX8WFZRzmCep/niCbtU= +golang.org/x/tools v0.0.0-20190411180116-681f9ce8ac52/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +k8s.io/api v0.0.0-20190222213804-5cb15d344471 h1:MzQGt8qWQCR+39kbYRd0uQqsvSidpYqJLFeWiJ9l4OE= +k8s.io/api v0.0.0-20190222213804-5cb15d344471/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apiextensions-apiserver v0.0.0-20190325193600-475668423e9f h1:+GpMltIq6SUOswgSQ3HcxgldikyBCreeRDkCYOzwfGk= +k8s.io/apiextensions-apiserver v0.0.0-20190325193600-475668423e9f/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= +k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628 h1:UYfHH+KEF88OTg+GojQUwFTNxbxwmoktLwutUzR0GPg= +k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v2.0.0-alpha.0.0.20190307161346-7621a5ebb88b+incompatible h1:SBpo3pl4emC76nXrrQB25cUzPngCnfzwthOsvcvgsVM= +k8s.io/client-go v2.0.0-alpha.0.0.20190307161346-7621a5ebb88b+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b h1:KH0fUlgdFZH8UMxJ/FDCYHpczfSQKefetq5NjL6BVF0= +k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70 h1:lgPp615xLHxN84RBd+viA/oHzJfI0miFYFH4T9wpPQ4= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d h1:QY1FeareEgkYrWnF2D2XxZFlF0k5Ir4uE8YjD1kHi94= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d/go.mod h1:rVrFWfTVftGH7bb972nWC6N4QkJ4LU7FOXu8GH2UkJo= +k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a h1:QoHVuRquf80YZ+/bovwxoMO3Q/A3nt3yTgS0/0nejuk= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.2.0 h1:0ElL0OHzF3N+OhoJTL0uca20SxtYt4X4+bzHeqrB83c= +k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20190401085232-94e1e7b7574c h1:kJCzg2vGCzah5icgkKR7O1Dzn0NA2iGlym27sb0ZfGE= +k8s.io/kube-openapi v0.0.0-20190401085232-94e1e7b7574c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 h1:IrnrEIp9du1SngrzGC1fdYEdos7Il6I6EVxwFQHJwCg= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 h1:8r+l4bNWjRlsFYlQJnKJ2p7s1YQPj4XyXiJVqDHRx7c= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/k8s.io/kubernetes/pkg/util/maps/string.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/doc.go similarity index 66% rename from vendor/k8s.io/kubernetes/pkg/util/maps/string.go rename to vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/doc.go index 17ef4f2001..d8a07691c9 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/maps/string.go +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +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. @@ -14,16 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -package maps +// Code generated by main. DO NOT EDIT. -// CopySS makes a shallow copy of a map. -func CopySS(m map[string]string) map[string]string { - if m == nil { - return nil - } - copy := make(map[string]string, len(m)) - for k, v := range m { - copy[k] = v - } - return copy -} +// +k8s:deepcopy-gen=package +// +groupName=helm.cattle.io + +package v1 diff --git a/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/types.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/types.go new file mode 100644 index 0000000000..21045a002b --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/types.go @@ -0,0 +1,30 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type HelmChart struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HelmChartSpec `json:"spec,omitempty"` + Status HelmChartStatus `json:"status,omitempty"` +} + +type HelmChartSpec struct { + TargetNamespace string `json:"targetNamespace,omitempty"` + Chart string `json:"chart,omitempty"` + Version string `json:"version,omitempty"` + Repo string `json:"repo,omitempty"` + Set map[string]intstr.IntOrString `json:"set,omitempty"` + ValuesContent string `json:"valuesContent,omitempty"` +} + +type HelmChartStatus struct { + JobName string `json:"jobName,omitempty"` +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_deepcopy.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_deepcopy.go new file mode 100644 index 0000000000..8666e4bbe3 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_deepcopy.go @@ -0,0 +1,126 @@ +// +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 main. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HelmChart) DeepCopyInto(out *HelmChart) { + *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 HelmChart. +func (in *HelmChart) DeepCopy() *HelmChart { + if in == nil { + return nil + } + out := new(HelmChart) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HelmChart) 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 *HelmChartList) DeepCopyInto(out *HelmChartList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HelmChart, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartList. +func (in *HelmChartList) DeepCopy() *HelmChartList { + if in == nil { + return nil + } + out := new(HelmChartList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HelmChartList) 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 *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) { + *out = *in + if in.Set != nil { + in, out := &in.Set, &out.Set + *out = make(map[string]intstr.IntOrString, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartSpec. +func (in *HelmChartSpec) DeepCopy() *HelmChartSpec { + if in == nil { + return nil + } + out := new(HelmChartSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HelmChartStatus) DeepCopyInto(out *HelmChartStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartStatus. +func (in *HelmChartStatus) DeepCopy() *HelmChartStatus { + if in == nil { + return nil + } + out := new(HelmChartStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_list_types.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_list_types.go new file mode 100644 index 0000000000..7f61d978bc --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_list_types.go @@ -0,0 +1,42 @@ +/* +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 main. DO NOT EDIT. + +// +k8s:deepcopy-gen=package +// +groupName=helm.cattle.io +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// HelmChartList is a list of HelmChart resources +type HelmChartList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []HelmChart `json:"items"` +} + +func NewHelmChart(namespace, name string, obj HelmChart) *HelmChart { + obj.APIVersion, obj.Kind = SchemeGroupVersion.WithKind("HelmChart").ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_register.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_register.go new file mode 100644 index 0000000000..8d482e4c56 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1/zz_generated_register.go @@ -0,0 +1,56 @@ +/* +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 main. DO NOT EDIT. + +// +k8s:deepcopy-gen=package +// +groupName=helm.cattle.io +package v1 + +import ( + helm "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: helm.GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns back 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 = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &HelmChart{}, + &HelmChartList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/zz_generated_register.go b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/zz_generated_register.go new file mode 100644 index 0000000000..1b101ea52b --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/zz_generated_register.go @@ -0,0 +1,24 @@ +/* +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 main. DO NOT EDIT. + +package helm + +const ( + // Package-wide consts from generator "zz_generated_register". + GroupName = "helm.cattle.io" +) diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/clientset.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/clientset.go new file mode 100644 index 0000000000..b081c2bfbe --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/clientset.go @@ -0,0 +1,90 @@ +/* +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 main. DO NOT EDIT. + +package versioned + +import ( + helmv1 "github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + HelmV1() helmv1.HelmV1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + helmV1 *helmv1.HelmV1Client +} + +// HelmV1 retrieves the HelmV1Client +func (c *Clientset) HelmV1() helmv1.HelmV1Interface { + return c.helmV1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.helmV1, err = helmv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.helmV1 = helmv1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.helmV1 = helmv1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/doc.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/doc.go new file mode 100644 index 0000000000..78439a3c14 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/doc.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/doc.go new file mode 100644 index 0000000000..6bd144ec29 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/register.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/register.go new file mode 100644 index 0000000000..337ab87a8e --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme/register.go @@ -0,0 +1,56 @@ +/* +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 main. DO NOT EDIT. + +package scheme + +import ( + helmv1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + helmv1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/doc.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/doc.go new file mode 100644 index 0000000000..761c8c49d4 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/generated_expansion.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/generated_expansion.go new file mode 100644 index 0000000000..d99566ca57 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +type HelmChartExpansion interface{} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helm.cattle.io_client.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helm.cattle.io_client.go new file mode 100644 index 0000000000..d29d04f4ba --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helm.cattle.io_client.go @@ -0,0 +1,90 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + "github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type HelmV1Interface interface { + RESTClient() rest.Interface + HelmChartsGetter +} + +// HelmV1Client is used to interact with features provided by the helm.cattle.io group. +type HelmV1Client struct { + restClient rest.Interface +} + +func (c *HelmV1Client) HelmCharts(namespace string) HelmChartInterface { + return newHelmCharts(c, namespace) +} + +// NewForConfig creates a new HelmV1Client for the given config. +func NewForConfig(c *rest.Config) (*HelmV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &HelmV1Client{client}, nil +} + +// NewForConfigOrDie creates a new HelmV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *HelmV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new HelmV1Client for the given RESTClient. +func New(c rest.Interface) *HelmV1Client { + return &HelmV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + 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 *HelmV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helmchart.go b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helmchart.go new file mode 100644 index 0000000000..cbb41e7f32 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1/helmchart.go @@ -0,0 +1,191 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + scheme "github.com/rancher/helm-controller/pkg/generated/clientset/versioned/scheme" + metav1 "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" +) + +// HelmChartsGetter has a method to return a HelmChartInterface. +// A group's client should implement this interface. +type HelmChartsGetter interface { + HelmCharts(namespace string) HelmChartInterface +} + +// HelmChartInterface has methods to work with HelmChart resources. +type HelmChartInterface interface { + Create(*v1.HelmChart) (*v1.HelmChart, error) + Update(*v1.HelmChart) (*v1.HelmChart, error) + UpdateStatus(*v1.HelmChart) (*v1.HelmChart, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.HelmChart, error) + List(opts metav1.ListOptions) (*v1.HelmChartList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.HelmChart, err error) + HelmChartExpansion +} + +// helmCharts implements HelmChartInterface +type helmCharts struct { + client rest.Interface + ns string +} + +// newHelmCharts returns a HelmCharts +func newHelmCharts(c *HelmV1Client, namespace string) *helmCharts { + return &helmCharts{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the helmChart, and returns the corresponding helmChart object, and an error if there is any. +func (c *helmCharts) Get(name string, options metav1.GetOptions) (result *v1.HelmChart, err error) { + result = &v1.HelmChart{} + err = c.client.Get(). + Namespace(c.ns). + Resource("helmcharts"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of HelmCharts that match those selectors. +func (c *helmCharts) List(opts metav1.ListOptions) (result *v1.HelmChartList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.HelmChartList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("helmcharts"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested helmCharts. +func (c *helmCharts) Watch(opts metav1.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("helmcharts"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a helmChart and creates it. Returns the server's representation of the helmChart, and an error, if there is any. +func (c *helmCharts) Create(helmChart *v1.HelmChart) (result *v1.HelmChart, err error) { + result = &v1.HelmChart{} + err = c.client.Post(). + Namespace(c.ns). + Resource("helmcharts"). + Body(helmChart). + Do(). + Into(result) + return +} + +// Update takes the representation of a helmChart and updates it. Returns the server's representation of the helmChart, and an error, if there is any. +func (c *helmCharts) Update(helmChart *v1.HelmChart) (result *v1.HelmChart, err error) { + result = &v1.HelmChart{} + err = c.client.Put(). + Namespace(c.ns). + Resource("helmcharts"). + Name(helmChart.Name). + Body(helmChart). + 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 *helmCharts) UpdateStatus(helmChart *v1.HelmChart) (result *v1.HelmChart, err error) { + result = &v1.HelmChart{} + err = c.client.Put(). + Namespace(c.ns). + Resource("helmcharts"). + Name(helmChart.Name). + SubResource("status"). + Body(helmChart). + Do(). + Into(result) + return +} + +// Delete takes name of the helmChart and deletes it. Returns an error if one occurs. +func (c *helmCharts) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("helmcharts"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *helmCharts) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.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("helmcharts"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched helmChart. +func (c *helmCharts) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.HelmChart, err error) { + result = &v1.HelmChart{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("helmcharts"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/factory.go b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/factory.go new file mode 100644 index 0000000000..bd8346da9a --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package helm + +import ( + "context" + "time" + + clientset "github.com/rancher/helm-controller/pkg/generated/clientset/versioned" + informers "github.com/rancher/helm-controller/pkg/generated/informers/externalversions" + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) Helm() Interface { + return New(c.controllerManager, c.informerFactory.Helm(), c.clientset) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/interface.go b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/interface.go new file mode 100644 index 0000000000..926b9f1c69 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package helm + +import ( + clientset "github.com/rancher/helm-controller/pkg/generated/clientset/versioned" + v1 "github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1" + informers "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io" + "github.com/rancher/wrangler/pkg/generic" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.HelmV1(), g.informers.V1()) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/helmchart.go b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/helmchart.go new file mode 100644 index 0000000000..826222fd8a --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/helmchart.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + clientset "github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1" + informers "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1" + listers "github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1" + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +type HelmChartHandler func(string, *v1.HelmChart) (*v1.HelmChart, error) + +type HelmChartController interface { + HelmChartClient + + OnChange(ctx context.Context, name string, sync HelmChartHandler) + OnRemove(ctx context.Context, name string, sync HelmChartHandler) + Enqueue(namespace, name string) + + Cache() HelmChartCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type HelmChartClient interface { + Create(*v1.HelmChart) (*v1.HelmChart, error) + Update(*v1.HelmChart) (*v1.HelmChart, error) + UpdateStatus(*v1.HelmChart) (*v1.HelmChart, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.HelmChart, error) + List(namespace string, opts metav1.ListOptions) (*v1.HelmChartList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.HelmChart, err error) +} + +type HelmChartCache interface { + Get(namespace, name string) (*v1.HelmChart, error) + List(namespace string, selector labels.Selector) ([]*v1.HelmChart, error) + + AddIndexer(indexName string, indexer HelmChartIndexer) + GetByIndex(indexName, key string) ([]*v1.HelmChart, error) +} + +type HelmChartIndexer func(obj *v1.HelmChart) ([]string, error) + +type helmChartController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.HelmChartsGetter + informer informers.HelmChartInformer + gvk schema.GroupVersionKind +} + +func NewHelmChartController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.HelmChartsGetter, informer informers.HelmChartInformer) HelmChartController { + return &helmChartController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromHelmChartHandlerToHandler(sync HelmChartHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.HelmChart + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.HelmChart)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *helmChartController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.HelmChart)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateHelmChartOnChange(updater generic.Updater, handler HelmChartHandler) HelmChartHandler { + return func(key string, obj *v1.HelmChart) (*v1.HelmChart, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.HelmChart) + } + } + + return copyObj, err + } +} + +func (c *helmChartController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *helmChartController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *helmChartController) OnChange(ctx context.Context, name string, sync HelmChartHandler) { + c.AddGenericHandler(ctx, name, FromHelmChartHandlerToHandler(sync)) +} + +func (c *helmChartController) OnRemove(ctx context.Context, name string, sync HelmChartHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromHelmChartHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *helmChartController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *helmChartController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *helmChartController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *helmChartController) Cache() HelmChartCache { + return &helmChartCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *helmChartController) Create(obj *v1.HelmChart) (*v1.HelmChart, error) { + return c.clientGetter.HelmCharts(obj.Namespace).Create(obj) +} + +func (c *helmChartController) Update(obj *v1.HelmChart) (*v1.HelmChart, error) { + return c.clientGetter.HelmCharts(obj.Namespace).Update(obj) +} + +func (c *helmChartController) UpdateStatus(obj *v1.HelmChart) (*v1.HelmChart, error) { + return c.clientGetter.HelmCharts(obj.Namespace).UpdateStatus(obj) +} + +func (c *helmChartController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.HelmCharts(namespace).Delete(name, options) +} + +func (c *helmChartController) Get(namespace, name string, options metav1.GetOptions) (*v1.HelmChart, error) { + return c.clientGetter.HelmCharts(namespace).Get(name, options) +} + +func (c *helmChartController) List(namespace string, opts metav1.ListOptions) (*v1.HelmChartList, error) { + return c.clientGetter.HelmCharts(namespace).List(opts) +} + +func (c *helmChartController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.HelmCharts(namespace).Watch(opts) +} + +func (c *helmChartController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.HelmChart, err error) { + return c.clientGetter.HelmCharts(namespace).Patch(name, pt, data, subresources...) +} + +type helmChartCache struct { + lister listers.HelmChartLister + indexer cache.Indexer +} + +func (c *helmChartCache) Get(namespace, name string) (*v1.HelmChart, error) { + return c.lister.HelmCharts(namespace).Get(name) +} + +func (c *helmChartCache) List(namespace string, selector labels.Selector) ([]*v1.HelmChart, error) { + return c.lister.HelmCharts(namespace).List(selector) +} + +func (c *helmChartCache) AddIndexer(indexName string, indexer HelmChartIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.HelmChart)) + }, + })) +} + +func (c *helmChartCache) GetByIndex(indexName, key string) (result []*v1.HelmChart, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.HelmChart)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/interface.go b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/interface.go new file mode 100644 index 0000000000..237b1b2bb9 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1/interface.go @@ -0,0 +1,49 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + clientset "github.com/rancher/helm-controller/pkg/generated/clientset/versioned/typed/helm.cattle.io/v1" + informers "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1" + "github.com/rancher/wrangler/pkg/generic" +) + +type Interface interface { + HelmChart() HelmChartController +} + +func New(controllerManager *generic.ControllerManager, client clientset.HelmV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.HelmV1Interface +} + +func (c *version) HelmChart() HelmChartController { + return NewHelmChartController(v1.SchemeGroupVersion.WithKind("HelmChart"), c.controllerManager, c.client, c.informers.HelmCharts()) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/factory.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/factory.go new file mode 100644 index 0000000000..1f03994ee4 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/factory.go @@ -0,0 +1,180 @@ +/* +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 main. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/rancher/helm-controller/pkg/generated/clientset/versioned" + helmcattleio "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io" + internalinterfaces "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Helm() helmcattleio.Interface +} + +func (f *sharedInformerFactory) Helm() helmcattleio.Interface { + return helmcattleio.New(f, f.namespace, f.tweakListOptions) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/generic.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/generic.go new file mode 100644 index 0000000000..d62013bc6c --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/generic.go @@ -0,0 +1,62 @@ +/* +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 main. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=helm.cattle.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("helmcharts"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Helm().V1().HelmCharts().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/interface.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/interface.go new file mode 100644 index 0000000000..b2ce3331f2 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/interface.go @@ -0,0 +1,46 @@ +/* +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 main. DO NOT EDIT. + +package helm + +import ( + v1 "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1" + internalinterfaces "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.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} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/helmchart.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/helmchart.go new file mode 100644 index 0000000000..06fea9f987 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/helmchart.go @@ -0,0 +1,89 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + time "time" + + helmcattleiov1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + versioned "github.com/rancher/helm-controller/pkg/generated/clientset/versioned" + internalinterfaces "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1" + metav1 "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" +) + +// HelmChartInformer provides access to a shared informer and lister for +// HelmCharts. +type HelmChartInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.HelmChartLister +} + +type helmChartInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewHelmChartInformer constructs a new informer for HelmChart 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 NewHelmChartInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredHelmChartInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredHelmChartInformer constructs a new informer for HelmChart 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 NewFilteredHelmChartInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HelmV1().HelmCharts(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.HelmV1().HelmCharts(namespace).Watch(options) + }, + }, + &helmcattleiov1.HelmChart{}, + resyncPeriod, + indexers, + ) +} + +func (f *helmChartInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredHelmChartInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *helmChartInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&helmcattleiov1.HelmChart{}, f.defaultInformer) +} + +func (f *helmChartInformer) Lister() v1.HelmChartLister { + return v1.NewHelmChartLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/interface.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/interface.go new file mode 100644 index 0000000000..1676770169 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/helm.cattle.io/v1/interface.go @@ -0,0 +1,45 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // HelmCharts returns a HelmChartInformer. + HelmCharts() HelmChartInformer +} + +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} +} + +// HelmCharts returns a HelmChartInformer. +func (v *version) HelmCharts() HelmChartInformer { + return &helmChartInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 0000000000..938b038854 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,40 @@ +/* +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 main. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/rancher/helm-controller/pkg/generated/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/expansion_generated.go b/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/expansion_generated.go new file mode 100644 index 0000000000..fd274425a6 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +// HelmChartListerExpansion allows custom methods to be added to +// HelmChartLister. +type HelmChartListerExpansion interface{} + +// HelmChartNamespaceListerExpansion allows custom methods to be added to +// HelmChartNamespaceLister. +type HelmChartNamespaceListerExpansion interface{} diff --git a/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/helmchart.go b/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/helmchart.go new file mode 100644 index 0000000000..6c3c316bc7 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/pkg/generated/listers/helm.cattle.io/v1/helmchart.go @@ -0,0 +1,94 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// HelmChartLister helps list HelmCharts. +type HelmChartLister interface { + // List lists all HelmCharts in the indexer. + List(selector labels.Selector) (ret []*v1.HelmChart, err error) + // HelmCharts returns an object that can list and get HelmCharts. + HelmCharts(namespace string) HelmChartNamespaceLister + HelmChartListerExpansion +} + +// helmChartLister implements the HelmChartLister interface. +type helmChartLister struct { + indexer cache.Indexer +} + +// NewHelmChartLister returns a new HelmChartLister. +func NewHelmChartLister(indexer cache.Indexer) HelmChartLister { + return &helmChartLister{indexer: indexer} +} + +// List lists all HelmCharts in the indexer. +func (s *helmChartLister) List(selector labels.Selector) (ret []*v1.HelmChart, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.HelmChart)) + }) + return ret, err +} + +// HelmCharts returns an object that can list and get HelmCharts. +func (s *helmChartLister) HelmCharts(namespace string) HelmChartNamespaceLister { + return helmChartNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// HelmChartNamespaceLister helps list and get HelmCharts. +type HelmChartNamespaceLister interface { + // List lists all HelmCharts in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.HelmChart, err error) + // Get retrieves the HelmChart from the indexer for a given namespace and name. + Get(name string) (*v1.HelmChart, error) + HelmChartNamespaceListerExpansion +} + +// helmChartNamespaceLister implements the HelmChartNamespaceLister +// interface. +type helmChartNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all HelmCharts in the indexer for a given namespace. +func (s helmChartNamespaceLister) List(selector labels.Selector) (ret []*v1.HelmChart, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.HelmChart)) + }) + return ret, err +} + +// Get retrieves the HelmChart from the indexer for a given namespace and name. +func (s helmChartNamespaceLister) Get(name string) (*v1.HelmChart, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("helmchart"), name) + } + return obj.(*v1.HelmChart), nil +} diff --git a/pkg/helm/controller.go b/vendor/github.com/rancher/helm-controller/pkg/helm/controller.go similarity index 66% rename from pkg/helm/controller.go rename to vendor/github.com/rancher/helm-controller/pkg/helm/controller.go index c30384f66b..7e67827b5e 100644 --- a/pkg/helm/controller.go +++ b/vendor/github.com/rancher/helm-controller/pkg/helm/controller.go @@ -8,12 +8,14 @@ import ( "os" "sort" - batchclient "github.com/rancher/k3s/types/apis/batch/v1" - coreclient "github.com/rancher/k3s/types/apis/core/v1" - k3s "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" - rbacclients "github.com/rancher/k3s/types/apis/rbac.authorization.k8s.io/v1" - "github.com/rancher/norman/pkg/changeset" - "github.com/rancher/norman/pkg/objectset" + helmv1 "github.com/rancher/helm-controller/pkg/apis/helm.cattle.io/v1" + helmcontroller "github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io/v1" + batchcontroller "github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1" + corecontroller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" + rbaccontroller "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1" + "github.com/rancher/wrangler/pkg/apply" + "github.com/rancher/wrangler/pkg/objectset" + "github.com/rancher/wrangler/pkg/relatedresource" batch "k8s.io/api/batch/v1" core "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" @@ -23,42 +25,38 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -const ( - namespace = "kube-system" - image = "rancher/klipper-helm:v0.1.5" - label = "helm.k3s.cattle.io/chart" -) - var ( trueVal = true ) -func Register(ctx context.Context) error { - k3sClients := k3s.ClientsFrom(ctx) - coreClients := coreclient.ClientsFrom(ctx) - jobClients := batchclient.ClientsFrom(ctx) - rbacClients := rbacclients.ClientsFrom(ctx) +type Controller struct { + namespace string + helmController helmcontroller.HelmChartController + jobsCache batchcontroller.JobCache + apply apply.Apply +} - h := &handler{ - jobs: jobClients.Job, - jobCache: jobClients.Job.Cache(), - processor: objectset.NewProcessor("k3s.helm"). - Client(coreClients.ConfigMap). - Client(coreClients.ServiceAccount). - Client(jobClients.Job). - Client(rbacClients.ClusterRoleBinding). - Patcher(batch.SchemeGroupVersion.WithKind("Job"), objectset.ReplaceOnChange), - } +const ( + image = "rancher/klipper-helm:v0.1.5" + label = "helmcharts.helm.cattle.io/chart" + name = "helm-controller" +) - k3sClients.HelmChart.OnChange(ctx, "helm", h.onChange) - k3sClients.HelmChart.OnRemove(ctx, "helm", h.onRemove) +func Register(ctx context.Context, apply apply.Apply, + helms helmcontroller.HelmChartController, + jobs batchcontroller.JobController, + crbs rbaccontroller.ClusterRoleBindingController, + sas corecontroller.ServiceAccountController) { + apply = apply.WithSetID(name). + WithCacheTypes(helms, jobs, crbs, sas). + WithStrictCaching() - changeset.Watch(ctx, "helm-pod-watch", - func(namespace, name string, obj runtime.Object) ([]changeset.Key, error) { + relatedresource.Watch(ctx, "helm-pod-watch", + func(namespace, name string, obj runtime.Object) ([]relatedresource.Key, error) { if job, ok := obj.(*batch.Job); ok { name := job.Labels[label] if name != "" { - return []changeset.Key{ + return []relatedresource.Key{ { Name: name, Namespace: namespace, @@ -68,19 +66,25 @@ func Register(ctx context.Context) error { } return nil, nil }, - k3sClients.HelmChart, - jobClients.Job) - return nil + helms, + jobs) + + controller := &Controller{ + helmController: helms, + jobsCache: jobs.Cache(), + apply: apply, + } + + helms.OnChange(ctx, name, controller.OnHelmChanged) + helms.OnRemove(ctx, name, controller.OnHelmRemove) } -type handler struct { - jobCache batchclient.JobClientCache - jobs batchclient.JobClient - processor *objectset.Processor -} +func (c *Controller) OnHelmChanged(key string, chart *helmv1.HelmChart) (*helmv1.HelmChart, error) { + if chart == nil { + return nil, nil + } -func (h *handler) onChange(chart *k3s.HelmChart) (runtime.Object, error) { - if chart.Namespace != namespace || chart.Spec.Chart == "" { + if chart.Spec.Chart == "" { return chart, nil } @@ -93,39 +97,47 @@ func (h *handler) onChange(chart *k3s.HelmChart) (runtime.Object, error) { objs.Add(configMap) } - if err := h.processor.NewDesiredSet(chart, objs).Apply(); err != nil { + if err := c.apply.WithOwner(chart).Apply(objs); err != nil { return chart, err } - chart.Status.JobName = job.Name - return chart, nil + chartCopy := chart.DeepCopy() + chartCopy.Status.JobName = job.Name + return c.helmController.Update(chartCopy) } -func (h *handler) onRemove(chart *k3s.HelmChart) (runtime.Object, error) { - if chart.Namespace != namespace || chart.Spec.Chart == "" { +func (c *Controller) OnHelmRemove(key string, chart *helmv1.HelmChart) (*helmv1.HelmChart, error) { + if chart.Spec.Chart == "" { return chart, nil } - job, _ := job(chart) + job, err := c.jobsCache.Get(chart.Namespace, job.Name) - job, err := h.jobCache.Get(chart.Namespace, job.Name) if errors.IsNotFound(err) { - _, err := h.onChange(chart) + _, err := c.OnHelmChanged(key, chart) if err != nil { return chart, err } } else if err != nil { - return nil, err + return chart, err } if job.Status.Succeeded <= 0 { - return nil, fmt.Errorf("waiting for delete of helm chart %s", chart.Name) + return chart, fmt.Errorf("waiting for delete of helm chart %s", chart.Name) } - return chart, h.processor.NewDesiredSet(chart, objectset.NewObjectSet()).Apply() + chartCopy := chart.DeepCopy() + chartCopy.Status.JobName = job.Name + newChart, err := c.helmController.Update(chartCopy) + + if err != nil { + return newChart, err + } + + return newChart, c.apply.WithOwner(newChart).Apply(objectset.NewObjectSet()) } -func job(chart *k3s.HelmChart) (*batch.Job, *core.ConfigMap) { +func job(chart *helmv1.HelmChart) (*batch.Job, *core.ConfigMap) { oneThousand := int32(1000) valuesHash := sha256.Sum256([]byte(chart.Spec.ValuesContent)) @@ -215,7 +227,7 @@ func job(chart *k3s.HelmChart) (*batch.Job, *core.ConfigMap) { return job, configMap } -func configMap(chart *k3s.HelmChart) *core.ConfigMap { +func configMap(chart *helmv1.HelmChart) *core.ConfigMap { if chart.Spec.ValuesContent == "" { return nil } @@ -235,7 +247,7 @@ func configMap(chart *k3s.HelmChart) *core.ConfigMap { } } -func roleBinding(chart *k3s.HelmChart) *rbac.ClusterRoleBinding { +func roleBinding(chart *helmv1.HelmChart) *rbac.ClusterRoleBinding { return &rbac.ClusterRoleBinding{ TypeMeta: meta.TypeMeta{ APIVersion: "rbac.authorization.k8s.io/v1", @@ -257,10 +269,9 @@ func roleBinding(chart *k3s.HelmChart) *rbac.ClusterRoleBinding { }, }, } - } -func serviceAccount(chart *k3s.HelmChart) *core.ServiceAccount { +func serviceAccount(chart *helmv1.HelmChart) *core.ServiceAccount { return &core.ServiceAccount{ TypeMeta: meta.TypeMeta{ APIVersion: "v1", @@ -274,7 +285,7 @@ func serviceAccount(chart *k3s.HelmChart) *core.ServiceAccount { } } -func args(chart *k3s.HelmChart) []string { +func args(chart *helmv1.HelmChart) []string { if chart.DeletionTimestamp != nil { return []string{ "delete", diff --git a/vendor/github.com/rancher/helm-controller/vendor.conf b/vendor/github.com/rancher/helm-controller/vendor.conf new file mode 100644 index 0000000000..2fa77ef470 --- /dev/null +++ b/vendor/github.com/rancher/helm-controller/vendor.conf @@ -0,0 +1,5 @@ +# package +github.com/urfave/cli v1.18.0 +github.com/rancher/wrangler latest +k8s.io/kubernetes v1.14.1 transitive=true,staging=true +golang.org/x/sync/errgroup latest \ No newline at end of file diff --git a/vendor/github.com/rancher/norman/.drone.yml b/vendor/github.com/rancher/norman/.drone.yml deleted file mode 100644 index 8f5c37cdad..0000000000 --- a/vendor/github.com/rancher/norman/.drone.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -pipeline: - build: - privileged: true - image: rancher/dapper:1.11.2 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - commands: - - dapper ci diff --git a/vendor/github.com/rancher/norman/.gitignore b/vendor/github.com/rancher/norman/.gitignore deleted file mode 100644 index a10e060c7d..0000000000 --- a/vendor/github.com/rancher/norman/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/.idea -/.dapper -/bin -/dist -*.swp -/.trash-cache -/trash.lock diff --git a/vendor/github.com/rancher/norman/Dockerfile.dapper b/vendor/github.com/rancher/norman/Dockerfile.dapper deleted file mode 100644 index 3cc956b86b..0000000000 --- a/vendor/github.com/rancher/norman/Dockerfile.dapper +++ /dev/null @@ -1,16 +0,0 @@ -FROM golang:1.11-alpine - -RUN apk -U add bash git gcc musl-dev docker -RUN go get -d golang.org/x/lint/golint && \ - git -C /go/src/golang.org/x/lint/golint checkout -b current 06c8688daad7faa9da5a0c2f163a3d14aac986ca && \ - go install golang.org/x/lint/golint && \ - rm -rf /go/src /go/pkg - -ENV DAPPER_SOURCE /go/src/github.com/rancher/norman/ -ENV DAPPER_OUTPUT ./bin ./dist -ENV DAPPER_DOCKER_SOCKET true -ENV HOME ${DAPPER_SOURCE} -WORKDIR ${DAPPER_SOURCE} - -ENTRYPOINT ["./scripts/entry"] -CMD ["ci"] diff --git a/vendor/github.com/rancher/norman/api/access/list.go b/vendor/github.com/rancher/norman/api/access/list.go deleted file mode 100644 index 3595c4b717..0000000000 --- a/vendor/github.com/rancher/norman/api/access/list.go +++ /dev/null @@ -1,87 +0,0 @@ -package access - -import ( - "fmt" - - "github.com/rancher/norman/parse/builder" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -func Create(context *types.APIContext, version *types.APIVersion, typeName string, data map[string]interface{}, into interface{}) error { - schema := context.Schemas.Schema(version, typeName) - if schema == nil { - return fmt.Errorf("failed to find schema " + typeName) - } - - item, err := schema.Store.Create(context, schema, data) - if err != nil { - return err - } - - b := builder.NewBuilder(context) - b.Version = version - - item, err = b.Construct(schema, item, builder.List) - if err != nil { - return err - } - - if into == nil { - return nil - } - - return convert.ToObj(item, into) -} - -func ByID(context *types.APIContext, version *types.APIVersion, typeName string, id string, into interface{}) error { - schema := context.Schemas.Schema(version, typeName) - if schema == nil { - return fmt.Errorf("failed to find schema " + typeName) - } - - item, err := schema.Store.ByID(context, schema, id) - if err != nil { - return err - } - - b := builder.NewBuilder(context) - b.Version = version - - item, err = b.Construct(schema, item, builder.List) - if err != nil { - return err - } - - if into == nil { - return nil - } - - return convert.ToObj(item, into) -} - -func List(context *types.APIContext, version *types.APIVersion, typeName string, opts *types.QueryOptions, into interface{}) error { - schema := context.Schemas.Schema(version, typeName) - if schema == nil { - return fmt.Errorf("failed to find schema " + typeName) - } - - data, err := schema.Store.List(context, schema, opts) - if err != nil { - return err - } - - b := builder.NewBuilder(context) - b.Version = version - - var newData []map[string]interface{} - for _, item := range data { - item, err = b.Construct(schema, item, builder.List) - if err != nil { - return err - } - newData = append(newData, item) - } - - return convert.ToObj(newData, into) -} diff --git a/vendor/github.com/rancher/norman/api/builtin/api_root.go b/vendor/github.com/rancher/norman/api/builtin/api_root.go deleted file mode 100644 index c51b81a028..0000000000 --- a/vendor/github.com/rancher/norman/api/builtin/api_root.go +++ /dev/null @@ -1,81 +0,0 @@ -package builtin - -import ( - "github.com/rancher/norman/store/empty" - "github.com/rancher/norman/types" -) - -func APIRootFormatter(apiContext *types.APIContext, resource *types.RawResource) { - path, _ := resource.Values["path"].(string) - if path == "" { - return - } - - delete(resource.Values, "path") - - resource.Links["root"] = apiContext.URLBuilder.RelativeToRoot(path) - - data, _ := resource.Values["apiVersion"].(map[string]interface{}) - apiVersion := apiVersionFromMap(apiContext.Schemas, data) - - resource.Links["self"] = apiContext.URLBuilder.Version(apiVersion) - - for _, schema := range apiContext.Schemas.SchemasForVersion(apiVersion) { - addCollectionLink(apiContext, schema, resource.Links) - } - - return -} - -func addCollectionLink(apiContext *types.APIContext, schema *types.Schema, links map[string]string) { - collectionLink := getSchemaCollectionLink(apiContext, schema, nil) - if collectionLink != "" { - links[schema.PluralName] = collectionLink - } -} - -type APIRootStore struct { - empty.Store - roots []string -} - -func NewAPIRootStore(roots []string) types.Store { - return &APIRootStore{roots: roots} -} - -func (a *APIRootStore) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - for _, version := range apiContext.Schemas.Versions() { - if version.Path == id { - return apiVersionToAPIRootMap(version), nil - } - } - return nil, nil -} - -func (a *APIRootStore) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { - var roots []map[string]interface{} - - for _, version := range apiContext.Schemas.Versions() { - roots = append(roots, apiVersionToAPIRootMap(version)) - } - - for _, root := range a.roots { - roots = append(roots, map[string]interface{}{ - "path": root, - }) - } - - return roots, nil -} - -func apiVersionToAPIRootMap(version types.APIVersion) map[string]interface{} { - return map[string]interface{}{ - "type": "/meta/schemas/apiRoot", - "apiVersion": map[string]interface{}{ - "version": version.Version, - "group": version.Group, - "path": version.Path, - }, - "path": version.Path, - } -} diff --git a/vendor/github.com/rancher/norman/api/builtin/schema.go b/vendor/github.com/rancher/norman/api/builtin/schema.go deleted file mode 100644 index 30044ea4a8..0000000000 --- a/vendor/github.com/rancher/norman/api/builtin/schema.go +++ /dev/null @@ -1,136 +0,0 @@ -package builtin - -import ( - "net/http" - - "github.com/rancher/norman/store/schema" - "github.com/rancher/norman/types" -) - -var ( - Version = types.APIVersion{ - Group: "meta.cattle.io", - Version: "v1", - Path: "/meta", - } - - Schema = types.Schema{ - ID: "schema", - PluralName: "schemas", - Version: Version, - CollectionMethods: []string{"GET"}, - ResourceMethods: []string{"GET"}, - ResourceFields: map[string]types.Field{ - "collectionActions": {Type: "map[json]"}, - "collectionFields": {Type: "map[json]"}, - "collectionFilters": {Type: "map[json]"}, - "collectionMethods": {Type: "array[string]"}, - "pluralName": {Type: "string"}, - "resourceActions": {Type: "map[json]"}, - "resourceFields": {Type: "map[json]"}, - "resourceMethods": {Type: "array[string]"}, - "version": {Type: "map[json]"}, - }, - Formatter: SchemaFormatter, - Store: schema.NewSchemaStore(), - } - - Error = types.Schema{ - ID: "error", - Version: Version, - ResourceMethods: []string{}, - CollectionMethods: []string{}, - ResourceFields: map[string]types.Field{ - "code": {Type: "string"}, - "detail": {Type: "string", Nullable: true}, - "message": {Type: "string", Nullable: true}, - "fieldName": {Type: "string", Nullable: true}, - "status": {Type: "int"}, - }, - } - - Collection = types.Schema{ - ID: "collection", - Version: Version, - ResourceMethods: []string{}, - CollectionMethods: []string{}, - ResourceFields: map[string]types.Field{ - "data": {Type: "array[json]"}, - "pagination": {Type: "map[json]"}, - "sort": {Type: "map[json]"}, - "filters": {Type: "map[json]"}, - }, - } - - APIRoot = types.Schema{ - ID: "apiRoot", - Version: Version, - CollectionMethods: []string{"GET"}, - ResourceMethods: []string{"GET"}, - ResourceFields: map[string]types.Field{ - "apiVersion": {Type: "map[json]"}, - "path": {Type: "string"}, - }, - Formatter: APIRootFormatter, - Store: NewAPIRootStore(nil), - } - - Schemas = types.NewSchemas(). - AddSchema(Schema). - AddSchema(Error). - AddSchema(Collection). - AddSchema(APIRoot) -) - -func apiVersionFromMap(schemas *types.Schemas, apiVersion map[string]interface{}) types.APIVersion { - path, _ := apiVersion["path"].(string) - version, _ := apiVersion["version"].(string) - group, _ := apiVersion["group"].(string) - - apiVersionObj := types.APIVersion{ - Path: path, - Version: version, - Group: group, - } - - for _, testVersion := range schemas.Versions() { - if testVersion.Equals(&apiVersionObj) { - return testVersion - } - } - - return apiVersionObj -} - -func SchemaFormatter(apiContext *types.APIContext, resource *types.RawResource) { - data, _ := resource.Values["version"].(map[string]interface{}) - apiVersion := apiVersionFromMap(apiContext.Schemas, data) - - schema := apiContext.Schemas.Schema(&apiVersion, resource.ID) - if schema == nil { - return - } - - collectionLink := getSchemaCollectionLink(apiContext, schema, &apiVersion) - if collectionLink != "" { - resource.Links["collection"] = collectionLink - } - - resource.Links["self"] = apiContext.URLBuilder.SchemaLink(schema) -} - -func getSchemaCollectionLink(apiContext *types.APIContext, schema *types.Schema, apiVersion *types.APIVersion) string { - if schema != nil && contains(schema.CollectionMethods, http.MethodGet) { - return apiContext.URLBuilder.Collection(schema, apiVersion) - } - return "" -} - -func contains(list []string, needle string) bool { - for _, v := range list { - if v == needle { - return true - } - } - return false -} diff --git a/vendor/github.com/rancher/norman/api/handler/create.go b/vendor/github.com/rancher/norman/api/handler/create.go deleted file mode 100644 index 75f2b152b1..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/create.go +++ /dev/null @@ -1,30 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" -) - -func CreateHandler(apiContext *types.APIContext, next types.RequestHandler) error { - var err error - - data, err := ParseAndValidateBody(apiContext, true) - if err != nil { - return err - } - - store := apiContext.Schema.Store - if store == nil { - return httperror.NewAPIError(httperror.NotFound, "no store found") - } - - data, err = store.Create(apiContext, apiContext.Schema, data) - if err != nil { - return err - } - - apiContext.WriteResponse(http.StatusCreated, data) - return nil -} diff --git a/vendor/github.com/rancher/norman/api/handler/delete.go b/vendor/github.com/rancher/norman/api/handler/delete.go deleted file mode 100644 index 141c22482b..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/delete.go +++ /dev/null @@ -1,27 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" -) - -func DeleteHandler(request *types.APIContext, next types.RequestHandler) error { - store := request.Schema.Store - if store == nil { - return httperror.NewAPIError(httperror.NotFound, "no store found") - } - - obj, err := store.Delete(request, request.Schema, request.ID) - if err != nil { - return err - } - - if obj == nil { - request.WriteResponse(http.StatusNoContent, nil) - } else { - request.WriteResponse(http.StatusOK, obj) - } - return nil -} diff --git a/vendor/github.com/rancher/norman/api/handler/list.go b/vendor/github.com/rancher/norman/api/handler/list.go deleted file mode 100644 index 9b9fb0522a..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/list.go +++ /dev/null @@ -1,43 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/parse" - "github.com/rancher/norman/types" -) - -func ListHandler(request *types.APIContext, next types.RequestHandler) error { - var ( - err error - data interface{} - ) - - store := request.Schema.Store - if store == nil { - return httperror.NewAPIError(httperror.NotFound, "no store found") - } - - if request.ID == "" { - opts := parse.QueryOptions(request, request.Schema) - // Save the pagination on the context so it's not reset later - request.Pagination = opts.Pagination - data, err = store.List(request, request.Schema, &opts) - } else if request.Link == "" { - data, err = store.ByID(request, request.Schema, request.ID) - } else { - _, err = store.ByID(request, request.Schema, request.ID) - if err != nil { - return err - } - return request.Schema.LinkHandler(request, nil) - } - - if err != nil { - return err - } - - request.WriteResponse(http.StatusOK, data) - return nil -} diff --git a/vendor/github.com/rancher/norman/api/handler/query.go b/vendor/github.com/rancher/norman/api/handler/query.go deleted file mode 100644 index 2c5449842f..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/query.go +++ /dev/null @@ -1,121 +0,0 @@ -package handler - -import ( - "sort" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -func QueryFilter(opts *types.QueryOptions, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} { - return ApplyQueryOptions(opts, schema, data) -} - -func ApplyQueryOptions(options *types.QueryOptions, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} { - data = ApplyQueryConditions(options.Conditions, schema, data) - data = ApplySort(options.Sort, data) - return ApplyPagination(options.Pagination, data) -} - -func ApplySort(sortOpts types.Sort, data []map[string]interface{}) []map[string]interface{} { - name := sortOpts.Name - if name == "" { - name = "id" - } - - sort.Slice(data, func(i, j int) bool { - left, right := i, j - if sortOpts.Order == types.DESC { - left, right = j, i - } - - return convert.ToString(data[left][name]) < convert.ToString(data[right][name]) - }) - - return data -} - -func ApplyQueryConditions(conditions []*types.QueryCondition, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} { - var result []map[string]interface{} - -outer: - for _, item := range data { - for _, condition := range conditions { - if !condition.Valid(schema, item) { - continue outer - } - } - - result = append(result, item) - } - - return result -} - -func ApplyPagination(pagination *types.Pagination, data []map[string]interface{}) []map[string]interface{} { - if pagination == nil || pagination.Limit == nil { - return data - } - - limit := *pagination.Limit - if limit < 0 { - limit = 0 - } - - total := int64(len(data)) - - // Reset fields - pagination.Next = "" - pagination.Previous = "" - pagination.Partial = false - pagination.Total = &total - pagination.First = "" - - if len(data) == 0 { - return data - } - - // startIndex is guaranteed to be a valid index - startIndex := int64(0) - if pagination.Marker != "" { - for i, item := range data { - id, _ := item["id"].(string) - if id == pagination.Marker { - startIndex = int64(i) - break - } - } - } - - previousIndex := startIndex - limit - if previousIndex <= 0 { - previousIndex = 0 - } - nextIndex := startIndex + limit - if nextIndex > int64(len(data)) { - nextIndex = int64(len(data)) - } - - if previousIndex < startIndex { - pagination.Previous, _ = data[previousIndex]["id"].(string) - } - - if nextIndex > startIndex && nextIndex < int64(len(data)) { - pagination.Next, _ = data[nextIndex]["id"].(string) - } - - if startIndex > 0 || nextIndex < int64(len(data)) { - pagination.Partial = true - } - - if pagination.Partial { - pagination.First, _ = data[0]["id"].(string) - - lastIndex := int64(len(data)) - limit - if lastIndex > 0 && lastIndex < int64(len(data)) { - pagination.Last, _ = data[lastIndex]["id"].(string) - } - } - - return data[startIndex:nextIndex] -} diff --git a/vendor/github.com/rancher/norman/api/handler/update.go b/vendor/github.com/rancher/norman/api/handler/update.go deleted file mode 100644 index 12001f6a27..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/update.go +++ /dev/null @@ -1,28 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" -) - -func UpdateHandler(apiContext *types.APIContext, next types.RequestHandler) error { - data, err := ParseAndValidateBody(apiContext, false) - if err != nil { - return err - } - - store := apiContext.Schema.Store - if store == nil { - return httperror.NewAPIError(httperror.NotFound, "no store found") - } - - data, err = store.Update(apiContext, apiContext.Schema, data, apiContext.ID) - if err != nil { - return err - } - - apiContext.WriteResponse(http.StatusOK, data) - return nil -} diff --git a/vendor/github.com/rancher/norman/api/handler/validate.go b/vendor/github.com/rancher/norman/api/handler/validate.go deleted file mode 100644 index 4619d9ce2b..0000000000 --- a/vendor/github.com/rancher/norman/api/handler/validate.go +++ /dev/null @@ -1,59 +0,0 @@ -package handler - -import ( - "github.com/rancher/norman/parse" - "github.com/rancher/norman/parse/builder" - "github.com/rancher/norman/types" -) - -func ParseAndValidateBody(apiContext *types.APIContext, create bool) (map[string]interface{}, error) { - data, err := parse.Body(apiContext.Request) - if err != nil { - return nil, err - } - - if create { - for key, value := range apiContext.SubContextAttributeProvider.Create(apiContext, apiContext.Schema) { - if data == nil { - data = map[string]interface{}{} - } - data[key] = value - } - } - - b := builder.NewBuilder(apiContext) - - op := builder.Create - if !create { - op = builder.Update - } - if apiContext.Schema.InputFormatter != nil { - err = apiContext.Schema.InputFormatter(apiContext, apiContext.Schema, data, create) - if err != nil { - return nil, err - } - } - data, err = b.Construct(apiContext.Schema, data, op) - if err != nil { - return nil, err - } - - return data, nil -} - -func ParseAndValidateActionBody(apiContext *types.APIContext, actionInputSchema *types.Schema) (map[string]interface{}, error) { - data, err := parse.Body(apiContext.Request) - if err != nil { - return nil, err - } - - b := builder.NewBuilder(apiContext) - - op := builder.Create - data, err = b.Construct(actionInputSchema, data, op) - if err != nil { - return nil, err - } - - return data, nil -} diff --git a/vendor/github.com/rancher/norman/api/server.go b/vendor/github.com/rancher/norman/api/server.go deleted file mode 100644 index 66fdd8e224..0000000000 --- a/vendor/github.com/rancher/norman/api/server.go +++ /dev/null @@ -1,277 +0,0 @@ -package api - -import ( - "net/http" - "sync" - - "github.com/rancher/norman/api/access" - "github.com/rancher/norman/api/builtin" - "github.com/rancher/norman/api/handler" - "github.com/rancher/norman/api/writer" - "github.com/rancher/norman/authorization" - "github.com/rancher/norman/httperror" - ehandler "github.com/rancher/norman/httperror/handler" - "github.com/rancher/norman/parse" - "github.com/rancher/norman/store/wrapper" - "github.com/rancher/norman/types" -) - -type StoreWrapper func(types.Store) types.Store - -type Parser func(rw http.ResponseWriter, req *http.Request) (*types.APIContext, error) - -type Server struct { - initBuiltin sync.Once - IgnoreBuiltin bool - Parser Parser - Resolver parse.ResolverFunc - SubContextAttributeProvider types.SubContextAttributeProvider - ResponseWriters map[string]ResponseWriter - Schemas *types.Schemas - QueryFilter types.QueryFilter - StoreWrapper StoreWrapper - URLParser parse.URLParser - Defaults Defaults - AccessControl types.AccessControl -} - -type Defaults struct { - ActionHandler types.ActionHandler - ListHandler types.RequestHandler - LinkHandler types.RequestHandler - CreateHandler types.RequestHandler - DeleteHandler types.RequestHandler - UpdateHandler types.RequestHandler - Store types.Store - ErrorHandler types.ErrorHandler -} - -func NewAPIServer() *Server { - s := &Server{ - Schemas: types.NewSchemas(), - ResponseWriters: map[string]ResponseWriter{ - "json": &writer.EncodingResponseWriter{ - ContentType: "application/json", - Encoder: types.JSONEncoder, - }, - "html": &writer.HTMLResponseWriter{ - EncodingResponseWriter: writer.EncodingResponseWriter{ - Encoder: types.JSONEncoder, - ContentType: "application/json", - }, - }, - "yaml": &writer.EncodingResponseWriter{ - ContentType: "application/yaml", - Encoder: types.YAMLEncoder, - }, - }, - SubContextAttributeProvider: &parse.DefaultSubContextAttributeProvider{}, - Resolver: parse.DefaultResolver, - AccessControl: &authorization.AllAccess{}, - Defaults: Defaults{ - CreateHandler: handler.CreateHandler, - DeleteHandler: handler.DeleteHandler, - UpdateHandler: handler.UpdateHandler, - ListHandler: handler.ListHandler, - LinkHandler: func(*types.APIContext, types.RequestHandler) error { - return httperror.NewAPIError(httperror.NotFound, "Link not found") - }, - ErrorHandler: ehandler.ErrorHandler, - }, - StoreWrapper: wrapper.Wrap, - URLParser: parse.DefaultURLParser, - QueryFilter: handler.QueryFilter, - } - - s.Schemas.AddHook = s.setupDefaults - s.Parser = s.parser - return s -} - -func (s *Server) parser(rw http.ResponseWriter, req *http.Request) (*types.APIContext, error) { - ctx, err := parse.Parse(rw, req, s.Schemas, s.URLParser, s.Resolver) - ctx.ResponseWriter = s.ResponseWriters[ctx.ResponseFormat] - if ctx.ResponseWriter == nil { - ctx.ResponseWriter = s.ResponseWriters["json"] - } - - if ctx.QueryFilter == nil { - ctx.QueryFilter = s.QueryFilter - } - - if ctx.SubContextAttributeProvider == nil { - ctx.SubContextAttributeProvider = s.SubContextAttributeProvider - } - - ctx.AccessControl = s.AccessControl - - return ctx, err -} - -func (s *Server) AddSchemas(schemas *types.Schemas) error { - if schemas.Err() != nil { - return schemas.Err() - } - - s.initBuiltin.Do(func() { - if s.IgnoreBuiltin { - return - } - for _, schema := range builtin.Schemas.Schemas() { - s.Schemas.AddSchema(*schema) - } - }) - - for _, schema := range schemas.Schemas() { - s.Schemas.AddSchema(*schema) - } - - return s.Schemas.Err() -} - -func (s *Server) setupDefaults(schema *types.Schema) { - if schema.ActionHandler == nil { - schema.ActionHandler = s.Defaults.ActionHandler - } - - if schema.Store == nil { - schema.Store = s.Defaults.Store - } - - if schema.ListHandler == nil { - schema.ListHandler = s.Defaults.ListHandler - } - - if schema.LinkHandler == nil { - schema.LinkHandler = s.Defaults.LinkHandler - } - - if schema.CreateHandler == nil { - schema.CreateHandler = s.Defaults.CreateHandler - } - - if schema.UpdateHandler == nil { - schema.UpdateHandler = s.Defaults.UpdateHandler - } - - if schema.DeleteHandler == nil { - schema.DeleteHandler = s.Defaults.DeleteHandler - } - - if schema.ErrorHandler == nil { - schema.ErrorHandler = s.Defaults.ErrorHandler - } - - if schema.Store != nil && s.StoreWrapper != nil { - schema.Store = s.StoreWrapper(schema.Store) - } -} - -func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - if apiResponse, err := s.handle(rw, req); err != nil { - s.handleError(apiResponse, err) - } -} - -func (s *Server) handle(rw http.ResponseWriter, req *http.Request) (*types.APIContext, error) { - apiRequest, err := s.Parser(rw, req) - if err != nil { - return apiRequest, err - } - - if err := CheckCSRF(apiRequest); err != nil { - return apiRequest, err - } - - action, err := ValidateAction(apiRequest) - if err != nil { - return apiRequest, err - } - - if apiRequest.Schema == nil { - return apiRequest, nil - } - - if action == nil && apiRequest.Type != "" { - var handler types.RequestHandler - var nextHandler types.RequestHandler - if apiRequest.Link == "" { - switch apiRequest.Method { - case http.MethodGet: - if apiRequest.ID == "" { - if err := apiRequest.AccessControl.CanList(apiRequest, apiRequest.Schema); err != nil { - return apiRequest, err - } - } else { - if err := apiRequest.AccessControl.CanGet(apiRequest, apiRequest.Schema); err != nil { - return apiRequest, err - } - } - handler = apiRequest.Schema.ListHandler - nextHandler = s.Defaults.ListHandler - case http.MethodPost: - if err := apiRequest.AccessControl.CanCreate(apiRequest, apiRequest.Schema); err != nil { - return apiRequest, err - } - handler = apiRequest.Schema.CreateHandler - nextHandler = s.Defaults.CreateHandler - case http.MethodPut: - if err := apiRequest.AccessControl.CanUpdate(apiRequest, nil, apiRequest.Schema); err != nil { - return apiRequest, err - } - handler = apiRequest.Schema.UpdateHandler - nextHandler = s.Defaults.UpdateHandler - case http.MethodDelete: - if err := apiRequest.AccessControl.CanDelete(apiRequest, nil, apiRequest.Schema); err != nil { - return apiRequest, err - } - handler = apiRequest.Schema.DeleteHandler - nextHandler = s.Defaults.DeleteHandler - } - } else { - handler = apiRequest.Schema.ListHandler - nextHandler = s.Defaults.ListHandler - } - - if handler == nil { - return apiRequest, httperror.NewAPIError(httperror.NotFound, "") - } - - return apiRequest, handler(apiRequest, nextHandler) - } else if action != nil { - return apiRequest, handleAction(action, apiRequest) - } - - return apiRequest, nil -} - -func handleAction(action *types.Action, context *types.APIContext) error { - if context.ID != "" { - if err := access.ByID(context, context.Version, context.Type, context.ID, nil); err != nil { - return err - } - } - return context.Schema.ActionHandler(context.Action, action, context) -} - -func (s *Server) handleError(apiRequest *types.APIContext, err error) { - if apiRequest.Schema == nil { - s.Defaults.ErrorHandler(apiRequest, err) - } else if apiRequest.Schema.ErrorHandler != nil { - apiRequest.Schema.ErrorHandler(apiRequest, err) - } -} - -func (s *Server) CustomAPIUIResponseWriter(cssURL, jsURL, version writer.StringGetter) { - wi, ok := s.ResponseWriters["html"] - if !ok { - return - } - w, ok := wi.(*writer.HTMLResponseWriter) - if !ok { - return - } - w.CSSURL = cssURL - w.JSURL = jsURL - w.APIUIVersion = version -} diff --git a/vendor/github.com/rancher/norman/api/types.go b/vendor/github.com/rancher/norman/api/types.go deleted file mode 100644 index 032f6dc4a0..0000000000 --- a/vendor/github.com/rancher/norman/api/types.go +++ /dev/null @@ -1,7 +0,0 @@ -package api - -import "github.com/rancher/norman/types" - -type ResponseWriter interface { - Write(apiContext *types.APIContext, code int, obj interface{}) -} diff --git a/vendor/github.com/rancher/norman/api/validate.go b/vendor/github.com/rancher/norman/api/validate.go deleted file mode 100644 index 0a27d62a95..0000000000 --- a/vendor/github.com/rancher/norman/api/validate.go +++ /dev/null @@ -1,83 +0,0 @@ -package api - -import ( - "crypto/rand" - "encoding/hex" - "fmt" - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/parse" - "github.com/rancher/norman/types" -) - -const ( - csrfCookie = "CSRF" - csrfHeader = "X-API-CSRF" -) - -func ValidateAction(request *types.APIContext) (*types.Action, error) { - if request.Action == "" || request.Link != "" || request.Method != http.MethodPost { - return nil, nil - } - - actions := request.Schema.CollectionActions - if request.ID != "" { - actions = request.Schema.ResourceActions - } - - action, ok := actions[request.Action] - if !ok { - return nil, httperror.NewAPIError(httperror.InvalidAction, fmt.Sprintf("Invalid action: %s", request.Action)) - } - - if request.ID != "" && request.ReferenceValidator != nil { - resource := request.ReferenceValidator.Lookup(request.Type, request.ID) - if resource == nil { - return nil, httperror.NewAPIError(httperror.NotFound, fmt.Sprintf("Failed to find type: %s id: %s", request.Type, request.ID)) - } - - if _, ok := resource.Actions[request.Action]; !ok { - return nil, httperror.NewAPIError(httperror.InvalidAction, fmt.Sprintf("Invalid action: %s", request.Action)) - } - } - - return &action, nil -} - -func CheckCSRF(apiContext *types.APIContext) error { - if !parse.IsBrowser(apiContext.Request, false) { - return nil - } - - cookie, err := apiContext.Request.Cookie(csrfCookie) - if err == http.ErrNoCookie { - bytes := make([]byte, 5) - _, err := rand.Read(bytes) - if err != nil { - return httperror.WrapAPIError(err, httperror.ServerError, "Failed in CSRF processing") - } - - cookie = &http.Cookie{ - Name: csrfCookie, - Value: hex.EncodeToString(bytes), - } - } else if err != nil { - return httperror.NewAPIError(httperror.InvalidCSRFToken, "Failed to parse cookies") - } else if apiContext.Method != http.MethodGet { - /* - * Very important to use apiContext.Method and not apiContext.Request.Method. The client can override the HTTP method with _method - */ - if cookie.Value == apiContext.Request.Header.Get(csrfHeader) { - // Good - } else if cookie.Value == apiContext.Request.URL.Query().Get(csrfCookie) { - // Good - } else { - return httperror.NewAPIError(httperror.InvalidCSRFToken, "Invalid CSRF token") - } - } - - cookie.Path = "/" - http.SetCookie(apiContext.Response, cookie) - return nil -} diff --git a/vendor/github.com/rancher/norman/api/writer/headers.go b/vendor/github.com/rancher/norman/api/writer/headers.go deleted file mode 100644 index ed3980162a..0000000000 --- a/vendor/github.com/rancher/norman/api/writer/headers.go +++ /dev/null @@ -1,30 +0,0 @@ -package writer - -import ( - "github.com/rancher/norman/api/builtin" - "github.com/rancher/norman/types" -) - -func AddCommonResponseHeader(apiContext *types.APIContext) error { - addExpires(apiContext) - return addSchemasHeader(apiContext) -} - -func addSchemasHeader(apiContext *types.APIContext) error { - schema := apiContext.Schemas.Schema(&builtin.Version, "schema") - if schema == nil { - return nil - } - - version := apiContext.SchemasVersion - if version == nil { - version = apiContext.Version - } - - apiContext.Response.Header().Set("X-Api-Schemas", apiContext.URLBuilder.Collection(schema, version)) - return nil -} - -func addExpires(apiContext *types.APIContext) { - apiContext.Response.Header().Set("Expires", "Wed 24 Feb 1982 18:42:00 GMT") -} diff --git a/vendor/github.com/rancher/norman/api/writer/html.go b/vendor/github.com/rancher/norman/api/writer/html.go deleted file mode 100644 index c77adefb5c..0000000000 --- a/vendor/github.com/rancher/norman/api/writer/html.go +++ /dev/null @@ -1,74 +0,0 @@ -package writer - -import ( - "strings" - - "github.com/rancher/norman/api/builtin" - "github.com/rancher/norman/types" -) - -const ( - JSURL = "https://releases.rancher.com/api-ui/%API_UI_VERSION%/ui.min.js" - CSSURL = "https://releases.rancher.com/api-ui/%API_UI_VERSION%/ui.min.css" - DefaultVersion = "1.1.6" -) - -var ( - start = ` - - - - - -`) -) - -type StringGetter func() string - -type HTMLResponseWriter struct { - EncodingResponseWriter - CSSURL StringGetter - JSURL StringGetter - APIUIVersion StringGetter -} - -func (h *HTMLResponseWriter) start(apiContext *types.APIContext, code int, obj interface{}) { - AddCommonResponseHeader(apiContext) - apiContext.Response.Header().Set("content-type", "text/html") - apiContext.Response.WriteHeader(code) -} - -func (h *HTMLResponseWriter) Write(apiContext *types.APIContext, code int, obj interface{}) { - h.start(apiContext, code, obj) - schemaSchema := apiContext.Schemas.Schema(&builtin.Version, "schema") - headerString := start - if schemaSchema != nil { - headerString = strings.Replace(headerString, "%SCHEMAS%", apiContext.URLBuilder.Collection(schemaSchema, apiContext.Version), 1) - } - var jsurl, cssurl string - if h.CSSURL != nil && h.JSURL != nil && h.CSSURL() != "" && h.JSURL() != "" { - jsurl = h.JSURL() - cssurl = h.CSSURL() - } else if h.APIUIVersion != nil && h.APIUIVersion() != "" { - jsurl = strings.Replace(JSURL, "%API_UI_VERSION%", h.APIUIVersion(), 1) - cssurl = strings.Replace(CSSURL, "%API_UI_VERSION%", h.APIUIVersion(), 1) - } else { - jsurl = strings.Replace(JSURL, "%API_UI_VERSION%", DefaultVersion, 1) - cssurl = strings.Replace(CSSURL, "%API_UI_VERSION%", DefaultVersion, 1) - } - headerString = strings.Replace(headerString, "%JSURL%", jsurl, 1) - headerString = strings.Replace(headerString, "%CSSURL%", cssurl, 1) - - apiContext.Response.Write([]byte(headerString)) - h.Body(apiContext, apiContext.Response, obj) - if schemaSchema != nil { - apiContext.Response.Write(end) - } -} diff --git a/vendor/github.com/rancher/norman/api/writer/json.go b/vendor/github.com/rancher/norman/api/writer/json.go deleted file mode 100644 index 4fb61fa5bb..0000000000 --- a/vendor/github.com/rancher/norman/api/writer/json.go +++ /dev/null @@ -1,234 +0,0 @@ -package writer - -import ( - "fmt" - "io" - "net/http" - - "github.com/rancher/norman/parse" - "github.com/rancher/norman/parse/builder" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/definition" - "github.com/sirupsen/logrus" -) - -type EncodingResponseWriter struct { - ContentType string - Encoder func(io.Writer, interface{}) error -} - -func (j *EncodingResponseWriter) start(apiContext *types.APIContext, code int, obj interface{}) { - AddCommonResponseHeader(apiContext) - apiContext.Response.Header().Set("content-type", j.ContentType) - apiContext.Response.WriteHeader(code) -} - -func (j *EncodingResponseWriter) Write(apiContext *types.APIContext, code int, obj interface{}) { - j.start(apiContext, code, obj) - j.Body(apiContext, apiContext.Response, obj) -} - -func (j *EncodingResponseWriter) Body(apiContext *types.APIContext, writer io.Writer, obj interface{}) error { - return j.VersionBody(apiContext, apiContext.Version, writer, obj) - -} - -func (j *EncodingResponseWriter) VersionBody(apiContext *types.APIContext, version *types.APIVersion, writer io.Writer, obj interface{}) error { - var output interface{} - - builder := builder.NewBuilder(apiContext) - builder.Version = version - - switch v := obj.(type) { - case []interface{}: - output = j.writeInterfaceSlice(builder, apiContext, v) - case []map[string]interface{}: - output = j.writeMapSlice(builder, apiContext, v) - case map[string]interface{}: - output = j.convert(builder, apiContext, v) - case types.RawResource: - output = v - } - - if output != nil { - return j.Encoder(writer, output) - } - - return nil -} -func (j *EncodingResponseWriter) writeMapSlice(builder *builder.Builder, apiContext *types.APIContext, input []map[string]interface{}) *types.GenericCollection { - collection := newCollection(apiContext) - for _, value := range input { - converted := j.convert(builder, apiContext, value) - if converted != nil { - collection.Data = append(collection.Data, converted) - } - } - - if apiContext.Schema.CollectionFormatter != nil { - apiContext.Schema.CollectionFormatter(apiContext, collection) - } - - return collection -} - -func (j *EncodingResponseWriter) writeInterfaceSlice(builder *builder.Builder, apiContext *types.APIContext, input []interface{}) *types.GenericCollection { - collection := newCollection(apiContext) - for _, value := range input { - switch v := value.(type) { - case map[string]interface{}: - converted := j.convert(builder, apiContext, v) - if converted != nil { - collection.Data = append(collection.Data, converted) - } - default: - collection.Data = append(collection.Data, v) - } - } - - if apiContext.Schema.CollectionFormatter != nil { - apiContext.Schema.CollectionFormatter(apiContext, collection) - } - - return collection -} - -func toString(val interface{}) string { - if val == nil { - return "" - } - return fmt.Sprint(val) -} - -func (j *EncodingResponseWriter) convert(b *builder.Builder, context *types.APIContext, input map[string]interface{}) *types.RawResource { - schema := context.Schemas.Schema(context.Version, definition.GetFullType(input)) - if schema == nil { - return nil - } - op := builder.List - if context.Method == http.MethodPost { - op = builder.ListForCreate - } - data, err := b.Construct(schema, input, op) - if err != nil { - logrus.Errorf("Failed to construct object on output: %v", err) - return nil - } - - rawResource := &types.RawResource{ - ID: toString(input["id"]), - Type: schema.ID, - Schema: schema, - Links: map[string]string{}, - Actions: map[string]string{}, - Values: data, - ActionLinks: context.Request.Header.Get("X-API-Action-Links") != "", - } - - j.addLinks(b, schema, context, input, rawResource) - - if schema.Formatter != nil { - schema.Formatter(context, rawResource) - } - - return rawResource -} - -func (j *EncodingResponseWriter) addLinks(b *builder.Builder, schema *types.Schema, context *types.APIContext, input map[string]interface{}, rawResource *types.RawResource) { - if rawResource.ID == "" { - return - } - - self := context.URLBuilder.ResourceLink(rawResource) - rawResource.Links["self"] = self - if context.AccessControl.CanUpdate(context, input, schema) == nil { - rawResource.Links["update"] = self - } - if context.AccessControl.CanDelete(context, input, schema) == nil { - rawResource.Links["remove"] = self - } - - subContextVersion := context.Schemas.SubContextVersionForSchema(schema) - for _, backRef := range context.Schemas.References(schema) { - if backRef.Schema.CanList(context) != nil { - continue - } - - if subContextVersion == nil { - rawResource.Links[backRef.Schema.PluralName] = context.URLBuilder.FilterLink(backRef.Schema, backRef.FieldName, rawResource.ID) - } else { - rawResource.Links[backRef.Schema.PluralName] = context.URLBuilder.SubContextCollection(schema, rawResource.ID, backRef.Schema) - } - } - - if subContextVersion != nil { - for _, subSchema := range context.Schemas.SchemasForVersion(*subContextVersion) { - if subSchema.CanList(context) == nil { - rawResource.Links[subSchema.PluralName] = context.URLBuilder.SubContextCollection(schema, rawResource.ID, subSchema) - } - } - } -} - -func newCollection(apiContext *types.APIContext) *types.GenericCollection { - result := &types.GenericCollection{ - Collection: types.Collection{ - Type: "collection", - ResourceType: apiContext.Type, - CreateTypes: map[string]string{}, - Links: map[string]string{ - "self": apiContext.URLBuilder.Current(), - }, - Actions: map[string]string{}, - }, - Data: []interface{}{}, - } - - if apiContext.Method == http.MethodGet { - if apiContext.AccessControl.CanCreate(apiContext, apiContext.Schema) == nil { - result.CreateTypes[apiContext.Schema.ID] = apiContext.URLBuilder.Collection(apiContext.Schema, apiContext.Version) - } - } - - opts := parse.QueryOptions(apiContext, apiContext.Schema) - result.Sort = &opts.Sort - result.Sort.Reverse = apiContext.URLBuilder.ReverseSort(result.Sort.Order) - result.Sort.Links = map[string]string{} - result.Pagination = opts.Pagination - result.Filters = map[string][]types.Condition{} - - for _, cond := range opts.Conditions { - filters := result.Filters[cond.Field] - result.Filters[cond.Field] = append(filters, cond.ToCondition()) - } - - for name := range apiContext.Schema.CollectionFilters { - if _, ok := result.Filters[name]; !ok { - result.Filters[name] = nil - } - } - - for queryField := range apiContext.Schema.CollectionFilters { - field, ok := apiContext.Schema.ResourceFields[queryField] - if ok && (field.Type == "string" || field.Type == "enum") { - result.Sort.Links[queryField] = apiContext.URLBuilder.Sort(queryField) - } - } - - if result.Pagination != nil && result.Pagination.Partial { - if result.Pagination.Next != "" { - result.Pagination.Next = apiContext.URLBuilder.Marker(result.Pagination.Next) - } - if result.Pagination.Previous != "" { - result.Pagination.Previous = apiContext.URLBuilder.Marker(result.Pagination.Previous) - } - if result.Pagination.First != "" { - result.Pagination.First = apiContext.URLBuilder.Marker(result.Pagination.First) - } - if result.Pagination.Last != "" { - result.Pagination.Last = apiContext.URLBuilder.Marker(result.Pagination.Last) - } - } - - return result -} diff --git a/vendor/github.com/rancher/norman/authorization/all.go b/vendor/github.com/rancher/norman/authorization/all.go deleted file mode 100644 index 9eac12f90f..0000000000 --- a/vendor/github.com/rancher/norman/authorization/all.go +++ /dev/null @@ -1,62 +0,0 @@ -package authorization - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/slice" -) - -type AllAccess struct { -} - -func (*AllAccess) CanCreate(apiContext *types.APIContext, schema *types.Schema) error { - if slice.ContainsString(schema.CollectionMethods, http.MethodPost) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not create "+schema.ID) -} - -func (*AllAccess) CanGet(apiContext *types.APIContext, schema *types.Schema) error { - if slice.ContainsString(schema.ResourceMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not get "+schema.ID) -} - -func (*AllAccess) CanList(apiContext *types.APIContext, schema *types.Schema) error { - if slice.ContainsString(schema.CollectionMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not list "+schema.ID) -} - -func (*AllAccess) CanUpdate(apiContext *types.APIContext, obj map[string]interface{}, schema *types.Schema) error { - if slice.ContainsString(schema.ResourceMethods, http.MethodPut) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not update "+schema.ID) -} - -func (*AllAccess) CanDelete(apiContext *types.APIContext, obj map[string]interface{}, schema *types.Schema) error { - if slice.ContainsString(schema.ResourceMethods, http.MethodDelete) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not delete "+schema.ID) -} - -func (*AllAccess) CanDo(apiGroup, resource, verb string, apiContext *types.APIContext, obj map[string]interface{}, schema *types.Schema) error { - if slice.ContainsString(schema.ResourceMethods, verb) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not perform "+verb+" "+schema.ID) -} - -func (*AllAccess) Filter(apiContext *types.APIContext, schema *types.Schema, obj map[string]interface{}, context map[string]string) map[string]interface{} { - return obj -} - -func (*AllAccess) FilterList(apiContext *types.APIContext, schema *types.Schema, obj []map[string]interface{}, context map[string]string) []map[string]interface{} { - return obj -} diff --git a/vendor/github.com/rancher/norman/build.go b/vendor/github.com/rancher/norman/build.go deleted file mode 100644 index c169405727..0000000000 --- a/vendor/github.com/rancher/norman/build.go +++ /dev/null @@ -1,244 +0,0 @@ -package norman - -import ( - "context" - "errors" - "fmt" - "os" - - "github.com/rancher/norman/api" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/leader" - "github.com/rancher/norman/store/crd" - "github.com/rancher/norman/store/proxy" - "github.com/rancher/norman/types" - "github.com/sirupsen/logrus" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" -) - -type serverContextKey struct{} - -func GetServer(ctx context.Context) *Server { - return ctx.Value(serverContextKey{}).(*Server) -} - -func (c *Config) Build(ctx context.Context, opts *Options) (context.Context, *Server, error) { - var ( - err error - starters []controller.Starter - ) - - if c.Name == "" { - return ctx, nil, errors.New("name must be set on norman.Config") - } - - if opts == nil { - opts = &Options{} - } - - r := &Runtime{ - AllSchemas: types.NewSchemas(), - } - - server := &Server{ - Config: c, - Runtime: r, - } - - ctx = context.WithValue(ctx, serverContextKey{}, server) - - ctx, err = c.defaults(ctx, r, *opts) - if err != nil { - return ctx, nil, err - } - - for _, schema := range c.Schemas { - r.AllSchemas.AddSchemas(schema) - } - - c.createCRDs(ctx, r) - - ctx, starters, err = c.clients(ctx, r) - if err != nil { - return ctx, nil, err - } - - if c.CustomizeSchemas != nil { - if err := c.CustomizeSchemas(ctx, c.ClientGetter, r.AllSchemas); err != nil { - return ctx, nil, err - } - } - - if c.GlobalSetup != nil { - ctx, err = c.GlobalSetup(ctx) - if err != nil { - return ctx, nil, err - } - } - - if err := c.registerControllers(ctx, c.PerServerControllers); err != nil { - return ctx, nil, err - } - - if c.EnableAPI { - if err := c.apiServer(ctx, r); err != nil { - return ctx, nil, err - } - } - - if c.PreStart != nil { - if err := c.PreStart(ctx); err != nil { - return ctx, nil, err - } - } - - if !opts.DisableControllers { - err = controller.SyncThenStart(ctx, c.Threadiness, starters...) - go c.masterControllers(ctx, starters, r) - } - - return ctx, server, err -} - -func (c *Config) apiServer(ctx context.Context, r *Runtime) error { - server := api.NewAPIServer() - if err := server.AddSchemas(r.AllSchemas); err != nil { - return err - } - - r.APIHandler = server - - if c.APISetup != nil { - if err := c.APISetup(ctx, server); err != nil { - return err - } - } - - return nil -} - -func (c *Config) registerControllers(ctx context.Context, controllers []ControllerRegister) error { - for _, controller := range controllers { - if err := controller(ctx); err != nil { - return fmt.Errorf("failed to start controller: %v", err) - } - } - - return nil -} - -func (c *Config) masterControllers(ctx context.Context, starters []controller.Starter, r *Runtime) { - f := func(ctx context.Context) { - var ( - err error - ) - - if c.MasterSetup != nil { - ctx, err = c.MasterSetup(ctx) - if err != nil { - logrus.Fatalf("failed to setup master: %v", err) - } - } - - err = c.registerControllers(ctx, c.MasterControllers) - if err != nil { - logrus.Fatalf("failed to register master controllers: %v", err) - } - - if err := controller.SyncThenStart(ctx, c.Threadiness, starters...); err != nil { - logrus.Fatalf("failed to start master controllers: %v", err) - } - - <-ctx.Done() - } - - if c.DisableLeaderElection { - go f(ctx) - } else { - leader.RunOrDie(ctx, c.LeaderLockNamespace, c.Name, c.K8sClient, f) - } -} - -func (c *Config) defaults(ctx context.Context, r *Runtime, opts Options) (context.Context, error) { - var ( - err error - ) - - if c.Threadiness <= 0 { - c.Threadiness = 5 - } - - if opts.KubeConfig != "" { - c.KubeConfig = opts.KubeConfig - } - - if c.Config == nil { - envConfig := os.Getenv("KUBECONFIG") - if c.KubeConfig != "" { - envConfig = c.KubeConfig - } else if c.IgnoredKubeConfigEnv { - envConfig = "" - } - - c.Config, err = clientcmd.BuildConfigFromFlags("", envConfig) - if err != nil { - return ctx, err - } - } - - r.LocalConfig = c.Config - - if c.ClientGetter == nil { - cg, err := proxy.NewClientGetterFromConfig(*c.Config) - if err != nil { - return ctx, err - } - c.ClientGetter = cg - } - - return ctx, nil -} - -func (c *Config) createCRDs(ctx context.Context, r *Runtime) { - factory := &crd.Factory{ClientGetter: c.ClientGetter} - - for version, types := range c.CRDs { - factory.BatchCreateCRDs(ctx, c.CRDStorageContext, r.AllSchemas, version, types...) - } - - factory.BatchWait() -} - -func (c *Config) clients(ctx context.Context, r *Runtime) (context.Context, []controller.Starter, error) { - var ( - starter controller.Starter - starters []controller.Starter - err error - ) - - if c.K8sClient == nil { - c.K8sClient, err = kubernetes.NewForConfig(c.Config) - if err != nil { - return ctx, nil, err - } - } - - if c.APIExtClient == nil { - c.APIExtClient, err = clientset.NewForConfig(c.Config) - if err != nil { - return ctx, nil, err - } - } - - for _, clientFactory := range c.Clients { - ctx, starter, err = clientFactory(ctx, *c.Config) - if err != nil { - return ctx, nil, err - } - starters = append(starters, starter) - } - - return ctx, starters, nil -} diff --git a/vendor/github.com/rancher/norman/controller/cluster_check.go b/vendor/github.com/rancher/norman/controller/cluster_check.go deleted file mode 100644 index 0389ddfd25..0000000000 --- a/vendor/github.com/rancher/norman/controller/cluster_check.go +++ /dev/null @@ -1,73 +0,0 @@ -package controller - -import ( - "reflect" - "strings" -) - -func ObjectInCluster(cluster string, obj interface{}) bool { - var clusterName string - if c := getValue(obj, "ClusterName"); c.IsValid() { - clusterName = c.String() - } - if clusterName == "" { - if c := getValue(obj, "Spec", "ClusterName"); c.IsValid() { - clusterName = c.String() - } - - } - if clusterName == "" { - if c := getValue(obj, "ProjectName"); c.IsValid() { - if parts := strings.SplitN(c.String(), ":", 2); len(parts) == 2 { - clusterName = parts[0] - } - } - } - if clusterName == "" { - if c := getValue(obj, "Spec", "ProjectName"); c.IsValid() { - if parts := strings.SplitN(c.String(), ":", 2); len(parts) == 2 { - clusterName = parts[0] - } - } - } - if clusterName == "" { - if a := getValue(obj, "Annotations"); a.IsValid() { - if c := a.MapIndex(reflect.ValueOf("field.cattle.io/projectId")); c.IsValid() { - if parts := strings.SplitN(c.String(), ":", 2); len(parts) == 2 { - clusterName = parts[0] - } - } - } - } - if clusterName == "" { - if c := getValue(obj, "Namespace"); c.IsValid() { - clusterName = c.String() - } - } - - return clusterName == cluster -} - -func getValue(obj interface{}, name ...string) reflect.Value { - v := reflect.ValueOf(obj) - t := v.Type() - if t.Kind() == reflect.Ptr { - v = v.Elem() - t = v.Type() - } - - field := v.FieldByName(name[0]) - if !field.IsValid() || len(name) == 1 { - return field - } - - return getFieldValue(field, name[1:]...) -} - -func getFieldValue(v reflect.Value, name ...string) reflect.Value { - field := v.FieldByName(name[0]) - if len(name) == 1 { - return field - } - return getFieldValue(field, name[1:]...) -} diff --git a/vendor/github.com/rancher/norman/controller/error.go b/vendor/github.com/rancher/norman/controller/error.go deleted file mode 100644 index 24c829c050..0000000000 --- a/vendor/github.com/rancher/norman/controller/error.go +++ /dev/null @@ -1,10 +0,0 @@ -package controller - -type ForgetError struct { - Err error - Reason string -} - -func (f *ForgetError) Error() string { - return f.Err.Error() -} diff --git a/vendor/github.com/rancher/norman/controller/generic_controller.go b/vendor/github.com/rancher/norman/controller/generic_controller.go deleted file mode 100644 index 919ce0de7a..0000000000 --- a/vendor/github.com/rancher/norman/controller/generic_controller.go +++ /dev/null @@ -1,361 +0,0 @@ -package controller - -import ( - "context" - "fmt" - "reflect" - "strings" - "sync" - "time" - - errors2 "github.com/pkg/errors" - "github.com/rancher/norman/metrics" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/types" - "github.com/sirupsen/logrus" - "golang.org/x/time/rate" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" -) - -var ( - resyncPeriod = 2 * time.Hour -) - -type HandlerFunc func(key string, obj interface{}) (interface{}, error) - -type GenericController interface { - SetThreadinessOverride(count int) - Informer() cache.SharedIndexInformer - AddHandler(ctx context.Context, name string, handler HandlerFunc) - HandlerCount() int - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type Backend interface { - List(opts metav1.ListOptions) (runtime.Object, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - ObjectFactory() objectclient.ObjectFactory -} - -type handlerDef struct { - name string - generation int - handler HandlerFunc -} - -type generationKey struct { - generation int - key string -} - -type genericController struct { - sync.Mutex - threadinessOverride int - generation int - informer cache.SharedIndexInformer - handlers []*handlerDef - queue workqueue.RateLimitingInterface - name string - running bool - synced bool -} - -func NewGenericController(name string, genericClient Backend) GenericController { - informer := cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: genericClient.List, - WatchFunc: genericClient.Watch, - }, - genericClient.ObjectFactory().Object(), resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) - - rl := workqueue.NewMaxOfRateLimiter( - workqueue.NewItemExponentialFailureRateLimiter(500*time.Millisecond, 1000*time.Second), - // 10 qps, 100 bucket size. This is only for retry speed and its only the overall factor (not per item) - &workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)}, - ) - - return &genericController{ - informer: informer, - queue: workqueue.NewNamedRateLimitingQueue(rl, name), - name: name, - } -} - -func (g *genericController) SetThreadinessOverride(count int) { - g.threadinessOverride = count -} - -func (g *genericController) HandlerCount() int { - return len(g.handlers) -} - -func (g *genericController) Informer() cache.SharedIndexInformer { - return g.informer -} - -func (g *genericController) Enqueue(namespace, name string) { - if namespace == "" { - g.queue.Add(name) - } else { - g.queue.Add(namespace + "/" + name) - } -} - -func (g *genericController) AddHandler(ctx context.Context, name string, handler HandlerFunc) { - g.Lock() - h := &handlerDef{ - name: name, - generation: g.generation, - handler: handler, - } - g.handlers = append(g.handlers, h) - g.Unlock() - - go func() { - <-ctx.Done() - g.Lock() - var handlers []*handlerDef - for _, handler := range g.handlers { - if handler != h { - handlers = append(handlers, h) - } - } - g.handlers = handlers - g.Unlock() - }() -} - -func (g *genericController) Sync(ctx context.Context) error { - g.Lock() - defer g.Unlock() - - return g.sync(ctx) -} - -func (g *genericController) sync(ctx context.Context) error { - if g.synced { - return nil - } - - defer utilruntime.HandleCrash() - - g.informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: g.queueObject, - UpdateFunc: func(_, obj interface{}) { - g.queueObject(obj) - }, - DeleteFunc: g.queueObject, - }) - - logrus.Debugf("Syncing %s Controller", g.name) - - go g.informer.Run(ctx.Done()) - - if !cache.WaitForCacheSync(ctx.Done(), g.informer.HasSynced) { - return fmt.Errorf("failed to sync controller %s", g.name) - } - logrus.Debugf("Syncing %s Controller Done", g.name) - - g.synced = true - return nil -} - -func (g *genericController) Start(ctx context.Context, threadiness int) error { - g.Lock() - defer g.Unlock() - - if err := g.sync(ctx); err != nil { - return err - } - - if !g.running { - if g.threadinessOverride > 0 { - threadiness = g.threadinessOverride - } - go g.run(ctx, threadiness) - } - - if g.running { - for _, h := range g.handlers { - if h.generation != g.generation { - continue - } - for _, key := range g.informer.GetStore().ListKeys() { - g.queueObject(generationKey{ - generation: g.generation, - key: key, - }) - } - break - } - } - - g.generation++ - g.running = true - return nil -} - -func (g *genericController) queueObject(obj interface{}) { - if _, ok := obj.(generationKey); ok { - g.queue.Add(obj) - return - } - - key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) - if err == nil { - g.queue.Add(key) - } -} - -func (g *genericController) run(ctx context.Context, threadiness int) { - defer utilruntime.HandleCrash() - defer g.queue.ShutDown() - - for i := 0; i < threadiness; i++ { - go wait.Until(g.runWorker, time.Second, ctx.Done()) - } - - <-ctx.Done() - logrus.Infof("Shutting down %s controller", g.name) -} - -func (g *genericController) runWorker() { - for g.processNextWorkItem() { - } -} - -func (g *genericController) processNextWorkItem() bool { - key, quit := g.queue.Get() - if quit { - return false - } - defer g.queue.Done(key) - - // do your work on the key. This method will contains your "do stuff" logic - err := g.syncHandler(key) - checkErr := err - if handlerErr, ok := checkErr.(*handlerError); ok { - checkErr = handlerErr.err - } - if _, ok := checkErr.(*ForgetError); err == nil || ok { - if ok { - logrus.Debugf("%v %v completed with dropped err: %v", g.name, key, err) - } - g.queue.Forget(key) - return true - } - - if err := filterConflictsError(err); err != nil { - logrus.Errorf("%v %v %v", g.name, key, err) - } - - if gk, ok := key.(generationKey); ok { - g.queue.AddRateLimited(gk.key) - } else { - g.queue.AddRateLimited(key) - } - - return true -} - -func ignoreError(err error, checkString bool) bool { - err = errors2.Cause(err) - if errors.IsConflict(err) { - return true - } - if _, ok := err.(*ForgetError); ok { - return true - } - if checkString { - return strings.HasSuffix(err.Error(), "please apply your changes to the latest version and try again") - } - return false -} - -func filterConflictsError(err error) error { - if ignoreError(err, false) { - return nil - } - - if errs, ok := errors2.Cause(err).(*types.MultiErrors); ok { - var newErrors []error - for _, err := range errs.Errors { - if !ignoreError(err, true) { - newErrors = append(newErrors, err) - } - } - return types.NewErrors(newErrors...) - } - - return err -} - -func (g *genericController) syncHandler(key interface{}) (err error) { - defer utilruntime.RecoverFromPanic(&err) - - generation := -1 - var s string - var obj interface{} - - switch v := key.(type) { - case string: - s = v - case generationKey: - generation = v.generation - s = v.key - default: - return nil - } - - obj, exists, err := g.informer.GetStore().GetByKey(s) - if err != nil { - return err - } else if !exists { - obj = nil - } - - var errs []error - for _, handler := range g.handlers { - if generation > -1 && handler.generation != generation { - continue - } - - logrus.Debugf("%s calling handler %s %s", g.name, handler.name, s) - metrics.IncTotalHandlerExecution(g.name, handler.name) - if newObj, err := handler.handler(s, obj); err != nil { - if !ignoreError(err, false) { - metrics.IncTotalHandlerFailure(g.name, handler.name, s) - } - errs = append(errs, &handlerError{ - name: handler.name, - err: err, - }) - } else if newObj != nil && !reflect.ValueOf(newObj).IsNil() { - obj = newObj - } - } - err = types.NewErrors(errs...) - return -} - -type handlerError struct { - name string - err error -} - -func (h *handlerError) Error() string { - return fmt.Sprintf("[%s] failed with : %v", h.name, h.err) -} - -func (h *handlerError) Cause() error { - return h.err -} diff --git a/vendor/github.com/rancher/norman/generator/client_template.go b/vendor/github.com/rancher/norman/generator/client_template.go deleted file mode 100644 index b7c673a886..0000000000 --- a/vendor/github.com/rancher/norman/generator/client_template.go +++ /dev/null @@ -1,31 +0,0 @@ -package generator - -var clientTemplate = `package client - -import ( - "github.com/rancher/norman/clientbase" -) - -type Client struct { - clientbase.APIBaseClient - - {{range .schemas}} - {{- if . | hasGet }}{{.CodeName}} {{.CodeName}}Operations -{{end}}{{end}}} - -func NewClient(opts *clientbase.ClientOpts) (*Client, error) { - baseClient, err := clientbase.NewAPIClient(opts) - if err != nil { - return nil, err - } - - client := &Client{ - APIBaseClient: baseClient, - } - - {{range .schemas}} - {{- if . | hasGet }}client.{{.CodeName}} = new{{.CodeName}}Client(client) -{{end}}{{end}} - return client, nil -} -` diff --git a/vendor/github.com/rancher/norman/generator/controller_template.go b/vendor/github.com/rancher/norman/generator/controller_template.go deleted file mode 100644 index 081d9557d9..0000000000 --- a/vendor/github.com/rancher/norman/generator/controller_template.go +++ /dev/null @@ -1,448 +0,0 @@ -package generator - -var controllerTemplate = `package {{.schema.Version.Version}} - -import ( - "context" - - {{.importPackage}} - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/controller" - "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/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -var ( - {{.schema.CodeName}}GroupVersionKind = schema.GroupVersionKind{ - Version: Version, - Group: GroupName, - Kind: "{{.schema.CodeName}}", - } - {{.schema.CodeName}}Resource = metav1.APIResource{ - Name: "{{.schema.PluralName | toLower}}", - SingularName: "{{.schema.ID | toLower}}", -{{- if eq .schema.Scope "namespace" }} - Namespaced: true, -{{ else }} - Namespaced: false, -{{- end }} - Kind: {{.schema.CodeName}}GroupVersionKind.Kind, - } -) - -func New{{.schema.CodeName}}(namespace, name string, obj {{.prefix}}{{.schema.CodeName}}) *{{.prefix}}{{.schema.CodeName}} { - obj.APIVersion, obj.Kind = {{.schema.CodeName}}GroupVersionKind.ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -type {{.schema.CodeName}}List struct { - metav1.TypeMeta %BACK%json:",inline"%BACK% - metav1.ListMeta %BACK%json:"metadata,omitempty"%BACK% - Items []{{.prefix}}{{.schema.CodeName}} -} - -type {{.schema.CodeName}}HandlerFunc func(key string, obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) - -type {{.schema.CodeName}}ChangeHandlerFunc func(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) - -type {{.schema.CodeName}}Lister interface { - List(namespace string, selector labels.Selector) (ret []*{{.prefix}}{{.schema.CodeName}}, err error) - Get(namespace, name string) (*{{.prefix}}{{.schema.CodeName}}, error) -} - -type {{.schema.CodeName}}Controller interface { - Generic() controller.GenericController - Informer() cache.SharedIndexInformer - Lister() {{.schema.CodeName}}Lister - AddHandler(ctx context.Context, name string, handler {{.schema.CodeName}}HandlerFunc) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, handler {{.schema.CodeName}}HandlerFunc) - Enqueue(namespace, name string) - Sync(ctx context.Context) error - Start(ctx context.Context, threadiness int) error -} - -type {{.schema.CodeName}}Interface interface { - ObjectClient() *objectclient.ObjectClient - Create(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) - Get(name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) - Update(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (*{{.schema.CodeName}}List, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error - Controller() {{.schema.CodeName}}Controller - AddHandler(ctx context.Context, name string, sync {{.schema.CodeName}}HandlerFunc) - AddLifecycle(ctx context.Context, name string, lifecycle {{.schema.CodeName}}Lifecycle) - AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync {{.schema.CodeName}}HandlerFunc) - AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle {{.schema.CodeName}}Lifecycle) -} - -type {{.schema.ID}}Lister struct { - controller *{{.schema.ID}}Controller -} - -func (l *{{.schema.ID}}Lister) List(namespace string, selector labels.Selector) (ret []*{{.prefix}}{{.schema.CodeName}}, err error) { - err = cache.ListAllByNamespace(l.controller.Informer().GetIndexer(), namespace, selector, func(obj interface{}) { - ret = append(ret, obj.(*{{.prefix}}{{.schema.CodeName}})) - }) - return -} - -func (l *{{.schema.ID}}Lister) Get(namespace, name string) (*{{.prefix}}{{.schema.CodeName}}, error) { - var key string - if namespace != "" { - key = namespace + "/" + name - } else { - key = name - } - obj, exists, err := l.controller.Informer().GetIndexer().GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(schema.GroupResource{ - Group: {{.schema.CodeName}}GroupVersionKind.Group, - Resource: "{{.schema.ID}}", - }, key) - } - return obj.(*{{.prefix}}{{.schema.CodeName}}), nil -} - -type {{.schema.ID}}Controller struct { - controller.GenericController -} - -func (c *{{.schema.ID}}Controller) Generic() controller.GenericController { - return c.GenericController -} - -func (c *{{.schema.ID}}Controller) Lister() {{.schema.CodeName}}Lister { - return &{{.schema.ID}}Lister{ - controller: c, - } -} - - -func (c *{{.schema.ID}}Controller) AddHandler(ctx context.Context, name string, handler {{.schema.CodeName}}HandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*{{.prefix}}{{.schema.CodeName}}); ok { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -func (c *{{.schema.ID}}Controller) AddClusterScopedHandler(ctx context.Context, name, cluster string, handler {{.schema.CodeName}}HandlerFunc) { - c.GenericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - if obj == nil { - return handler(key, nil) - } else if v, ok := obj.(*{{.prefix}}{{.schema.CodeName}}); ok && controller.ObjectInCluster(cluster, obj) { - return handler(key, v) - } else { - return nil, nil - } - }) -} - -type {{.schema.ID}}Factory struct { -} - -func (c {{.schema.ID}}Factory) Object() runtime.Object { - return &{{.prefix}}{{.schema.CodeName}}{} -} - -func (c {{.schema.ID}}Factory) List() runtime.Object { - return &{{.schema.CodeName}}List{} -} - -func (s *{{.schema.ID}}Client) Controller() {{.schema.CodeName}}Controller { - s.client.Lock() - defer s.client.Unlock() - - c, ok := s.client.{{.schema.ID}}Controllers[s.ns] - if ok { - return c - } - - genericController := controller.NewGenericController({{.schema.CodeName}}GroupVersionKind.Kind+"Controller", - s.objectClient) - - c = &{{.schema.ID}}Controller{ - GenericController: genericController, - } - - s.client.{{.schema.ID}}Controllers[s.ns] = c - s.client.starters = append(s.client.starters, c) - - return c -} - -type {{.schema.ID}}Client struct { - client *Client - ns string - objectClient *objectclient.ObjectClient - controller {{.schema.CodeName}}Controller -} - -func (s *{{.schema.ID}}Client) ObjectClient() *objectclient.ObjectClient { - return s.objectClient -} - -func (s *{{.schema.ID}}Client) Create(o *{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) { - obj, err := s.objectClient.Create(o) - return obj.(*{{.prefix}}{{.schema.CodeName}}), err -} - -func (s *{{.schema.ID}}Client) Get(name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) { - obj, err := s.objectClient.Get(name, opts) - return obj.(*{{.prefix}}{{.schema.CodeName}}), err -} - -func (s *{{.schema.ID}}Client) GetNamespaced(namespace, name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) { - obj, err := s.objectClient.GetNamespaced(namespace, name, opts) - return obj.(*{{.prefix}}{{.schema.CodeName}}), err -} - -func (s *{{.schema.ID}}Client) Update(o *{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) { - obj, err := s.objectClient.Update(o.Name, o) - return obj.(*{{.prefix}}{{.schema.CodeName}}), err -} - -func (s *{{.schema.ID}}Client) Delete(name string, options *metav1.DeleteOptions) error { - return s.objectClient.Delete(name, options) -} - -func (s *{{.schema.ID}}Client) DeleteNamespaced(namespace, name string, options *metav1.DeleteOptions) error { - return s.objectClient.DeleteNamespaced(namespace, name, options) -} - -func (s *{{.schema.ID}}Client) List(opts metav1.ListOptions) (*{{.schema.CodeName}}List, error) { - obj, err := s.objectClient.List(opts) - return obj.(*{{.schema.CodeName}}List), err -} - -func (s *{{.schema.ID}}Client) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return s.objectClient.Watch(opts) -} - -// Patch applies the patch and returns the patched deployment. -func (s *{{.schema.ID}}Client) Patch(o *{{.prefix}}{{.schema.CodeName}}, patchType types.PatchType, data []byte, subresources ...string) (*{{.prefix}}{{.schema.CodeName}}, error) { - obj, err := s.objectClient.Patch(o.Name, o, patchType, data, subresources...) - return obj.(*{{.prefix}}{{.schema.CodeName}}), err -} - -func (s *{{.schema.ID}}Client) DeleteCollection(deleteOpts *metav1.DeleteOptions, listOpts metav1.ListOptions) error { - return s.objectClient.DeleteCollection(deleteOpts, listOpts) -} - -func (s *{{.schema.ID}}Client) AddHandler(ctx context.Context, name string, sync {{.schema.CodeName}}HandlerFunc) { - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *{{.schema.ID}}Client) AddLifecycle(ctx context.Context, name string, lifecycle {{.schema.CodeName}}Lifecycle) { - sync := New{{.schema.CodeName}}LifecycleAdapter(name, false, s, lifecycle) - s.Controller().AddHandler(ctx, name, sync) -} - -func (s *{{.schema.ID}}Client) AddClusterScopedHandler(ctx context.Context, name, clusterName string, sync {{.schema.CodeName}}HandlerFunc) { - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -func (s *{{.schema.ID}}Client) AddClusterScopedLifecycle(ctx context.Context, name, clusterName string, lifecycle {{.schema.CodeName}}Lifecycle) { - sync := New{{.schema.CodeName}}LifecycleAdapter(name+"_"+clusterName, true, s, lifecycle) - s.Controller().AddClusterScopedHandler(ctx, name, clusterName, sync) -} - -type {{.schema.CodeName}}Indexer func(obj *{{.prefix}}{{.schema.CodeName}}) ([]string, error) - -type {{.schema.CodeName}}ClientCache interface { - Get(namespace, name string) (*{{.prefix}}{{.schema.CodeName}}, error) - List(namespace string, selector labels.Selector) ([]*{{.prefix}}{{.schema.CodeName}}, error) - - Index(name string, indexer {{.schema.CodeName}}Indexer) - GetIndexed(name, key string) ([]*{{.prefix}}{{.schema.CodeName}}, error) -} - -type {{.schema.CodeName}}Client interface { - Create(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) - Get(namespace, name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) - Update(*{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - List(namespace string, opts metav1.ListOptions) (*{{.schema.CodeName}}List, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - - Cache() {{.schema.CodeName}}ClientCache - - OnCreate(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) - OnChange(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) - OnRemove(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) - Enqueue(namespace, name string) - - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient - Interface() {{.schema.CodeName}}Interface -} - -type {{.schema.ID}}ClientCache struct { - client *{{.schema.ID}}Client2 -} - -type {{.schema.ID}}Client2 struct { - iface {{.schema.CodeName}}Interface - controller {{.schema.CodeName}}Controller -} - -func (n *{{.schema.ID}}Client2) Interface() {{.schema.CodeName}}Interface { - return n.iface -} - -func (n *{{.schema.ID}}Client2) Generic() controller.GenericController { - return n.iface.Controller().Generic() -} - -func (n *{{.schema.ID}}Client2) ObjectClient() *objectclient.ObjectClient { - return n.Interface().ObjectClient() -} - -func (n *{{.schema.ID}}Client2) Enqueue(namespace, name string) { - n.iface.Controller().Enqueue(namespace, name) -} - -func (n *{{.schema.ID}}Client2) Create(obj *{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) { - return n.iface.Create(obj) -} - -func (n *{{.schema.ID}}Client2) Get(namespace, name string, opts metav1.GetOptions) (*{{.prefix}}{{.schema.CodeName}}, error) { - return n.iface.GetNamespaced(namespace, name, opts) -} - -func (n *{{.schema.ID}}Client2) Update(obj *{{.prefix}}{{.schema.CodeName}}) (*{{.prefix}}{{.schema.CodeName}}, error) { - return n.iface.Update(obj) -} - -func (n *{{.schema.ID}}Client2) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return n.iface.DeleteNamespaced(namespace, name, options) -} - -func (n *{{.schema.ID}}Client2) List(namespace string, opts metav1.ListOptions) (*{{.schema.CodeName}}List, error) { - return n.iface.List(opts) -} - -func (n *{{.schema.ID}}Client2) Watch(opts metav1.ListOptions) (watch.Interface, error) { - return n.iface.Watch(opts) -} - -func (n *{{.schema.ID}}ClientCache) Get(namespace, name string) (*{{.prefix}}{{.schema.CodeName}}, error) { - return n.client.controller.Lister().Get(namespace, name) -} - -func (n *{{.schema.ID}}ClientCache) List(namespace string, selector labels.Selector) ([]*{{.prefix}}{{.schema.CodeName}}, error) { - return n.client.controller.Lister().List(namespace, selector) -} - -func (n *{{.schema.ID}}Client2) Cache() {{.schema.CodeName}}ClientCache { - n.loadController() - return &{{.schema.ID}}ClientCache{ - client: n, - } -} - -func (n *{{.schema.ID}}Client2) OnCreate(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-create", &{{.schema.ID}}LifecycleDelegate{create: sync}) -} - -func (n *{{.schema.ID}}Client2) OnChange(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name+"-change", &{{.schema.ID}}LifecycleDelegate{update: sync}) -} - -func (n *{{.schema.ID}}Client2) OnRemove(ctx context.Context, name string, sync {{.schema.CodeName}}ChangeHandlerFunc) { - n.loadController() - n.iface.AddLifecycle(ctx, name, &{{.schema.ID}}LifecycleDelegate{remove: sync}) -} - -func (n *{{.schema.ID}}ClientCache) Index(name string, indexer {{.schema.CodeName}}Indexer) { - err := n.client.controller.Informer().GetIndexer().AddIndexers(map[string]cache.IndexFunc{ - name: func(obj interface{}) ([]string, error) { - if v, ok := obj.(*{{.prefix}}{{.schema.CodeName}}); ok { - return indexer(v) - } - return nil, nil - }, - }) - - if err != nil { - panic(err) - } -} - -func (n *{{.schema.ID}}ClientCache) GetIndexed(name, key string) ([]*{{.prefix}}{{.schema.CodeName}}, error) { - var result []*{{.prefix}}{{.schema.CodeName}} - objs, err := n.client.controller.Informer().GetIndexer().ByIndex(name, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - if v, ok := obj.(*{{.prefix}}{{.schema.CodeName}}); ok { - result = append(result, v) - } - } - - return result, nil -} - -func (n *{{.schema.ID}}Client2) loadController() { - if n.controller == nil { - n.controller = n.iface.Controller() - } -} - -type {{.schema.ID}}LifecycleDelegate struct { - create {{.schema.CodeName}}ChangeHandlerFunc - update {{.schema.CodeName}}ChangeHandlerFunc - remove {{.schema.CodeName}}ChangeHandlerFunc -} - -func (n *{{.schema.ID}}LifecycleDelegate) HasCreate() bool { - return n.create != nil -} - -func (n *{{.schema.ID}}LifecycleDelegate) Create(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) { - if n.create == nil { - return obj, nil - } - return n.create(obj) -} - -func (n *{{.schema.ID}}LifecycleDelegate) HasFinalize() bool { - return n.remove != nil -} - -func (n *{{.schema.ID}}LifecycleDelegate) Remove(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) { - if n.remove == nil { - return obj, nil - } - return n.remove(obj) -} - -func (n *{{.schema.ID}}LifecycleDelegate) Updated(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) { - if n.update == nil { - return obj, nil - } - return n.update(obj) -} -` diff --git a/vendor/github.com/rancher/norman/generator/default.go b/vendor/github.com/rancher/norman/generator/default.go deleted file mode 100644 index e13c43d5a1..0000000000 --- a/vendor/github.com/rancher/norman/generator/default.go +++ /dev/null @@ -1,66 +0,0 @@ -package generator - -import ( - "fmt" - "path" - "strings" - - "github.com/rancher/norman/types" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - baseCattle = "client" - baseK8s = "apis" -) - -func DefaultGenerate(schemas *types.Schemas, pkgPath string, publicAPI bool, privateTypes map[string]bool) error { - version := getVersion(schemas) - group := strings.Split(version.Group, ".")[0] - - cattleOutputPackage := path.Join(pkgPath, baseCattle, group, version.Version) - if !publicAPI { - cattleOutputPackage = "" - } - k8sOutputPackage := path.Join(pkgPath, baseK8s, version.Group, version.Version) - - if err := Generate(schemas, privateTypes, cattleOutputPackage, k8sOutputPackage); err != nil { - return err - } - - return nil -} - -func ControllersForForeignTypes(baseOutputPackage string, gv schema.GroupVersion, nsObjs []interface{}, objs []interface{}) error { - version := gv.Version - group := gv.Group - groupPath := group - - if groupPath == "" { - groupPath = "core" - } - - k8sOutputPackage := path.Join(baseOutputPackage, baseK8s, groupPath, version) - - return GenerateControllerForTypes(&types.APIVersion{ - Version: version, - Group: group, - Path: fmt.Sprintf("/k8s/%s-%s", groupPath, version), - }, k8sOutputPackage, nsObjs, objs) -} - -func getVersion(schemas *types.Schemas) *types.APIVersion { - var version types.APIVersion - for _, schema := range schemas.Schemas() { - if version.Group == "" { - version = schema.Version - continue - } - if version.Group != schema.Version.Group || - version.Version != schema.Version.Version { - panic("schema set contains two APIVersions") - } - } - - return &version -} diff --git a/vendor/github.com/rancher/norman/generator/funcs.go b/vendor/github.com/rancher/norman/generator/funcs.go deleted file mode 100644 index 4d191c76b2..0000000000 --- a/vendor/github.com/rancher/norman/generator/funcs.go +++ /dev/null @@ -1,50 +0,0 @@ -package generator - -import ( - "net/http" - "strings" - "text/template" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -func funcs() template.FuncMap { - return template.FuncMap{ - "capitalize": convert.Capitalize, - "unCapitalize": convert.Uncapitalize, - "upper": strings.ToUpper, - "toLower": strings.ToLower, - "hasGet": hasGet, - "hasPost": hasPost, - "getCollectionOutput": getCollectionOutput, - } -} - -func addUnderscore(input string) string { - return strings.ToLower(underscoreRegexp.ReplaceAllString(input, `${1}_${2}`)) -} - -func hasGet(schema *types.Schema) bool { - return contains(schema.CollectionMethods, http.MethodGet) -} - -func hasPost(schema *types.Schema) bool { - return contains(schema.CollectionMethods, http.MethodPost) -} - -func contains(list []string, needle string) bool { - for _, i := range list { - if i == needle { - return true - } - } - return false -} - -func getCollectionOutput(output, codeName string) string { - if output == "collection" { - return codeName + "Collection" - } - return convert.Capitalize(output) -} diff --git a/vendor/github.com/rancher/norman/generator/generator.go b/vendor/github.com/rancher/norman/generator/generator.go deleted file mode 100644 index a4813235d8..0000000000 --- a/vendor/github.com/rancher/norman/generator/generator.go +++ /dev/null @@ -1,533 +0,0 @@ -package generator - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "os/exec" - "path" - "regexp" - "strings" - "text/template" - - "github.com/pkg/errors" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "k8s.io/gengo/args" - "k8s.io/gengo/examples/deepcopy-gen/generators" - "k8s.io/gengo/generator" - gengotypes "k8s.io/gengo/types" -) - -var ( - blackListTypes = map[string]bool{ - "schema": true, - "resource": true, - "collection": true, - } - underscoreRegexp = regexp.MustCompile(`([a-z])([A-Z])`) -) - -type fieldInfo struct { - Name string - Type string -} - -func getGoType(field types.Field, schema *types.Schema, schemas *types.Schemas) string { - return getTypeString(field.Nullable, field.Type, schema, schemas) -} - -func getTypeString(nullable bool, typeName string, schema *types.Schema, schemas *types.Schemas) string { - switch { - case strings.HasPrefix(typeName, "reference["): - return "string" - case strings.HasPrefix(typeName, "map["): - return "map[string]" + getTypeString(false, typeName[len("map["):len(typeName)-1], schema, schemas) - case strings.HasPrefix(typeName, "array["): - return "[]" + getTypeString(false, typeName[len("array["):len(typeName)-1], schema, schemas) - } - - name := "" - - switch typeName { - case "base64": - return "string" - case "json": - return "interface{}" - case "boolean": - name = "bool" - case "float": - name = "float64" - case "int": - name = "int64" - case "multiline": - return "string" - case "masked": - return "string" - case "password": - return "string" - case "date": - return "string" - case "string": - return "string" - case "enum": - return "string" - case "intOrString": - return "intstr.IntOrString" - case "dnsLabel": - return "string" - case "dnsLabelRestricted": - return "string" - case "hostname": - return "string" - default: - if schema != nil && schemas != nil { - otherSchema := schemas.Schema(&schema.Version, typeName) - if otherSchema != nil { - name = otherSchema.CodeName - } - } - - if name == "" { - name = convert.Capitalize(typeName) - } - } - - if nullable { - return "*" + name - } - - return name -} - -func getTypeMap(schema *types.Schema, schemas *types.Schemas) map[string]fieldInfo { - result := map[string]fieldInfo{} - for name, field := range schema.ResourceFields { - if strings.EqualFold(name, "id") { - continue - } - result[field.CodeName] = fieldInfo{ - Name: name, - Type: getGoType(field, schema, schemas), - } - } - return result -} - -func getResourceActions(schema *types.Schema, schemas *types.Schemas) map[string]types.Action { - result := map[string]types.Action{} - for name, action := range schema.ResourceActions { - if action.Output != "" { - if schemas.Schema(&schema.Version, action.Output) != nil { - result[name] = action - } - } else { - result[name] = action - } - } - return result -} - -func getCollectionActions(schema *types.Schema, schemas *types.Schemas) map[string]types.Action { - result := map[string]types.Action{} - for name, action := range schema.CollectionActions { - if action.Output != "" { - output := action.Output - if action.Output == "collection" { - output = strings.ToLower(schema.CodeName) - } - if schemas.Schema(&schema.Version, output) != nil { - result[name] = action - } - } else { - result[name] = action - } - } - return result -} - -func generateType(outputDir string, schema *types.Schema, schemas *types.Schemas) error { - filePath := strings.ToLower("zz_generated_" + addUnderscore(schema.ID) + ".go") - output, err := os.Create(path.Join(outputDir, filePath)) - if err != nil { - return err - } - defer output.Close() - - typeTemplate, err := template.New("type.template"). - Funcs(funcs()). - Parse(strings.Replace(typeTemplate, "%BACK%", "`", -1)) - if err != nil { - return err - } - - return typeTemplate.Execute(output, map[string]interface{}{ - "schema": schema, - "structFields": getTypeMap(schema, schemas), - "resourceActions": getResourceActions(schema, schemas), - "collectionActions": getCollectionActions(schema, schemas), - }) -} - -func generateLifecycle(external bool, outputDir string, schema *types.Schema, schemas *types.Schemas) error { - filePath := strings.ToLower("zz_generated_" + addUnderscore(schema.ID) + "_lifecycle_adapter.go") - output, err := os.Create(path.Join(outputDir, filePath)) - if err != nil { - return err - } - defer output.Close() - - typeTemplate, err := template.New("lifecycle.template"). - Funcs(funcs()). - Parse(strings.Replace(lifecycleTemplate, "%BACK%", "`", -1)) - if err != nil { - return err - } - - importPackage := "" - prefix := "" - if external { - parts := strings.Split(schema.PkgName, "/vendor/") - importPackage = fmt.Sprintf("\"%s\"", parts[len(parts)-1]) - prefix = schema.Version.Version + "." - } - - return typeTemplate.Execute(output, map[string]interface{}{ - "schema": schema, - "importPackage": importPackage, - "prefix": prefix, - }) -} - -func generateController(external bool, outputDir string, schema *types.Schema, schemas *types.Schemas) error { - filePath := strings.ToLower("zz_generated_" + addUnderscore(schema.ID) + "_controller.go") - output, err := os.Create(path.Join(outputDir, filePath)) - if err != nil { - return err - } - defer output.Close() - - typeTemplate, err := template.New("controller.template"). - Funcs(funcs()). - Parse(strings.Replace(controllerTemplate, "%BACK%", "`", -1)) - if err != nil { - return err - } - - importPackage := "" - prefix := "" - if external { - parts := strings.Split(schema.PkgName, "/vendor/") - importPackage = fmt.Sprintf("\"%s\"", parts[len(parts)-1]) - prefix = schema.Version.Version + "." - } - - return typeTemplate.Execute(output, map[string]interface{}{ - "schema": schema, - "importPackage": importPackage, - "prefix": prefix, - }) -} - -func generateScheme(external bool, outputDir string, version *types.APIVersion, schemas []*types.Schema) error { - filePath := strings.ToLower("zz_generated_scheme.go") - output, err := os.Create(path.Join(outputDir, filePath)) - if err != nil { - return err - } - defer output.Close() - - typeTemplate, err := template.New("scheme.template"). - Funcs(funcs()). - Parse(strings.Replace(schemeTemplate, "%BACK%", "`", -1)) - if err != nil { - return err - } - - names := []string{} - for _, schema := range schemas { - if !external { - names = append(names, schema.CodeName) - } - if schema.CanList(nil) == nil { - names = append(names, schema.CodeName+"List") - } - } - - return typeTemplate.Execute(output, map[string]interface{}{ - "version": version, - "schemas": schemas, - "names": names, - }) -} - -func generateK8sClient(outputDir string, version *types.APIVersion, schemas []*types.Schema) error { - filePath := strings.ToLower("zz_generated_k8s_client.go") - output, err := os.Create(path.Join(outputDir, filePath)) - if err != nil { - return err - } - defer output.Close() - - typeTemplate, err := template.New("k8sClient.template"). - Funcs(funcs()). - Parse(strings.Replace(k8sClientTemplate, "%BACK%", "`", -1)) - if err != nil { - return err - } - - return typeTemplate.Execute(output, map[string]interface{}{ - "version": version, - "schemas": schemas, - }) -} - -func generateClient(outputDir string, schemas []*types.Schema) error { - template, err := template.New("client.template"). - Funcs(funcs()). - Parse(clientTemplate) - if err != nil { - return err - } - - output, err := os.Create(path.Join(outputDir, "zz_generated_client.go")) - if err != nil { - return err - } - defer output.Close() - - return template.Execute(output, map[string]interface{}{ - "schemas": schemas, - }) -} - -func GenerateControllerForTypes(version *types.APIVersion, k8sOutputPackage string, nsObjs []interface{}, objs []interface{}) error { - baseDir := args.DefaultSourceTree() - k8sDir := path.Join(baseDir, k8sOutputPackage) - - if err := prepareDirs(k8sDir); err != nil { - return err - } - - schemas := types.NewSchemas() - var controllers []*types.Schema - - for _, obj := range objs { - schema, err := schemas.Import(version, obj) - if err != nil { - return err - } - controllers = append(controllers, schema) - - if err := generateController(true, k8sDir, schema, schemas); err != nil { - return err - } - - if err := generateLifecycle(true, k8sDir, schema, schemas); err != nil { - return err - } - } - - for _, obj := range nsObjs { - schema, err := schemas.Import(version, obj) - if err != nil { - return err - } - schema.Scope = types.NamespaceScope - controllers = append(controllers, schema) - - if err := generateController(true, k8sDir, schema, schemas); err != nil { - return err - } - - if err := generateLifecycle(true, k8sDir, schema, schemas); err != nil { - return err - } - } - - if err := deepCopyGen(baseDir, k8sOutputPackage); err != nil { - return err - } - - if err := generateK8sClient(k8sDir, version, controllers); err != nil { - return err - } - - if err := generateScheme(true, k8sDir, version, controllers); err != nil { - return err - } - - return gofmt(baseDir, k8sOutputPackage) -} - -func Generate(schemas *types.Schemas, privateTypes map[string]bool, cattleOutputPackage, k8sOutputPackage string) error { - baseDir := args.DefaultSourceTree() - cattleDir := path.Join(baseDir, cattleOutputPackage) - k8sDir := path.Join(baseDir, k8sOutputPackage) - - if cattleOutputPackage == "" { - cattleDir = "" - } - - if err := prepareDirs(cattleDir, k8sDir); err != nil { - return err - } - - var controllers []*types.Schema - - var cattleClientTypes []*types.Schema - for _, schema := range schemas.Schemas() { - if blackListTypes[schema.ID] { - continue - } - - _, privateType := privateTypes[schema.ID] - - if cattleDir != "" { - if err := generateType(cattleDir, schema, schemas); err != nil { - return err - } - } - - if privateType || - (contains(schema.CollectionMethods, http.MethodGet) && - !strings.HasPrefix(schema.PkgName, "k8s.io") && - !strings.Contains(schema.PkgName, "/vendor/")) { - controllers = append(controllers, schema) - if err := generateController(false, k8sDir, schema, schemas); err != nil { - return err - } - if err := generateLifecycle(false, k8sDir, schema, schemas); err != nil { - return err - } - } - - if !privateType { - cattleClientTypes = append(cattleClientTypes, schema) - } - } - - if cattleDir != "" { - if err := generateClient(cattleDir, cattleClientTypes); err != nil { - return err - } - } - - if len(controllers) > 0 { - if err := deepCopyGen(baseDir, k8sOutputPackage); err != nil { - return err - } - - if err := generateK8sClient(k8sDir, &controllers[0].Version, controllers); err != nil { - return err - } - - if err := generateScheme(false, k8sDir, &controllers[0].Version, controllers); err != nil { - return err - } - } - - if err := gofmt(baseDir, k8sOutputPackage); err != nil { - return err - } - - if cattleOutputPackage != "" { - return gofmt(baseDir, cattleOutputPackage) - } - - return nil -} - -func prepareDirs(dirs ...string) error { - for _, dir := range dirs { - if dir == "" { - continue - } - - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - - files, err := ioutil.ReadDir(dir) - if err != nil { - return err - } - - for _, file := range files { - if strings.HasPrefix(file.Name(), "zz_generated") { - if err := os.Remove(path.Join(dir, file.Name())); err != nil { - return errors.Wrapf(err, "failed to delete %s", path.Join(dir, file.Name())) - } - } - } - } - - return nil -} - -func gofmt(workDir, pkg string) error { - cmd := exec.Command("goimports", "-w", "-l", "./"+pkg) - cmd.Dir = workDir - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - return cmd.Run() -} - -func deepCopyGen(workDir, pkg string) error { - arguments := &args.GeneratorArgs{ - InputDirs: []string{pkg}, - OutputBase: workDir, - OutputPackagePath: pkg, - OutputFileBaseName: "zz_generated_deepcopy", - GoHeaderFilePath: "/dev/null", - GeneratedBuildTag: "ignore_autogenerated", - } - - return arguments.Execute( - generators.NameSystems(), - generators.DefaultNameSystem(), - func(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { - packageParts := strings.Split(pkg, "/") - return generator.Packages{ - &generator.DefaultPackage{ - PackageName: packageParts[len(packageParts)-1], - PackagePath: pkg, - HeaderText: []byte{}, - GeneratorFunc: func(c *generator.Context) []generator.Generator { - return []generator.Generator{ - //&noInitGenerator{ - generators.NewGenDeepCopy(arguments.OutputFileBaseName, pkg, nil, true, true), - //}, - } - }, - FilterFunc: func(c *generator.Context, t *gengotypes.Type) bool { - if t.Name.Package != pkg { - return false - } - - if isObjectOrList(t) { - t.SecondClosestCommentLines = append(t.SecondClosestCommentLines, - "+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object") - } - - return true - }, - }, - } - }) -} - -func isObjectOrList(t *gengotypes.Type) bool { - for _, member := range t.Members { - if member.Embedded && (member.Name == "ObjectMeta" || member.Name == "ListMeta") { - return true - } - if member.Embedded && isObjectOrList(member.Type) { - return true - } - } - - return false -} diff --git a/vendor/github.com/rancher/norman/generator/k8s_client_template.go b/vendor/github.com/rancher/norman/generator/k8s_client_template.go deleted file mode 100644 index 9cd78b3662..0000000000 --- a/vendor/github.com/rancher/norman/generator/k8s_client_template.go +++ /dev/null @@ -1,124 +0,0 @@ -package generator - -var k8sClientTemplate = `package {{.version.Version}} - -import ( - "sync" - "context" - - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/restwatch" - "k8s.io/client-go/rest" -) - -type ( - contextKeyType struct{} - contextClientsKeyType struct{} -) - -type Interface interface { - RESTClient() rest.Interface - controller.Starter - {{range .schemas}} - {{.CodeNamePlural}}Getter{{end}} -} - -type Clients struct { - Interface Interface - {{range .schemas}} - {{.CodeName}} {{.CodeName}}Client{{end}} -} - -type Client struct { - sync.Mutex - restClient rest.Interface - starters []controller.Starter - {{range .schemas}} - {{.ID}}Controllers map[string]{{.CodeName}}Controller{{end}} -} - -func Factory(ctx context.Context, config rest.Config) (context.Context, controller.Starter, error) { - c, err := NewForConfig(config) - if err != nil { - return ctx, nil, err - } - - cs := NewClientsFromInterface(c) - - ctx = context.WithValue(ctx, contextKeyType{}, c) - ctx = context.WithValue(ctx, contextClientsKeyType{}, cs) - return ctx, c, nil -} - -func ClientsFrom(ctx context.Context) *Clients { - return ctx.Value(contextClientsKeyType{}).(*Clients) -} - -func From(ctx context.Context) Interface { - return ctx.Value(contextKeyType{}).(Interface) -} - -func NewClients(config rest.Config) (*Clients, error) { - iface, err := NewForConfig(config) - if err != nil { - return nil, err - } - return NewClientsFromInterface(iface), nil -} - -func NewClientsFromInterface(iface Interface) *Clients { - return &Clients{ - Interface: iface, - {{range .schemas}} - {{.CodeName}}: &{{.ID}}Client2{ - iface: iface.{{.CodeNamePlural}}(""), - },{{end}} - } -} - -func NewForConfig(config rest.Config) (Interface, error) { - if config.NegotiatedSerializer == nil { - config.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&config) - if err != nil { - return nil, err - } - - return &Client{ - restClient: restClient, - {{range .schemas}} - {{.ID}}Controllers: map[string]{{.CodeName}}Controller{},{{end}} - }, nil -} - -func (c *Client) RESTClient() rest.Interface { - return c.restClient -} - -func (c *Client) Sync(ctx context.Context) error { - return controller.Sync(ctx, c.starters...) -} - -func (c *Client) Start(ctx context.Context, threadiness int) error { - return controller.Start(ctx, threadiness, c.starters...) -} - -{{range .schemas}} -type {{.CodeNamePlural}}Getter interface { - {{.CodeNamePlural}}(namespace string) {{.CodeName}}Interface -} - -func (c *Client) {{.CodeNamePlural}}(namespace string) {{.CodeName}}Interface { - objectClient := objectclient.NewObjectClient(namespace, c.restClient, &{{.CodeName}}Resource, {{.CodeName}}GroupVersionKind, {{.ID}}Factory{}) - return &{{.ID}}Client{ - ns: namespace, - client: c, - objectClient: objectClient, - } -} -{{end}} -` diff --git a/vendor/github.com/rancher/norman/generator/lifecycle_template.go b/vendor/github.com/rancher/norman/generator/lifecycle_template.go deleted file mode 100644 index d0a6cf545b..0000000000 --- a/vendor/github.com/rancher/norman/generator/lifecycle_template.go +++ /dev/null @@ -1,67 +0,0 @@ -package generator - -var lifecycleTemplate = `package {{.schema.Version.Version}} - -import ( - {{.importPackage}} - "k8s.io/apimachinery/pkg/runtime" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/lifecycle" -) - -type {{.schema.CodeName}}Lifecycle interface { - Create(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) - Remove(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) - Updated(obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) -} - -type {{.schema.ID}}LifecycleAdapter struct { - lifecycle {{.schema.CodeName}}Lifecycle -} - -func (w *{{.schema.ID}}LifecycleAdapter) HasCreate() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasCreate() -} - -func (w *{{.schema.ID}}LifecycleAdapter) HasFinalize() bool { - o, ok := w.lifecycle.(lifecycle.ObjectLifecycleCondition) - return !ok || o.HasFinalize() -} - -func (w *{{.schema.ID}}LifecycleAdapter) Create(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Create(obj.(*{{.prefix}}{{.schema.CodeName}})) - if o == nil { - return nil, err - } - return o, err -} - -func (w *{{.schema.ID}}LifecycleAdapter) Finalize(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Remove(obj.(*{{.prefix}}{{.schema.CodeName}})) - if o == nil { - return nil, err - } - return o, err -} - -func (w *{{.schema.ID}}LifecycleAdapter) Updated(obj runtime.Object) (runtime.Object, error) { - o, err := w.lifecycle.Updated(obj.(*{{.prefix}}{{.schema.CodeName}})) - if o == nil { - return nil, err - } - return o, err -} - -func New{{.schema.CodeName}}LifecycleAdapter(name string, clusterScoped bool, client {{.schema.CodeName}}Interface, l {{.schema.CodeName}}Lifecycle) {{.schema.CodeName}}HandlerFunc { - adapter := &{{.schema.ID}}LifecycleAdapter{lifecycle: l} - syncFn := lifecycle.NewObjectLifecycleAdapter(name, clusterScoped, adapter, client.ObjectClient()) - return func(key string, obj *{{.prefix}}{{.schema.CodeName}}) (runtime.Object, error) { - newObj, err := syncFn(key, obj) - if o, ok := newObj.(runtime.Object); ok { - return o, err - } - return nil, err - } -} -` diff --git a/vendor/github.com/rancher/norman/generator/scheme_template.go b/vendor/github.com/rancher/norman/generator/scheme_template.go deleted file mode 100644 index 0ef19048f5..0000000000 --- a/vendor/github.com/rancher/norman/generator/scheme_template.go +++ /dev/null @@ -1,42 +0,0 @@ -package generator - -var schemeTemplate = `package {{.version.Version}} - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -const ( - GroupName = "{{.version.Group}}" - Version = "{{.version.Version}}" -) - -// SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} - -// 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 = runtime.NewSchemeBuilder(addKnownTypes) - AddToScheme = SchemeBuilder.AddToScheme -) - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - // TODO this gets cleaned up when the types are fixed - scheme.AddKnownTypes(SchemeGroupVersion, - {{range .names}} - &{{.}}{},{{end}} - ) - return nil -} -` diff --git a/vendor/github.com/rancher/norman/generator/type_template.go b/vendor/github.com/rancher/norman/generator/type_template.go deleted file mode 100644 index 2a640dcf38..0000000000 --- a/vendor/github.com/rancher/norman/generator/type_template.go +++ /dev/null @@ -1,166 +0,0 @@ -package generator - -var typeTemplate = `package client - -{{- if .schema | hasGet }} -import ( - "github.com/rancher/norman/types" - "k8s.io/apimachinery/pkg/util/intstr" -) -{{- end}} - -const ( - {{.schema.CodeName}}Type = "{{.schema.ID}}" -{{- range $key, $value := .structFields}} - {{$.schema.CodeName}}Field{{$key}} = "{{$value.Name}}" -{{- end}} -) - -type {{.schema.CodeName}} struct { -{{- if .schema | hasGet }} - types.Resource -{{- end}} - {{- range $key, $value := .structFields}} - {{$key}} {{$value.Type}} %BACK%json:"{{$value.Name}},omitempty" yaml:"{{$value.Name}},omitempty"%BACK% - {{- end}} -} - -{{ if .schema | hasGet }} -type {{.schema.CodeName}}Collection struct { - types.Collection - Data []{{.schema.CodeName}} %BACK%json:"data,omitempty"%BACK% - client *{{.schema.CodeName}}Client -} - -type {{.schema.CodeName}}Client struct { - apiClient *Client -} - -type {{.schema.CodeName}}Operations interface { - List(opts *types.ListOpts) (*{{.schema.CodeName}}Collection, error) - Create(opts *{{.schema.CodeName}}) (*{{.schema.CodeName}}, error) - Update(existing *{{.schema.CodeName}}, updates interface{}) (*{{.schema.CodeName}}, error) - Replace(existing *{{.schema.CodeName}}) (*{{.schema.CodeName}}, error) - ByID(id string) (*{{.schema.CodeName}}, error) - Delete(container *{{.schema.CodeName}}) error - {{range $key, $value := .resourceActions}} - {{if (and (eq $value.Input "") (eq $value.Output ""))}} - Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (error) - {{else if (and (eq $value.Input "") (ne $value.Output ""))}} - Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) - {{else if (and (ne $value.Input "") (eq $value.Output ""))}} - Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (error) - {{else}} - Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) - {{end}} - {{end}} - {{range $key, $value := .collectionActions}} - {{if (and (eq $value.Input "") (eq $value.Output ""))}} - CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection) (error) - {{else if (and (eq $value.Input "") (ne $value.Output ""))}} - CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection) (*{{getCollectionOutput $value.Output $.schema.CodeName}}, error) - {{else if (and (ne $value.Input "") (eq $value.Output ""))}} - CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection, input *{{$value.Input | capitalize}}) (error) - {{else}} - CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection, input *{{$value.Input | capitalize}}) (*{{getCollectionOutput $value.Output $.schema.CodeName}}, error) - {{end}} - {{end}} -} - -func new{{.schema.CodeName}}Client(apiClient *Client) *{{.schema.CodeName}}Client { - return &{{.schema.CodeName}}Client{ - apiClient: apiClient, - } -} - -func (c *{{.schema.CodeName}}Client) Create(container *{{.schema.CodeName}}) (*{{.schema.CodeName}}, error) { - resp := &{{.schema.CodeName}}{} - err := c.apiClient.Ops.DoCreate({{.schema.CodeName}}Type, container, resp) - return resp, err -} - -func (c *{{.schema.CodeName}}Client) Update(existing *{{.schema.CodeName}}, updates interface{}) (*{{.schema.CodeName}}, error) { - resp := &{{.schema.CodeName}}{} - err := c.apiClient.Ops.DoUpdate({{.schema.CodeName}}Type, &existing.Resource, updates, resp) - return resp, err -} - -func (c *{{.schema.CodeName}}Client) Replace(obj *{{.schema.CodeName}}) (*{{.schema.CodeName}}, error) { - resp := &{{.schema.CodeName}}{} - err := c.apiClient.Ops.DoReplace({{.schema.CodeName}}Type, &obj.Resource, obj, resp) - return resp, err -} - -func (c *{{.schema.CodeName}}Client) List(opts *types.ListOpts) (*{{.schema.CodeName}}Collection, error) { - resp := &{{.schema.CodeName}}Collection{} - err := c.apiClient.Ops.DoList({{.schema.CodeName}}Type, opts, resp) - resp.client = c - return resp, err -} - -func (cc *{{.schema.CodeName}}Collection) Next() (*{{.schema.CodeName}}Collection, error) { - if cc != nil && cc.Pagination != nil && cc.Pagination.Next != "" { - resp := &{{.schema.CodeName}}Collection{} - err := cc.client.apiClient.Ops.DoNext(cc.Pagination.Next, resp) - resp.client = cc.client - return resp, err - } - return nil, nil -} - -func (c *{{.schema.CodeName}}Client) ByID(id string) (*{{.schema.CodeName}}, error) { - resp := &{{.schema.CodeName}}{} - err := c.apiClient.Ops.DoByID({{.schema.CodeName}}Type, id, resp) - return resp, err -} - -func (c *{{.schema.CodeName}}Client) Delete(container *{{.schema.CodeName}}) error { - return c.apiClient.Ops.DoResourceDelete({{.schema.CodeName}}Type, &container.Resource) -} - -{{range $key, $value := .resourceActions}} - {{if (and (eq $value.Input "") (eq $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (error) { - err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, nil, nil) - return err - {{else if (and (eq $value.Input "") (ne $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}) (*{{.Output | capitalize}}, error) { - resp := &{{.Output | capitalize}}{} - err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, nil, resp) - return resp, err - {{else if (and (ne $value.Input "") (eq $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (error) { - err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, input, nil) - return err - {{else}} - func (c *{{$.schema.CodeName}}Client) Action{{$key | capitalize}} (resource *{{$.schema.CodeName}}, input *{{$value.Input | capitalize}}) (*{{.Output | capitalize}}, error) { - resp := &{{.Output | capitalize}}{} - err := c.apiClient.Ops.DoAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Resource, input, resp) - return resp, err - {{- end -}} - } -{{end}} - -{{range $key, $value := .collectionActions}} - {{if (and (eq $value.Input "") (eq $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection) (error) { - err := c.apiClient.Ops.DoCollectionAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Collection, nil, nil) - return err - {{else if (and (eq $value.Input "") (ne $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection) (*{{getCollectionOutput $value.Output $.schema.CodeName}}, error) { - resp := &{{getCollectionOutput $value.Output $.schema.CodeName}}{} - err := c.apiClient.Ops.DoCollectionAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Collection, nil, resp) - return resp, err - {{else if (and (ne $value.Input "") (eq $value.Output ""))}} - func (c *{{$.schema.CodeName}}Client) CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection, input *{{$value.Input | capitalize}}) (error) { - err := c.apiClient.Ops.DoCollectionAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Collection, input, nil) - return err - {{else}} - func (c *{{$.schema.CodeName}}Client) CollectionAction{{$key | capitalize}} (resource *{{$.schema.CodeName}}Collection, input *{{$value.Input | capitalize}}) (*{{getCollectionOutput $value.Output $.schema.CodeName}}, error) { - resp := &{{getCollectionOutput $value.Output $.schema.CodeName}}{} - err := c.apiClient.Ops.DoCollectionAction({{$.schema.CodeName}}Type, "{{$key}}", &resource.Collection, input, resp) - return resp, err - {{- end -}} - } -{{end}} -{{end}}` diff --git a/vendor/github.com/rancher/norman/httperror/error.go b/vendor/github.com/rancher/norman/httperror/error.go deleted file mode 100644 index 73b10acd7f..0000000000 --- a/vendor/github.com/rancher/norman/httperror/error.go +++ /dev/null @@ -1,114 +0,0 @@ -package httperror - -import ( - "fmt" -) - -var ( - Unauthorized = ErrorCode{"Unauthorized", 401} - PermissionDenied = ErrorCode{"PermissionDenied", 403} - NotFound = ErrorCode{"NotFound", 404} - MethodNotAllowed = ErrorCode{"MethodNotAllow", 405} - Conflict = ErrorCode{"Conflict", 409} - - InvalidDateFormat = ErrorCode{"InvalidDateFormat", 422} - InvalidFormat = ErrorCode{"InvalidFormat", 422} - InvalidReference = ErrorCode{"InvalidReference", 422} - NotNullable = ErrorCode{"NotNullable", 422} - NotUnique = ErrorCode{"NotUnique", 422} - MinLimitExceeded = ErrorCode{"MinLimitExceeded", 422} - MaxLimitExceeded = ErrorCode{"MaxLimitExceeded", 422} - MinLengthExceeded = ErrorCode{"MinLengthExceeded", 422} - MaxLengthExceeded = ErrorCode{"MaxLengthExceeded", 422} - InvalidOption = ErrorCode{"InvalidOption", 422} - InvalidCharacters = ErrorCode{"InvalidCharacters", 422} - MissingRequired = ErrorCode{"MissingRequired", 422} - InvalidCSRFToken = ErrorCode{"InvalidCSRFToken", 422} - InvalidAction = ErrorCode{"InvalidAction", 422} - InvalidBodyContent = ErrorCode{"InvalidBodyContent", 422} - InvalidType = ErrorCode{"InvalidType", 422} - ActionNotAvailable = ErrorCode{"ActionNotAvailable", 404} - InvalidState = ErrorCode{"InvalidState", 422} - - ServerError = ErrorCode{"ServerError", 500} - ClusterUnavailable = ErrorCode{"ClusterUnavailable", 503} -) - -type ErrorCode struct { - Code string - Status int -} - -func (e ErrorCode) String() string { - return fmt.Sprintf("%s %d", e.Code, e.Status) -} - -type APIError struct { - Code ErrorCode - Message string - Cause error - FieldName string -} - -func NewAPIErrorLong(status int, code, message string) error { - return NewAPIError(ErrorCode{ - Code: code, - Status: status, - }, message) -} - -func NewAPIError(code ErrorCode, message string) error { - return &APIError{ - Code: code, - Message: message, - } -} - -func NewFieldAPIError(code ErrorCode, fieldName, message string) error { - return &APIError{ - Code: code, - Message: message, - FieldName: fieldName, - } -} - -// WrapFieldAPIError will cause the API framework to log the underlying err before returning the APIError as a response. -// err WILL NOT be in the API response -func WrapFieldAPIError(err error, code ErrorCode, fieldName, message string) error { - return &APIError{ - Cause: err, - Code: code, - Message: message, - FieldName: fieldName, - } -} - -// WrapAPIError will cause the API framework to log the underlying err before returning the APIError as a response. -// err WILL NOT be in the API response -func WrapAPIError(err error, code ErrorCode, message string) error { - return &APIError{ - Code: code, - Message: message, - Cause: err, - } -} - -func (a *APIError) Error() string { - if a.FieldName != "" { - return fmt.Sprintf("%s=%s: %s", a.FieldName, a.Code, a.Message) - } - return fmt.Sprintf("%s: %s", a.Code, a.Message) -} - -func IsAPIError(err error) bool { - _, ok := err.(*APIError) - return ok -} - -func IsConflict(err error) bool { - if apiError, ok := err.(*APIError); ok { - return apiError.Code.Status == 409 - } - - return false -} diff --git a/vendor/github.com/rancher/norman/httperror/handler/handler.go b/vendor/github.com/rancher/norman/httperror/handler/handler.go deleted file mode 100644 index 38b0224377..0000000000 --- a/vendor/github.com/rancher/norman/httperror/handler/handler.go +++ /dev/null @@ -1,47 +0,0 @@ -package handler - -import ( - "net/url" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "github.com/sirupsen/logrus" -) - -func ErrorHandler(request *types.APIContext, err error) { - var error *httperror.APIError - if apiError, ok := err.(*httperror.APIError); ok { - if apiError.Cause != nil { - url, _ := url.PathUnescape(request.Request.URL.String()) - if url == "" { - url = request.Request.URL.String() - } - logrus.Errorf("API error response %v for %v %v. Cause: %v", apiError.Code.Status, request.Request.Method, - url, apiError.Cause) - } - error = apiError - } else { - logrus.Errorf("Unknown error: %v", err) - error = &httperror.APIError{ - Code: httperror.ServerError, - Message: err.Error(), - } - } - - data := toError(error) - request.WriteResponse(error.Code.Status, data) -} - -func toError(apiError *httperror.APIError) map[string]interface{} { - e := map[string]interface{}{ - "type": "/meta/schemas/error", - "status": apiError.Code.Status, - "code": apiError.Code.Code, - "message": apiError.Message, - } - if apiError.FieldName != "" { - e["fieldName"] = apiError.FieldName - } - - return e -} diff --git a/vendor/github.com/rancher/norman/lifecycle/object.go b/vendor/github.com/rancher/norman/lifecycle/object.go deleted file mode 100644 index 25b12cb278..0000000000 --- a/vendor/github.com/rancher/norman/lifecycle/object.go +++ /dev/null @@ -1,267 +0,0 @@ -package lifecycle - -import ( - "fmt" - "reflect" - - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/types/slice" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" -) - -var ( - created = "lifecycle.cattle.io/create" - finalizerKey = "controller.cattle.io/" - ScopedFinalizerKey = "clusterscoped.controller.cattle.io/" -) - -type ObjectLifecycle interface { - Create(obj runtime.Object) (runtime.Object, error) - Finalize(obj runtime.Object) (runtime.Object, error) - Updated(obj runtime.Object) (runtime.Object, error) -} - -type ObjectLifecycleCondition interface { - HasCreate() bool - HasFinalize() bool -} - -type objectLifecycleAdapter struct { - name string - clusterScoped bool - lifecycle ObjectLifecycle - objectClient *objectclient.ObjectClient -} - -func NewObjectLifecycleAdapter(name string, clusterScoped bool, lifecycle ObjectLifecycle, objectClient *objectclient.ObjectClient) func(key string, obj interface{}) (interface{}, error) { - o := objectLifecycleAdapter{ - name: name, - clusterScoped: clusterScoped, - lifecycle: lifecycle, - objectClient: objectClient, - } - return o.sync -} - -func (o *objectLifecycleAdapter) sync(key string, in interface{}) (interface{}, error) { - if in == nil || reflect.ValueOf(in).IsNil() { - return nil, nil - } - - obj, ok := in.(runtime.Object) - if !ok { - return nil, nil - } - - if newObj, cont, err := o.finalize(obj); err != nil || !cont { - return nil, err - } else if newObj != nil { - obj = newObj - } - - if newObj, cont, err := o.create(obj); err != nil || !cont { - return nil, err - } else if newObj != nil { - obj = newObj - } - - return o.record(obj, o.lifecycle.Updated) -} - -func (o *objectLifecycleAdapter) update(name string, orig, obj runtime.Object) (runtime.Object, error) { - if obj != nil && orig != nil && !reflect.DeepEqual(orig, obj) { - newObj, err := o.objectClient.Update(name, obj) - if newObj != nil { - return newObj, err - } - return obj, err - } - if obj == nil { - return orig, nil - } - return obj, nil -} - -func (o *objectLifecycleAdapter) finalize(obj runtime.Object) (runtime.Object, bool, error) { - if !o.hasFinalize() { - return obj, true, nil - } - - metadata, err := meta.Accessor(obj) - if err != nil { - return obj, false, err - } - - // Check finalize - if metadata.GetDeletionTimestamp() == nil { - return nil, true, nil - } - - if !slice.ContainsString(metadata.GetFinalizers(), o.constructFinalizerKey()) { - return nil, false, nil - } - - newObj, err := o.record(obj, o.lifecycle.Finalize) - if err != nil { - return obj, false, err - } - - obj, err = o.removeFinalizer(o.constructFinalizerKey(), maybeDeepCopy(obj, newObj)) - return obj, false, err -} - -func maybeDeepCopy(old, newObj runtime.Object) runtime.Object { - if old == newObj { - return old.DeepCopyObject() - } - return newObj -} - -func (o *objectLifecycleAdapter) removeFinalizer(name string, obj runtime.Object) (runtime.Object, error) { - for i := 0; i < 3; i++ { - metadata, err := meta.Accessor(obj) - if err != nil { - return nil, err - } - - var finalizers []string - for _, finalizer := range metadata.GetFinalizers() { - if finalizer == name { - continue - } - finalizers = append(finalizers, finalizer) - } - metadata.SetFinalizers(finalizers) - - newObj, err := o.objectClient.Update(metadata.GetName(), obj) - if err == nil { - return newObj, nil - } - - obj, err = o.objectClient.GetNamespaced(metadata.GetNamespace(), metadata.GetName(), metav1.GetOptions{}) - if err != nil { - return nil, err - } - } - - return nil, fmt.Errorf("failed to remove finalizer on %s", name) -} - -func (o *objectLifecycleAdapter) createKey() string { - return created + "." + o.name -} - -func (o *objectLifecycleAdapter) constructFinalizerKey() string { - if o.clusterScoped { - return ScopedFinalizerKey + o.name - } - return finalizerKey + o.name -} - -func (o *objectLifecycleAdapter) hasFinalize() bool { - cond, ok := o.lifecycle.(ObjectLifecycleCondition) - return !ok || cond.HasFinalize() -} - -func (o *objectLifecycleAdapter) hasCreate() bool { - cond, ok := o.lifecycle.(ObjectLifecycleCondition) - return !ok || cond.HasCreate() -} - -func (o *objectLifecycleAdapter) record(obj runtime.Object, f func(runtime.Object) (runtime.Object, error)) (runtime.Object, error) { - metadata, err := meta.Accessor(obj) - if err != nil { - return obj, err - } - - origObj := obj - obj = origObj.DeepCopyObject() - if newObj, err := checkNil(obj, f); err != nil { - newObj, _ = o.update(metadata.GetName(), origObj, newObj) - return newObj, err - } else if newObj != nil { - return o.update(metadata.GetName(), origObj, newObj) - } - return obj, nil -} - -func checkNil(obj runtime.Object, f func(runtime.Object) (runtime.Object, error)) (runtime.Object, error) { - obj, err := f(obj) - if obj == nil || reflect.ValueOf(obj).IsNil() { - return nil, err - } - return obj, err -} - -func (o *objectLifecycleAdapter) create(obj runtime.Object) (runtime.Object, bool, error) { - metadata, err := meta.Accessor(obj) - if err != nil { - return obj, false, err - } - - if o.isInitialized(metadata) { - return nil, true, nil - } - - if o.hasFinalize() { - obj, err = o.addFinalizer(obj) - if err != nil { - return obj, false, err - } - } - - if !o.hasCreate() { - return obj, true, err - } - - obj, err = o.record(obj, o.lifecycle.Create) - if err != nil { - return obj, false, err - } - - obj, err = o.setInitialized(obj) - return obj, false, err -} - -func (o *objectLifecycleAdapter) isInitialized(metadata metav1.Object) bool { - initialized := o.createKey() - return metadata.GetAnnotations()[initialized] == "true" -} - -func (o *objectLifecycleAdapter) setInitialized(obj runtime.Object) (runtime.Object, error) { - metadata, err := meta.Accessor(obj) - if err != nil { - return nil, err - } - - initialized := o.createKey() - - if metadata.GetAnnotations() == nil { - metadata.SetAnnotations(map[string]string{}) - } - metadata.GetAnnotations()[initialized] = "true" - - return o.objectClient.Update(metadata.GetName(), obj) -} - -func (o *objectLifecycleAdapter) addFinalizer(obj runtime.Object) (runtime.Object, error) { - metadata, err := meta.Accessor(obj) - if err != nil { - return nil, err - } - - if slice.ContainsString(metadata.GetFinalizers(), o.constructFinalizerKey()) { - return obj, nil - } - - obj = obj.DeepCopyObject() - metadata, err = meta.Accessor(obj) - if err != nil { - return nil, err - } - - metadata.SetFinalizers(append(metadata.GetFinalizers(), o.constructFinalizerKey())) - return o.objectClient.Update(metadata.GetName(), obj) -} diff --git a/vendor/github.com/rancher/norman/metrics/generic_controller.go b/vendor/github.com/rancher/norman/metrics/generic_controller.go deleted file mode 100644 index 4f905db425..0000000000 --- a/vendor/github.com/rancher/norman/metrics/generic_controller.go +++ /dev/null @@ -1,58 +0,0 @@ -package metrics - -import ( - "os" - - "github.com/prometheus/client_golang/prometheus" -) - -const MetricsGenericControllerEnv = "NORMAN_GENERIC_CONTROLLER_METRICS" - -var ( - genericControllerMetrics = false - TotalHandlerExecution = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "norman_generic_controller", - Name: "total_handler_execution", - Help: "Total Count of executing handler", - }, - []string{"name", "handlerName"}, - ) - - TotalHandlerFailure = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "norman_generic_controller", - Name: "total_handler_failure", - Help: "Total Count of handler failure", - }, - []string{"name", "handlerName", "key"}, - ) -) - -func init() { - if os.Getenv(MetricsGenericControllerEnv) == "true" { - genericControllerMetrics = true - } -} - -func IncTotalHandlerExecution(controllerName, handlerName string) { - if genericControllerMetrics { - TotalHandlerExecution.With( - prometheus.Labels{ - "name": controllerName, - "handlerName": handlerName}, - ).Inc() - } -} - -func IncTotalHandlerFailure(controllerName, handlerName, key string) { - if genericControllerMetrics { - TotalHandlerFailure.With( - prometheus.Labels{ - "name": controllerName, - "handlerName": handlerName, - "key": key, - }, - ).Inc() - } -} diff --git a/vendor/github.com/rancher/norman/name/name.go b/vendor/github.com/rancher/norman/name/name.go deleted file mode 100644 index 8a5cfcf950..0000000000 --- a/vendor/github.com/rancher/norman/name/name.go +++ /dev/null @@ -1,27 +0,0 @@ -package name - -import "strings" - -func GuessPluralName(name string) string { - if name == "" { - return name - } - - if strings.EqualFold(name, "Endpoints") { - return name - } - - if suffix(name, "s") || suffix(name, "ch") || suffix(name, "x") { - return name + "es" - } - - if suffix(name, "y") && len(name) > 2 && !strings.ContainsAny(name[len(name)-2:len(name)-1], "[aeiou]") { - return name[0:len(name)-1] + "ies" - } - - return name + "s" -} - -func suffix(str, end string) bool { - return strings.HasSuffix(str, end) -} diff --git a/vendor/github.com/rancher/norman/objectclient/dynamic/content.go b/vendor/github.com/rancher/norman/objectclient/dynamic/content.go deleted file mode 100644 index 794f15b4e7..0000000000 --- a/vendor/github.com/rancher/norman/objectclient/dynamic/content.go +++ /dev/null @@ -1,58 +0,0 @@ -package dynamic - -import ( - ejson "encoding/json" - "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" -) - -var ( - NegotiatedSerializer = negotiatedSerializer{} -) - -type negotiatedSerializer struct{} - -func (s negotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo { - return []runtime.SerializerInfo{ - { - MediaType: "application/json", - EncodesAsText: true, - Serializer: dynamicCodec{ - Encoder: unstructured.UnstructuredJSONScheme, - }, - }, - } -} - -func (s negotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { - return encoder -} - -func (s negotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder { - return decoder -} - -type dynamicCodec struct { - runtime.Encoder -} - -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 _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" { - obj = &metav1.Status{} - err := ejson.Unmarshal(data, obj) - if err != nil { - return nil, nil, err - } - } - - return obj, gvk, nil -} diff --git a/vendor/github.com/rancher/norman/objectclient/object_client.go b/vendor/github.com/rancher/norman/objectclient/object_client.go deleted file mode 100644 index 6b4fcf5d9b..0000000000 --- a/vendor/github.com/rancher/norman/objectclient/object_client.go +++ /dev/null @@ -1,311 +0,0 @@ -package objectclient - -import ( - "encoding/json" - "strings" - - "github.com/pkg/errors" - "github.com/rancher/norman/restwatch" - "github.com/sirupsen/logrus" - "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" - json2 "k8s.io/apimachinery/pkg/runtime/serializer/json" - "k8s.io/apimachinery/pkg/runtime/serializer/streaming" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/rest" - restclientwatch "k8s.io/client-go/rest/watch" -) - -type ObjectFactory interface { - Object() runtime.Object - List() runtime.Object -} - -type UnstructuredObjectFactory struct { -} - -func (u *UnstructuredObjectFactory) Object() runtime.Object { - return &unstructured.Unstructured{} -} - -func (u *UnstructuredObjectFactory) List() runtime.Object { - return &unstructured.UnstructuredList{} -} - -type GenericClient interface { - UnstructuredClient() GenericClient - GroupVersionKind() schema.GroupVersionKind - Create(o runtime.Object) (runtime.Object, error) - GetNamespaced(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) - Get(name string, opts metav1.GetOptions) (runtime.Object, error) - Update(name string, o runtime.Object) (runtime.Object, error) - DeleteNamespaced(namespace, name string, opts *metav1.DeleteOptions) error - Delete(name string, opts *metav1.DeleteOptions) error - List(opts metav1.ListOptions) (runtime.Object, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error - Patch(name string, o runtime.Object, patchType types.PatchType, data []byte, subresources ...string) (runtime.Object, error) - ObjectFactory() ObjectFactory -} - -type ObjectClient struct { - restClient rest.Interface - resource *metav1.APIResource - gvk schema.GroupVersionKind - ns string - Factory ObjectFactory -} - -func NewObjectClient(namespace string, restClient rest.Interface, apiResource *metav1.APIResource, gvk schema.GroupVersionKind, factory ObjectFactory) *ObjectClient { - return &ObjectClient{ - restClient: restClient, - resource: apiResource, - gvk: gvk, - ns: namespace, - Factory: factory, - } -} - -func (p *ObjectClient) UnstructuredClient() GenericClient { - return &ObjectClient{ - restClient: p.restClient, - resource: p.resource, - gvk: p.gvk, - ns: p.ns, - Factory: &UnstructuredObjectFactory{}, - } -} - -func (p *ObjectClient) GroupVersionKind() schema.GroupVersionKind { - return p.gvk -} - -func (p *ObjectClient) getAPIPrefix() string { - if p.gvk.Group == "" { - return "api" - } - return "apis" -} - -func (p *ObjectClient) Create(o runtime.Object) (runtime.Object, error) { - ns := p.ns - obj, ok := o.(metav1.Object) - if ok && obj.GetNamespace() != "" { - ns = obj.GetNamespace() - } - - if ok { - labels := obj.GetLabels() - if labels == nil { - labels = make(map[string]string) - } - labels["cattle.io/creator"] = "norman" - obj.SetLabels(labels) - } - - if t, err := meta.TypeAccessor(o); err == nil { - if t.GetKind() == "" { - t.SetKind(p.gvk.Kind) - } - if t.GetAPIVersion() == "" { - apiVersion, _ := p.gvk.ToAPIVersionAndKind() - t.SetAPIVersion(apiVersion) - } - } - result := p.Factory.Object() - logrus.Debugf("REST CREATE %s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, ns, p.resource.Name) - err := p.restClient.Post(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(ns, p.resource.Namespaced). - Resource(p.resource.Name). - Body(o). - Do(). - Into(result) - return result, err -} - -func (p *ObjectClient) GetNamespaced(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) { - result := p.Factory.Object() - req := p.restClient.Get(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version) - if namespace != "" { - req = req.Namespace(namespace) - } - err := req. - Resource(p.resource.Name). - VersionedParams(&opts, metav1.ParameterCodec). - Name(name). - Do(). - Into(result) - logrus.Debugf("REST GET %s/%s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, namespace, p.resource.Name, name) - return result, err - -} - -func (p *ObjectClient) Get(name string, opts metav1.GetOptions) (runtime.Object, error) { - result := p.Factory.Object() - err := p.restClient.Get(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(p.ns, p.resource.Namespaced). - Resource(p.resource.Name). - VersionedParams(&opts, metav1.ParameterCodec). - Name(name). - Do(). - Into(result) - logrus.Debugf("REST GET %s/%s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, p.ns, p.resource.Name, name) - return result, err -} - -func (p *ObjectClient) Update(name string, o runtime.Object) (runtime.Object, error) { - ns := p.ns - if obj, ok := o.(metav1.Object); ok && obj.GetNamespace() != "" { - ns = obj.GetNamespace() - } - result := p.Factory.Object() - if len(name) == 0 { - return result, errors.New("object missing name") - } - logrus.Debugf("REST UPDATE %s/%s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, ns, p.resource.Name, name) - err := p.restClient.Put(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(ns, p.resource.Namespaced). - Resource(p.resource.Name). - Name(name). - Body(o). - Do(). - Into(result) - return result, err -} - -func (p *ObjectClient) DeleteNamespaced(namespace, name string, opts *metav1.DeleteOptions) error { - req := p.restClient.Delete(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version) - if namespace != "" { - req = req.Namespace(namespace) - } - logrus.Debugf("REST DELETE %s/%s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, namespace, p.resource.Name, name) - return req.Resource(p.resource.Name). - Name(name). - Body(opts). - Do(). - Error() -} - -func (p *ObjectClient) Delete(name string, opts *metav1.DeleteOptions) error { - logrus.Debugf("REST DELETE %s/%s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, p.ns, p.resource.Name, name) - return p.restClient.Delete(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(p.ns, p.resource.Namespaced). - Resource(p.resource.Name). - Name(name). - Body(opts). - Do(). - Error() -} - -func (p *ObjectClient) List(opts metav1.ListOptions) (runtime.Object, error) { - result := p.Factory.List() - logrus.Debugf("REST LIST %s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, p.ns, p.resource.Name) - return result, p.restClient.Get(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(p.ns, p.resource.Namespaced). - Resource(p.resource.Name). - VersionedParams(&opts, metav1.ParameterCodec). - Do(). - Into(result) -} - -func (p *ObjectClient) Watch(opts metav1.ListOptions) (watch.Interface, error) { - restClient := p.restClient - if watchClient, ok := restClient.(restwatch.WatchClient); ok { - restClient = watchClient.WatchClient() - } - - r, err := restClient.Get(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - Prefix("watch"). - NamespaceIfScoped(p.ns, p.resource.Namespaced). - Resource(p.resource.Name). - VersionedParams(&opts, metav1.ParameterCodec). - Stream() - if err != nil { - return nil, err - } - - embeddedDecoder := &structuredDecoder{ - factory: p.Factory, - } - streamDecoder := streaming.NewDecoder(json2.Framer.NewFrameReader(r), embeddedDecoder) - decoder := restclientwatch.NewDecoder(streamDecoder, embeddedDecoder) - return watch.NewStreamWatcher(decoder), nil -} - -type structuredDecoder struct { - factory ObjectFactory -} - -func (d *structuredDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { - if into == nil { - into = d.factory.Object() - } - - err := json.Unmarshal(data, &into) - if err != nil { - status := &metav1.Status{} - if err := json.Unmarshal(data, status); err == nil && strings.ToLower(status.Kind) == "status" { - return status, defaults, nil - } - return nil, nil, err - } - - if _, ok := into.(*metav1.Status); !ok && strings.ToLower(into.GetObjectKind().GroupVersionKind().Kind) == "status" { - into = &metav1.Status{} - err := json.Unmarshal(data, into) - if err != nil { - return nil, nil, err - } - } - - return into, defaults, err -} - -func (p *ObjectClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - return p.restClient.Delete(). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(p.ns, p.resource.Namespaced). - Resource(p.resource.Name). - VersionedParams(&listOptions, metav1.ParameterCodec). - Body(deleteOptions). - Do(). - Error() -} - -func (p *ObjectClient) Patch(name string, o runtime.Object, patchType types.PatchType, data []byte, subresources ...string) (runtime.Object, error) { - ns := p.ns - if obj, ok := o.(metav1.Object); ok && obj.GetNamespace() != "" { - ns = obj.GetNamespace() - } - result := p.Factory.Object() - if len(name) == 0 { - return result, errors.New("object missing name") - } - logrus.Debugf("REST PATCH %s/%s/%s/%s/%s", p.getAPIPrefix(), p.gvk.Group, p.gvk.Version, p.ns, name) - err := p.restClient.Patch(patchType). - Prefix(p.getAPIPrefix(), p.gvk.Group, p.gvk.Version). - NamespaceIfScoped(ns, p.resource.Namespaced). - Resource(p.resource.Name). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return result, err -} - -func (p *ObjectClient) ObjectFactory() ObjectFactory { - return p.Factory -} diff --git a/vendor/github.com/rancher/norman/parse/browser.go b/vendor/github.com/rancher/norman/parse/browser.go deleted file mode 100644 index 6d195d0e57..0000000000 --- a/vendor/github.com/rancher/norman/parse/browser.go +++ /dev/null @@ -1,18 +0,0 @@ -package parse - -import ( - "net/http" - "strings" -) - -func IsBrowser(req *http.Request, checkAccepts bool) bool { - accepts := strings.ToLower(req.Header.Get("Accept")) - userAgent := strings.ToLower(req.Header.Get("User-Agent")) - - if accepts == "" || !checkAccepts { - accepts = "*/*" - } - - // User agent has Mozilla and browser accepts */* - return strings.Contains(userAgent, "mozilla") && strings.Contains(accepts, "*/*") -} diff --git a/vendor/github.com/rancher/norman/parse/builder/builder.go b/vendor/github.com/rancher/norman/parse/builder/builder.go deleted file mode 100644 index 38084fc810..0000000000 --- a/vendor/github.com/rancher/norman/parse/builder/builder.go +++ /dev/null @@ -1,502 +0,0 @@ -package builder - -import ( - "errors" - "fmt" - "strings" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" - "k8s.io/apimachinery/pkg/util/validation" -) - -var ( - Create = Operation("create") - Update = Operation("update") - Action = Operation("action") - List = Operation("list") - ListForCreate = Operation("listcreate") - ErrComplexType = errors.New("complex type") -) - -type Operation string - -func (o Operation) IsList() bool { - return strings.HasPrefix(string(o), "list") -} - -type Builder struct { - apiContext *types.APIContext - Version *types.APIVersion - Schemas *types.Schemas - RefValidator types.ReferenceValidator - edit bool - export bool - yaml bool -} - -func NewBuilder(apiRequest *types.APIContext) *Builder { - return &Builder{ - apiContext: apiRequest, - yaml: apiRequest.ResponseFormat == "yaml", - edit: apiRequest.Option("edit") == "true", - export: apiRequest.Option("export") == "true", - Version: apiRequest.Version, - Schemas: apiRequest.Schemas, - RefValidator: apiRequest.ReferenceValidator, - } -} - -func (b *Builder) Construct(schema *types.Schema, input map[string]interface{}, op Operation) (map[string]interface{}, error) { - result, err := b.copyFields(schema, input, op) - if err != nil { - return nil, err - } - if (op == Create || op == Update) && schema.Validator != nil { - if err := schema.Validator(b.apiContext, schema, result); err != nil { - return nil, err - } - } - return result, nil -} - -func (b *Builder) copyInputs(schema *types.Schema, input map[string]interface{}, op Operation, result map[string]interface{}) error { - for fieldName, value := range input { - field, ok := schema.ResourceFields[fieldName] - if !ok { - continue - } - - if !fieldMatchesOp(field, op) { - continue - } - - wasNull := value == nil && (field.Nullable || field.Default == nil) - value, err := b.convert(field.Type, value, op) - if err != nil { - return httperror.WrapFieldAPIError(err, httperror.InvalidFormat, fieldName, err.Error()) - } - - if value != nil || wasNull { - if !op.IsList() { - if slice, ok := value.([]interface{}); ok { - for _, sliceValue := range slice { - if sliceValue == nil { - return httperror.NewFieldAPIError(httperror.NotNullable, fieldName, "Individual array values can not be null") - } - if err := CheckFieldCriteria(fieldName, field, sliceValue); err != nil { - return err - } - } - } else { - if err := CheckFieldCriteria(fieldName, field, value); err != nil { - return err - } - } - } - result[fieldName] = value - - if op.IsList() && field.Type == "date" && value != "" && !b.edit { - ts, err := convert.ToTimestamp(value) - if err == nil { - result[fieldName+"TS"] = ts - } - } - } - } - - if op.IsList() && !b.edit && !b.export { - if !convert.IsAPIObjectEmpty(input["type"]) { - result["type"] = input["type"] - } - if !convert.IsAPIObjectEmpty(input["id"]) { - result["id"] = input["id"] - } - } - - return nil -} - -func (b *Builder) checkDefaultAndRequired(schema *types.Schema, input map[string]interface{}, op Operation, result map[string]interface{}) error { - for fieldName, field := range schema.ResourceFields { - val, hasKey := result[fieldName] - if op == Create && (!hasKey || val == "") && field.Default != nil { - result[fieldName] = field.Default - } - - _, hasKey = result[fieldName] - if op == Create && fieldMatchesOp(field, Create) && field.Required { - if !hasKey { - return httperror.NewFieldAPIError(httperror.MissingRequired, fieldName, "") - } - - if definition.IsArrayType(field.Type) { - slice, err := b.convertArray(field.Type, result[fieldName], op) - if err != nil { - return err - } - if len(slice) == 0 { - return httperror.NewFieldAPIError(httperror.MissingRequired, fieldName, "") - } - } - } - - if op.IsList() && fieldMatchesOp(field, List) && definition.IsReferenceType(field.Type) && !hasKey { - result[fieldName] = nil - } else if op.IsList() && fieldMatchesOp(field, List) && !hasKey && field.Default != nil { - result[fieldName] = field.Default - } - } - - if op.IsList() && b.edit { - b.populateMissingFieldsForEdit(schema, result) - } - - if op.IsList() && b.export { - b.dropDefaultsAndReadOnly(schema, result) - } - - return nil -} - -func (b *Builder) dropDefaultsAndReadOnly(schema *types.Schema, result map[string]interface{}) { - for name, existingVal := range result { - field, ok := schema.ResourceFields[name] - if !ok { - delete(result, name) - } - - if !field.Create { - delete(result, name) - continue - } - - if field.Default == existingVal { - delete(result, name) - continue - } - - val, err := b.convert(field.Type, nil, List) - if err == nil && val == existingVal { - delete(result, name) - continue - } - - if convert.IsAPIObjectEmpty(existingVal) { - delete(result, name) - continue - } - } -} - -func (b *Builder) populateMissingFieldsForEdit(schema *types.Schema, result map[string]interface{}) { - for name, field := range schema.ResourceFields { - if !field.Update { - if name != "name" { - delete(result, name) - } - continue - } - - desc := field.Description - if len(desc) > 0 { - desc += " " - } - - value, hasKey := result[name] - if hasKey { - if field.Default != nil && field.Default == value { - delete(result, name) - result["zzz#("+desc+")("+field.Type+")"+name] = value - } - continue - } - - if field.Default != nil { - result["zzz#("+desc+")("+field.Type+")"+name] = field.Default - } else { - val, err := b.convert(field.Type, nil, List) - if err == nil { - result["zzz#("+desc+")("+field.Type+")"+name] = val - } - } - } -} - -func (b *Builder) copyFields(schema *types.Schema, input map[string]interface{}, op Operation) (map[string]interface{}, error) { - result := map[string]interface{}{} - - if err := b.copyInputs(schema, input, op, result); err != nil { - return nil, err - } - - return result, b.checkDefaultAndRequired(schema, input, op, result) -} - -func CheckFieldCriteria(fieldName string, field types.Field, value interface{}) error { - numVal, isNum := value.(int64) - strVal := "" - hasStrVal := false - - if value == nil && field.Default != nil { - value = field.Default - } - - if value != nil && value != "" { - hasStrVal = true - strVal = fmt.Sprint(value) - } - - if (value == nil || value == "") && !field.Nullable { - if field.Default == nil { - return httperror.NewFieldAPIError(httperror.NotNullable, fieldName, "") - } - } - - if isNum { - if field.Min != nil && numVal < *field.Min { - return httperror.NewFieldAPIError(httperror.MinLimitExceeded, fieldName, "") - } - if field.Max != nil && numVal > *field.Max { - return httperror.NewFieldAPIError(httperror.MaxLimitExceeded, fieldName, "") - } - } - - if hasStrVal || value == "" { - if field.MinLength != nil && int64(len(strVal)) < *field.MinLength { - return httperror.NewFieldAPIError(httperror.MinLengthExceeded, fieldName, "") - } - if field.MaxLength != nil && int64(len(strVal)) > *field.MaxLength { - return httperror.NewFieldAPIError(httperror.MaxLengthExceeded, fieldName, "") - } - } - - if len(field.Options) > 0 { - if hasStrVal || !field.Nullable { - found := false - for _, option := range field.Options { - if strVal == option { - found = true - break - } - } - - if !found { - return httperror.NewFieldAPIError(httperror.InvalidOption, fieldName, "") - } - } - } - - if len(field.ValidChars) > 0 && hasStrVal { - for _, c := range strVal { - if !strings.ContainsRune(field.ValidChars, c) { - return httperror.NewFieldAPIError(httperror.InvalidCharacters, fieldName, "") - } - - } - } - - if len(field.InvalidChars) > 0 && hasStrVal { - if strings.ContainsAny(strVal, field.InvalidChars) { - return httperror.NewFieldAPIError(httperror.InvalidCharacters, fieldName, "") - } - } - - return nil -} - -func ConvertSimple(fieldType string, value interface{}, op Operation) (interface{}, error) { - if value == nil { - return value, nil - } - - switch fieldType { - case "json": - return value, nil - case "date": - v := convert.ToString(value) - if v == "" { - return nil, nil - } - return v, nil - case "boolean": - return convert.ToBool(value), nil - case "enum": - return convert.ToString(value), nil - case "int": - return convert.ToNumber(value) - case "float": - return convert.ToFloat(value) - case "password": - return convert.ToString(value), nil - case "string": - if op.IsList() { - return convert.ToStringNoTrim(value), nil - } - return convert.ToString(value), nil - case "dnsLabel": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1123Label(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "dnsLabelRestricted": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1035Label(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "hostname": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1123Subdomain(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "intOrString": - num, err := convert.ToNumber(value) - if err == nil { - return num, nil - } - return convert.ToString(value), nil - case "base64": - return convert.ToString(value), nil - case "reference": - return convert.ToString(value), nil - } - - return nil, ErrComplexType -} - -func (b *Builder) convert(fieldType string, value interface{}, op Operation) (interface{}, error) { - if value == nil { - return value, nil - } - - switch { - case definition.IsMapType(fieldType): - return b.convertMap(fieldType, value, op) - case definition.IsArrayType(fieldType): - return b.convertArray(fieldType, value, op) - case definition.IsReferenceType(fieldType): - return b.convertReferenceType(fieldType, value) - } - - newValue, err := ConvertSimple(fieldType, value, op) - if err == ErrComplexType { - return b.convertType(fieldType, value, op) - } - return newValue, err -} - -func (b *Builder) convertType(fieldType string, value interface{}, op Operation) (interface{}, error) { - schema := b.Schemas.Schema(b.Version, fieldType) - if schema == nil { - return nil, httperror.NewAPIError(httperror.InvalidType, "Failed to find type "+fieldType) - } - - mapValue, ok := value.(map[string]interface{}) - if !ok { - return nil, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("Value can not be converted to type %s: %v", fieldType, value)) - } - - return b.Construct(schema, mapValue, op) -} - -func (b *Builder) convertReferenceType(fieldType string, value interface{}) (string, error) { - subType := definition.SubType(fieldType) - strVal := convert.ToString(value) - if b.RefValidator != nil && !b.RefValidator.Validate(subType, strVal) { - return "", httperror.NewAPIError(httperror.InvalidReference, fmt.Sprintf("Not found type: %s id: %s", subType, strVal)) - } - return strVal, nil -} - -func (b *Builder) convertArray(fieldType string, value interface{}, op Operation) ([]interface{}, error) { - if strSliceValue, ok := value.([]string); ok { - // Form data will be []string - var result []interface{} - for _, value := range strSliceValue { - result = append(result, value) - } - return result, nil - } - - sliceValue, ok := value.([]interface{}) - if !ok { - return nil, nil - } - - var result []interface{} - subType := definition.SubType(fieldType) - - for _, value := range sliceValue { - val, err := b.convert(subType, value, op) - if err != nil { - return nil, err - } - result = append(result, val) - } - - return result, nil -} - -func (b *Builder) convertMap(fieldType string, value interface{}, op Operation) (map[string]interface{}, error) { - mapValue, ok := value.(map[string]interface{}) - if !ok { - return nil, nil - } - - result := map[string]interface{}{} - subType := definition.SubType(fieldType) - - for key, value := range mapValue { - val, err := b.convert(subType, value, op) - if err != nil { - return nil, httperror.WrapAPIError(err, httperror.InvalidFormat, err.Error()) - } - result[key] = val - } - - return result, nil -} - -func fieldMatchesOp(field types.Field, op Operation) bool { - switch op { - case Create: - return field.Create - case Update: - return field.Update - case List: - if field.Type == "password" { - return false - } - return !field.WriteOnly - case ListForCreate: - if field.Type == "password" { - return false - } - return true - default: - return false - } -} diff --git a/vendor/github.com/rancher/norman/parse/collection.go b/vendor/github.com/rancher/norman/parse/collection.go deleted file mode 100644 index f6a20afc8e..0000000000 --- a/vendor/github.com/rancher/norman/parse/collection.go +++ /dev/null @@ -1,112 +0,0 @@ -package parse - -import ( - "net/http" - "strconv" - "strings" - - "github.com/rancher/norman/types" -) - -var ( - defaultLimit = int64(1000) - maxLimit = int64(3000) -) - -func QueryOptions(apiContext *types.APIContext, schema *types.Schema) types.QueryOptions { - req := apiContext.Request - if req.Method != http.MethodGet { - return types.QueryOptions{} - } - - result := &types.QueryOptions{} - - result.Sort = parseSort(schema, apiContext) - result.Pagination = parsePagination(apiContext) - result.Conditions = parseFilters(schema, apiContext) - - return *result -} - -func parseOrder(apiContext *types.APIContext) types.SortOrder { - order := apiContext.Query.Get("order") - if types.SortOrder(order) == types.DESC { - return types.DESC - } - return types.ASC -} - -func parseSort(schema *types.Schema, apiContext *types.APIContext) types.Sort { - sortField := apiContext.Query.Get("sort") - if _, ok := schema.CollectionFilters[sortField]; !ok { - sortField = "" - } - return types.Sort{ - Order: parseOrder(apiContext), - Name: sortField, - } -} - -func parsePagination(apiContext *types.APIContext) *types.Pagination { - if apiContext.Pagination != nil { - return apiContext.Pagination - } - - q := apiContext.Query - limit := q.Get("limit") - marker := q.Get("marker") - - result := &types.Pagination{ - Limit: &defaultLimit, - Marker: marker, - } - - if limit != "" { - limitInt, err := strconv.ParseInt(limit, 10, 64) - if err != nil { - return result - } - - if limitInt > maxLimit { - result.Limit = &maxLimit - } else if limitInt >= 0 { - result.Limit = &limitInt - } - } - - return result -} - -func parseNameAndOp(value string) (string, types.ModifierType) { - name := value - op := "eq" - - idx := strings.LastIndex(value, "_") - if idx > 0 { - op = value[idx+1:] - name = value[0:idx] - } - - return name, types.ModifierType(op) -} - -func parseFilters(schema *types.Schema, apiContext *types.APIContext) []*types.QueryCondition { - var conditions []*types.QueryCondition - for key, values := range apiContext.Query { - name, op := parseNameAndOp(key) - filter, ok := schema.CollectionFilters[name] - if !ok { - continue - } - - for _, mod := range filter.Modifiers { - if op != mod || !types.ValidMod(op) { - continue - } - - conditions = append(conditions, types.NewConditionFromString(name, mod, values...)) - } - } - - return conditions -} diff --git a/vendor/github.com/rancher/norman/parse/parse.go b/vendor/github.com/rancher/norman/parse/parse.go deleted file mode 100644 index 6d67c30932..0000000000 --- a/vendor/github.com/rancher/norman/parse/parse.go +++ /dev/null @@ -1,310 +0,0 @@ -package parse - -import ( - "net/http" - "net/url" - "regexp" - "strings" - - "sort" - - "github.com/rancher/norman/api/builtin" - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "github.com/rancher/norman/urlbuilder" -) - -const ( - maxFormSize = 2 * 1 << 20 -) - -var ( - multiSlashRegexp = regexp.MustCompile("//+") - allowedFormats = map[string]bool{ - "html": true, - "json": true, - "yaml": true, - } -) - -type ParsedURL struct { - Version *types.APIVersion - SchemasVersion *types.APIVersion - Type string - ID string - Link string - Method string - Action string - SubContext map[string]string - SubContextPrefix string - Query url.Values -} - -type ResolverFunc func(typeName string, context *types.APIContext) error - -type URLParser func(schema *types.Schemas, url *url.URL) (ParsedURL, error) - -func DefaultURLParser(schemas *types.Schemas, url *url.URL) (ParsedURL, error) { - result := ParsedURL{} - - path := url.EscapedPath() - path = multiSlashRegexp.ReplaceAllString(path, "/") - schemaVersion, version, prefix, parts, subContext := parseVersionAndSubContext(schemas, path) - - if version == nil { - return result, nil - } - - result.Version = version - result.SchemasVersion = schemaVersion - result.SubContext = subContext - result.SubContextPrefix = prefix - result.Action, result.Method = parseAction(url) - result.Query = url.Query() - - result.Type = safeIndex(parts, 0) - result.ID = safeIndex(parts, 1) - result.Link = safeIndex(parts, 2) - - return result, nil -} - -func Parse(rw http.ResponseWriter, req *http.Request, schemas *types.Schemas, urlParser URLParser, resolverFunc ResolverFunc) (*types.APIContext, error) { - var err error - - result := types.NewAPIContext(req, rw, schemas) - result.Method = parseMethod(req) - result.ResponseFormat = parseResponseFormat(req) - result.URLBuilder, _ = urlbuilder.New(req, types.APIVersion{}, schemas) - - // The response format is guarenteed to be set even in the event of an error - parsedURL, err := urlParser(schemas, req.URL) - // wait to check error, want to set as much as possible - - result.SubContext = parsedURL.SubContext - result.Type = parsedURL.Type - result.ID = parsedURL.ID - result.Link = parsedURL.Link - result.Action = parsedURL.Action - result.Query = parsedURL.Query - if parsedURL.Method != "" { - result.Method = parsedURL.Method - } - - result.Version = parsedURL.Version - result.SchemasVersion = parsedURL.SchemasVersion - - if err != nil { - return result, err - } - - if result.Version == nil { - result.Method = http.MethodGet - result.URLBuilder, err = urlbuilder.New(req, types.APIVersion{}, result.Schemas) - result.Type = "apiRoot" - result.Schema = result.Schemas.Schema(&builtin.Version, "apiRoot") - return result, nil - } - - result.URLBuilder, err = urlbuilder.New(req, *result.Version, result.Schemas) - if err != nil { - return result, err - } - - if parsedURL.SubContextPrefix != "" { - result.URLBuilder.SetSubContext(parsedURL.SubContextPrefix) - } - - if err := resolverFunc(result.Type, result); err != nil { - return result, err - } - - if result.Schema == nil { - if result.Type != "" { - err = httperror.NewAPIError(httperror.NotFound, "failed to find schema "+result.Type) - } - result.Method = http.MethodGet - result.Type = "apiRoot" - result.Schema = result.Schemas.Schema(&builtin.Version, "apiRoot") - result.ID = result.Version.Path - return result, err - } - - result.Type = result.Schema.ID - - if err := ValidateMethod(result); err != nil { - return result, err - } - - return result, nil -} - -func versionsForPath(schemas *types.Schemas, path string) []types.APIVersion { - var matchedVersion []types.APIVersion - for _, version := range schemas.Versions() { - if strings.HasPrefix(path, version.Path) { - afterPath := path[len(version.Path):] - // if version.Path is /v3/cluster allow /v3/clusters but not /v3/clusterstuff - if len(afterPath) < 3 || strings.Contains(afterPath[:3], "/") { - matchedVersion = append(matchedVersion, version) - } - } - } - sort.Slice(matchedVersion, func(i, j int) bool { - return len(matchedVersion[i].Path) > len(matchedVersion[j].Path) - }) - return matchedVersion -} - -func parseVersionAndSubContext(schemas *types.Schemas, escapedPath string) (*types.APIVersion, *types.APIVersion, string, []string, map[string]string) { - versions := versionsForPath(schemas, escapedPath) - if len(versions) == 0 { - return nil, nil, "", nil, nil - } - version := &versions[0] - - if strings.HasSuffix(escapedPath, "/") { - escapedPath = escapedPath[:len(escapedPath)-1] - } - - versionParts := strings.Split(version.Path, "/") - pp := strings.Split(escapedPath, "/") - var pathParts []string - for _, p := range pp { - part, err := url.PathUnescape(p) - if err == nil { - pathParts = append(pathParts, part) - } else { - pathParts = append(pathParts, p) - } - } - - paths := pathParts[len(versionParts):] - - if !version.SubContext || len(versions) < 2 { - return nil, version, "", paths, nil - } - - // Handle the special case of /v3/clusters/schema(s) - if len(paths) >= 1 && (paths[0] == "schema" || paths[0] == "schemas") { - return nil, version, "", paths, nil - } - - if len(paths) < 2 { - // Handle case like /v3/clusters/foo where /v3 and /v3/clusters are API versions. - // In this situation you want the version to be /v3 and the path "clusters", "foo" - newVersion := versions[0] - if len(paths) > 0 { - newVersion.Path = newVersion.Path + "/" + paths[0] - } - return &newVersion, &versions[1], "", pathParts[len(versionParts)-1:], nil - } - - // Length is always >= 3 - - attrs := map[string]string{ - version.SubContextSchema: paths[0], - } - - for i, version := range versions { - schema := schemas.Schema(&version, paths[1]) - if schema != nil { - if i == 0 { - break - } - return nil, &version, "", paths[1:], attrs - } - } - - return nil, version, "/" + paths[0], paths[1:], attrs -} - -func DefaultResolver(typeName string, apiContext *types.APIContext) error { - if typeName == "" { - return nil - } - - schema := apiContext.Schemas.Schema(apiContext.Version, typeName) - if schema == nil && (typeName == builtin.Schema.ID || typeName == builtin.Schema.PluralName) { - // Schemas are special, we include it as though part of the API request version - schema = apiContext.Schemas.Schema(&builtin.Version, typeName) - } - if schema == nil { - return nil - } - - apiContext.Schema = schema - return nil -} - -func safeIndex(slice []string, index int) string { - if index >= len(slice) { - return "" - } - return slice[index] -} - -func parseResponseFormat(req *http.Request) string { - format := req.URL.Query().Get("_format") - - if format != "" { - format = strings.TrimSpace(strings.ToLower(format)) - } - - /* Format specified */ - if allowedFormats[format] { - return format - } - - // User agent has Mozilla and browser accepts */* - if IsBrowser(req, true) { - return "html" - } - - if isYaml(req) { - return "yaml" - } - return "json" -} - -func isYaml(req *http.Request) bool { - return strings.Contains(req.Header.Get("Accept"), "application/yaml") -} - -func parseMethod(req *http.Request) string { - method := req.URL.Query().Get("_method") - if method == "" { - method = req.Method - } - return method -} - -func parseAction(url *url.URL) (string, string) { - action := url.Query().Get("action") - if action == "remove" { - return "", http.MethodDelete - } - - return action, "" -} - -func Body(req *http.Request) (map[string]interface{}, error) { - req.ParseMultipartForm(maxFormSize) - if req.MultipartForm != nil { - return valuesToBody(req.MultipartForm.Value), nil - } - - if req.PostForm != nil && len(req.PostForm) > 0 { - return valuesToBody(map[string][]string(req.Form)), nil - } - - return ReadBody(req) -} - -func valuesToBody(input map[string][]string) map[string]interface{} { - result := map[string]interface{}{} - for k, v := range input { - result[k] = v - } - return result -} diff --git a/vendor/github.com/rancher/norman/parse/read_input.go b/vendor/github.com/rancher/norman/parse/read_input.go deleted file mode 100644 index f90c9a1c29..0000000000 --- a/vendor/github.com/rancher/norman/parse/read_input.go +++ /dev/null @@ -1,45 +0,0 @@ -package parse - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - - "github.com/rancher/norman/httperror" - "k8s.io/apimachinery/pkg/util/yaml" -) - -const reqMaxSize = (2 * 1 << 20) + 1 - -var bodyMethods = map[string]bool{ - http.MethodPut: true, - http.MethodPost: true, -} - -type Decode func(interface{}) error - -func ReadBody(req *http.Request) (map[string]interface{}, error) { - if !bodyMethods[req.Method] { - return nil, nil - } - - decode := getDecoder(req, io.LimitReader(req.Body, maxFormSize)) - - data := map[string]interface{}{} - if err := decode(&data); err != nil { - return nil, httperror.NewAPIError(httperror.InvalidBodyContent, - fmt.Sprintf("Failed to parse body: %v", err)) - } - - return data, nil -} - -func getDecoder(req *http.Request, reader io.Reader) Decode { - if req.Header.Get("Content-type") == "application/yaml" { - return yaml.NewYAMLToJSONDecoder(reader).Decode - } - decoder := json.NewDecoder(reader) - decoder.UseNumber() - return decoder.Decode -} diff --git a/vendor/github.com/rancher/norman/parse/subcontext.go b/vendor/github.com/rancher/norman/parse/subcontext.go deleted file mode 100644 index 6e3f8459c9..0000000000 --- a/vendor/github.com/rancher/norman/parse/subcontext.go +++ /dev/null @@ -1,50 +0,0 @@ -package parse - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -type DefaultSubContextAttributeProvider struct { -} - -func (d *DefaultSubContextAttributeProvider) Query(apiContext *types.APIContext, schema *types.Schema) []*types.QueryCondition { - var result []*types.QueryCondition - - for name, value := range d.create(apiContext, schema) { - result = append(result, types.NewConditionFromString(name, types.ModifierEQ, value)) - } - - return result -} - -func (d *DefaultSubContextAttributeProvider) Create(apiContext *types.APIContext, schema *types.Schema) map[string]interface{} { - result := map[string]interface{}{} - for key, value := range d.create(apiContext, schema) { - result[key] = value - } - return result -} - -func (d *DefaultSubContextAttributeProvider) create(apiContext *types.APIContext, schema *types.Schema) map[string]string { - result := map[string]string{} - - for subContextSchemaID, value := range apiContext.SubContext { - subContextSchema := apiContext.Schemas.Schema(nil, subContextSchemaID) - if subContextSchema == nil { - continue - } - - ref := convert.ToReference(subContextSchema.ID) - fullRef := convert.ToFullReference(subContextSchema.Version.Path, subContextSchema.ID) - - for name, field := range schema.ResourceFields { - if field.Type == ref || field.Type == fullRef { - result[name] = value - break - } - } - } - - return result -} diff --git a/vendor/github.com/rancher/norman/parse/validate.go b/vendor/github.com/rancher/norman/parse/validate.go deleted file mode 100644 index cc30de08d2..0000000000 --- a/vendor/github.com/rancher/norman/parse/validate.go +++ /dev/null @@ -1,45 +0,0 @@ -package parse - -import ( - "fmt" - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" -) - -var ( - supportedMethods = map[string]bool{ - http.MethodPost: true, - http.MethodGet: true, - http.MethodPut: true, - http.MethodDelete: true, - } -) - -func ValidateMethod(request *types.APIContext) error { - if request.Action != "" && request.Method == http.MethodPost { - return nil - } - - if !supportedMethods[request.Method] { - return httperror.NewAPIError(httperror.MethodNotAllowed, fmt.Sprintf("Method %s not supported", request.Method)) - } - - if request.Type == "" || request.Schema == nil || request.Link != "" { - return nil - } - - allowed := request.Schema.ResourceMethods - if request.ID == "" { - allowed = request.Schema.CollectionMethods - } - - for _, method := range allowed { - if method == request.Method { - return nil - } - } - - return httperror.NewAPIError(httperror.MethodNotAllowed, fmt.Sprintf("Method %s not supported", request.Method)) -} diff --git a/vendor/github.com/rancher/norman/pkg/broadcast/broadcaster.go b/vendor/github.com/rancher/norman/pkg/broadcast/broadcaster.go deleted file mode 100644 index cb3e0eec0a..0000000000 --- a/vendor/github.com/rancher/norman/pkg/broadcast/broadcaster.go +++ /dev/null @@ -1,126 +0,0 @@ -package broadcast - -import ( - "context" - "sync" -) - -type ConnectFunc func() (chan map[string]interface{}, error) - -type Broadcaster struct { - sync.Mutex - running bool - subs map[chan map[string]interface{}]struct{} -} - -func (b *Broadcaster) Subscribe(ctx context.Context, connect ConnectFunc) (chan map[string]interface{}, error) { - b.Lock() - defer b.Unlock() - - if !b.running { - if err := b.start(connect); err != nil { - return nil, err - } - } - - sub := make(chan map[string]interface{}, 100) - if b.subs == nil { - b.subs = map[chan map[string]interface{}]struct{}{} - } - b.subs[sub] = struct{}{} - go func() { - <-ctx.Done() - b.unsub(sub, true) - }() - - return sub, nil -} - -func (b *Broadcaster) unsub(sub chan map[string]interface{}, lock bool) { - if lock { - b.Lock() - } - if _, ok := b.subs[sub]; ok { - close(sub) - delete(b.subs, sub) - } - if lock { - b.Unlock() - } -} - -func (b *Broadcaster) start(connect ConnectFunc) error { - c, err := connect() - if err != nil { - return err - } - - go b.stream(c) - b.running = true - return nil -} - -func (b *Broadcaster) stream(input chan map[string]interface{}) { - for item := range input { - b.Lock() - for sub := range b.subs { - newItem := cloneMap(item) - select { - case sub <- newItem: - default: - // Slow consumer, drop - go b.unsub(sub, true) - } - } - b.Unlock() - } - - b.Lock() - for sub := range b.subs { - b.unsub(sub, false) - } - b.running = false - b.Unlock() -} - -func cloneMap(data map[string]interface{}) map[string]interface{} { - if data == nil { - return nil - } - - result := map[string]interface{}{} - for k, v := range data { - result[k] = cloneValue(v) - } - - return result -} - -func cloneValue(v interface{}) interface{} { - switch t := v.(type) { - case []interface{}: - return cloneSlice(t) - case []map[string]interface{}: - return cloneMapSlice(t) - case map[string]interface{}: - return cloneMap(t) - default: - return v - } -} - -func cloneMapSlice(data []map[string]interface{}) []interface{} { - result := make([]interface{}, len(data)) - for i := range data { - result[i] = cloneValue(data[i]) - } - return result -} - -func cloneSlice(data []interface{}) []interface{} { - result := make([]interface{}, len(data)) - for i := range data { - result[i] = cloneValue(data[i]) - } - return result -} diff --git a/vendor/github.com/rancher/norman/pkg/changeset/changeset.go b/vendor/github.com/rancher/norman/pkg/changeset/changeset.go deleted file mode 100644 index d6c5a673c1..0000000000 --- a/vendor/github.com/rancher/norman/pkg/changeset/changeset.go +++ /dev/null @@ -1,74 +0,0 @@ -package changeset - -import ( - "context" - "strings" - - "github.com/rancher/norman/controller" - "k8s.io/apimachinery/pkg/runtime" -) - -type Key struct { - Namespace string - Name string -} - -type ControllerProvider interface { - Generic() controller.GenericController -} - -type Enqueuer interface { - Enqueue(namespace, name string) -} - -type Resolver func(namespace, name string, obj runtime.Object) ([]Key, error) - -func Watch(ctx context.Context, name string, resolve Resolver, enq Enqueuer, controllers ...ControllerProvider) { - for _, c := range controllers { - watch(ctx, name, enq, resolve, c.Generic()) - } -} - -func watch(ctx context.Context, name string, enq Enqueuer, resolve Resolver, genericController controller.GenericController) { - genericController.AddHandler(ctx, name, func(key string, obj interface{}) (interface{}, error) { - obj, exists, err := genericController.Informer().GetStore().GetByKey(key) - if err != nil { - return nil, err - } - - if !exists { - obj = nil - } - - var ( - ns string - name string - ) - - parts := strings.SplitN(key, "/", 2) - if len(parts) == 2 { - ns = parts[0] - name = parts[1] - } else { - name = parts[0] - } - - ro, ok := obj.(runtime.Object) - if !ok { - ro = nil - } - - keys, err := resolve(ns, name, ro) - if err != nil { - return nil, err - } - - for _, key := range keys { - if key.Name != "" { - enq.Enqueue(key.Namespace, key.Name) - } - } - - return nil, nil - }) -} diff --git a/vendor/github.com/rancher/norman/pkg/clientaccess/clientaccess.go b/vendor/github.com/rancher/norman/pkg/clientaccess/clientaccess.go deleted file mode 100644 index 8fcaf5ad44..0000000000 --- a/vendor/github.com/rancher/norman/pkg/clientaccess/clientaccess.go +++ /dev/null @@ -1,277 +0,0 @@ -package clientaccess - -import ( - "crypto/sha256" - "crypto/tls" - "crypto/x509" - "encoding/hex" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "os" - "strings" - - "github.com/pkg/errors" - "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" -) - -var ( - insecureClient = &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - }, - } -) - -type OverrideURLCallback func(config []byte) (*url.URL, error) - -type clientToken struct { - caHash string - username string - password string -} - -func AgentAccessInfoToTempKubeConfig(tempDir, server, token string) (string, error) { - f, err := ioutil.TempFile(tempDir, "tmp-") - if err != nil { - return "", err - } - if err := f.Close(); err != nil { - return "", err - } - err = accessInfoToKubeConfig(f.Name(), server, token) - if err != nil { - os.Remove(f.Name()) - } - return f.Name(), err -} - -func AgentAccessInfoToKubeConfig(destFile, server, token string) error { - return accessInfoToKubeConfig(destFile, server, token) -} - -type Info struct { - URL string `json:"url,omitempty"` - CACerts []byte `json:"cacerts,omitempty"` - username string - password string - Token string `json:"token,omitempty"` -} - -func (i *Info) WriteKubeConfig(destFile string) error { - return clientcmd.WriteToFile(*i.KubeConfig(), destFile) -} - -func (i *Info) KubeConfig() *clientcmdapi.Config { - config := clientcmdapi.NewConfig() - - cluster := clientcmdapi.NewCluster() - cluster.CertificateAuthorityData = i.CACerts - cluster.Server = i.URL - - authInfo := clientcmdapi.NewAuthInfo() - if i.password != "" { - authInfo.Username = i.username - authInfo.Password = i.password - } else if i.Token != "" { - if username, pass, ok := ParseUsernamePassword(i.Token); ok { - authInfo.Username = username - authInfo.Password = pass - } else { - authInfo.Token = i.Token - } - } - - context := clientcmdapi.NewContext() - context.AuthInfo = "default" - context.Cluster = "default" - - config.Clusters["default"] = cluster - config.AuthInfos["default"] = authInfo - config.Contexts["default"] = context - config.CurrentContext = "default" - - return config -} - -func ParseAndValidateToken(server, token string) (*Info, error) { - url, err := url.Parse(server) - if err != nil { - return nil, errors.Wrapf(err, "Invalid url, failed to parse %s", server) - } - - if url.Scheme != "https" { - return nil, fmt.Errorf("only https:// URLs are supported, invalid scheme: %s", server) - } - - for strings.HasSuffix(url.Path, "/") { - url.Path = url.Path[:len(url.Path)-1] - } - - parsedToken, err := parseToken(token) - if err != nil { - return nil, err - } - - cacerts, err := GetCACerts(*url) - if err != nil { - return nil, err - } - - if len(cacerts) > 0 && len(parsedToken.caHash) > 0 { - if ok, hash, newHash := validateCACerts(cacerts, parsedToken.caHash); !ok { - return nil, fmt.Errorf("token does not match the server %s != %s", hash, newHash) - } - } - - if err := validateToken(*url, cacerts, parsedToken.username, parsedToken.password); err != nil { - return nil, err - } - - return &Info{ - URL: url.String(), - CACerts: cacerts, - username: parsedToken.username, - password: parsedToken.password, - Token: token, - }, nil -} - -func accessInfoToKubeConfig(destFile, server, token string) error { - info, err := ParseAndValidateToken(server, token) - if err != nil { - return err - } - - return info.WriteKubeConfig(destFile) -} - -func validateToken(u url.URL, cacerts []byte, username, password string) error { - u.Path = "/apis" - _, err := get(u.String(), GetHTTPClient(cacerts), username, password) - if err != nil { - return errors.Wrap(err, "token is not valid") - } - return nil -} - -func validateCACerts(cacerts []byte, hash string) (bool, string, string) { - if len(cacerts) == 0 && hash == "" { - return true, "", "" - } - - digest := sha256.Sum256([]byte(cacerts)) - newHash := hex.EncodeToString(digest[:]) - return hash == newHash, hash, newHash -} - -func ParseUsernamePassword(token string) (string, string, bool) { - parsed, err := parseToken(token) - if err != nil { - return "", "", false - } - return parsed.username, parsed.password, true -} - -func parseToken(token string) (clientToken, error) { - var result clientToken - - if !strings.HasPrefix(token, "K10") { - return result, fmt.Errorf("token is not a valid token format") - } - - token = token[3:] - - parts := strings.SplitN(token, "::", 2) - token = parts[0] - if len(parts) > 1 { - result.caHash = parts[0] - token = parts[1] - } - - parts = strings.SplitN(token, ":", 2) - if len(parts) != 2 { - return result, fmt.Errorf("token credentials are the wrong format") - } - - result.username = parts[0] - result.password = parts[1] - - return result, nil -} - -func GetHTTPClient(cacerts []byte) *http.Client { - if len(cacerts) == 0 { - return http.DefaultClient - } - - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(cacerts) - - return &http.Client{ - Transport: &http.Transport{ - DisableKeepAlives: true, - TLSClientConfig: &tls.Config{ - RootCAs: pool, - }, - }, - } -} - -func Get(path string, info *Info) ([]byte, error) { - u, err := url.Parse(info.URL) - if err != nil { - return nil, err - } - u.Path = path - return get(u.String(), GetHTTPClient(info.CACerts), info.username, info.password) -} - -func GetCACerts(u url.URL) ([]byte, error) { - u.Path = "/cacerts" - url := u.String() - - _, err := get(url, http.DefaultClient, "", "") - if err == nil { - return nil, nil - } - - cacerts, err := get(url, insecureClient, "", "") - if err != nil { - return nil, errors.Wrapf(err, "failed to get CA certs at %s", url) - } - - _, err = get(url, GetHTTPClient(cacerts), "", "") - if err != nil { - return nil, errors.Wrapf(err, "server %s is not trusted", url) - } - - return cacerts, nil -} - -func get(u string, client *http.Client, username, password string) ([]byte, error) { - req, err := http.NewRequest(http.MethodGet, u, nil) - if err != nil { - return nil, err - } - - if username != "" { - req.SetBasicAuth(username, password) - } - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s: %s", u, resp.Status) - } - - return ioutil.ReadAll(resp.Body) -} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/desiredset.go b/vendor/github.com/rancher/norman/pkg/objectset/desiredset.go deleted file mode 100644 index 536fec67c7..0000000000 --- a/vendor/github.com/rancher/norman/pkg/objectset/desiredset.go +++ /dev/null @@ -1,55 +0,0 @@ -package objectset - -import ( - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/pkg/objectset/injectors" - "github.com/rancher/norman/types" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/discovery" - "k8s.io/client-go/rest" -) - -type DesiredSet struct { - discoveredClients map[schema.GroupVersionKind]*objectclient.ObjectClient - namespaced map[schema.GroupVersionKind]bool - discovery discovery.DiscoveryInterface - restConfig rest.Config - remove bool - setID string - objs *ObjectSet - codeVersion string - clients map[schema.GroupVersionKind]Client - patchers map[schema.GroupVersionKind]Patcher - owner runtime.Object - injectors []injectors.ConfigInjector - errs []error -} - -func (o *DesiredSet) AddDiscoveredClient(gvk schema.GroupVersionKind, client *objectclient.ObjectClient, namespaced bool) { - if o.discoveredClients == nil { - o.discoveredClients = map[schema.GroupVersionKind]*objectclient.ObjectClient{} - } - o.discoveredClients[gvk] = client - if o.namespaced == nil { - o.namespaced = map[schema.GroupVersionKind]bool{} - } - o.namespaced[gvk] = namespaced -} - -func (o *DesiredSet) DiscoveredClients() map[schema.GroupVersionKind]*objectclient.ObjectClient { - return o.discoveredClients -} - -func (o *DesiredSet) AddInjector(inj injectors.ConfigInjector) { - o.injectors = append(o.injectors, inj) -} - -func (o *DesiredSet) err(err error) error { - o.errs = append(o.errs, err) - return o.Err() -} - -func (o *DesiredSet) Err() error { - return types.NewErrors(append(o.objs.errs, o.errs...)...) -} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_process.go b/vendor/github.com/rancher/norman/pkg/objectset/desiredset_process.go deleted file mode 100644 index 4ab43fb4a6..0000000000 --- a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_process.go +++ /dev/null @@ -1,279 +0,0 @@ -package objectset - -import ( - "fmt" - "sort" - - "github.com/pkg/errors" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/restwatch" - "github.com/rancher/norman/types" - "github.com/sirupsen/logrus" - errors2 "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - types2 "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/discovery" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/cache" -) - -var ( - defaultNamespace = "default" - deletePolicy = v1.DeletePropagationBackground - ErrReplace = errors.New("replace object with changes") - ReplaceOnChange = func(name string, o runtime.Object, patchType types2.PatchType, data []byte, subresources ...string) (runtime.Object, error) { - return nil, ErrReplace - } -) - -func NewDiscoveredClient(gvk schema.GroupVersionKind, restConfig rest.Config, discovery discovery.DiscoveryInterface) (*objectclient.ObjectClient, bool, error) { - resources, err := discovery.ServerResourcesForGroupVersion(gvk.GroupVersion().String()) - if err != nil { - return nil, false, err - } - - for _, resource := range resources.APIResources { - if resource.Kind != gvk.Kind { - continue - } - - if restConfig.NegotiatedSerializer == nil { - restConfig.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - restClient, err := restwatch.UnversionedRESTClientFor(&restConfig) - if err != nil { - return nil, false, err - } - - objectClient := objectclient.NewObjectClient("", restClient, &resource, gvk, &objectclient.UnstructuredObjectFactory{}) - return objectClient, resource.Namespaced, nil - } - - return nil, false, fmt.Errorf("failed to discover client for %s", gvk) -} - -func (o *DesiredSet) getControllerAndObjectClient(debugID string, gvk schema.GroupVersionKind) (controller.GenericController, *objectclient.ObjectClient, error) { - client, ok := o.clients[gvk] - if !ok && o.discovery == nil { - return nil, nil, fmt.Errorf("failed to find client for %s for %s", gvk, debugID) - } - - if client != nil { - return client.Generic(), client.ObjectClient(), nil - } - - objectClient := o.discoveredClients[gvk] - if objectClient != nil { - return nil, objectClient, nil - } - - objectClient, namespaced, err := NewDiscoveredClient(gvk, o.restConfig, o.discovery) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to find client for %s for %s", gvk, debugID) - } - - o.AddDiscoveredClient(gvk, objectClient, namespaced) - return nil, objectClient, nil -} - -func (o *DesiredSet) adjustNamespace(gvk schema.GroupVersionKind, objs map[objectKey]runtime.Object) error { - namespaced, ok := o.namespaced[gvk] - if !ok || !namespaced { - return nil - } - - for k, v := range objs { - if k.namespace != "" { - continue - } - - v = v.DeepCopyObject() - meta, err := meta.Accessor(v) - if err != nil { - return err - } - - meta.SetNamespace(defaultNamespace) - - delete(objs, k) - k.namespace = defaultNamespace - objs[k] = v - } - - return nil -} - -func (o *DesiredSet) process(inputID, debugID string, set labels.Selector, gvk schema.GroupVersionKind, objs map[objectKey]runtime.Object) { - controller, objectClient, err := o.getControllerAndObjectClient(debugID, gvk) - if err != nil { - o.err(err) - return - } - - if err := o.adjustNamespace(gvk, objs); err != nil { - o.err(err) - return - } - - patcher, ok := o.patchers[gvk] - if !ok { - patcher = objectClient.Patch - } - - existing, err := list(controller, objectClient, set) - if err != nil { - o.err(fmt.Errorf("failed to list %s for %s", gvk, debugID)) - return - } - - toCreate, toDelete, toUpdate := compareSets(existing, objs) - - createF := func(k objectKey) { - obj := objs[k] - obj, err := prepareObjectForCreate(inputID, obj) - if err != nil { - o.err(errors.Wrapf(err, "failed to prepare create %s %s for %s", k, gvk, debugID)) - return - } - - _, err = objectClient.Create(obj) - if errors2.IsAlreadyExists(err) { - // Taking over an object that wasn't previously managed by us - existingObj, err := objectClient.GetNamespaced(k.namespace, k.name, v1.GetOptions{}) - if err == nil { - toUpdate = append(toUpdate, k) - existing[k] = existingObj - return - } - } - if err != nil { - o.err(errors.Wrapf(err, "failed to create %s %s for %s", k, gvk, debugID)) - return - } - logrus.Debugf("DesiredSet - Created %s %s for %s", gvk, k, debugID) - } - - deleteF := func(k objectKey) { - err := objectClient.DeleteNamespaced(k.namespace, k.name, &v1.DeleteOptions{ - PropagationPolicy: &deletePolicy, - }) - if err != nil { - o.err(errors.Wrapf(err, "failed to delete %s %s for %s", k, gvk, debugID)) - return - } - logrus.Debugf("DesiredSet - Delete %s %s for %s", gvk, k, debugID) - } - - updateF := func(k objectKey) { - err := o.compareObjects(patcher, objectClient, debugID, inputID, existing[k], objs[k], len(toCreate) > 0 || len(toDelete) > 0) - if err == ErrReplace { - deleteF(k) - o.err(fmt.Errorf("DesiredSet - Replace Wait %s %s for %s", gvk, k, debugID)) - } else if err != nil { - o.err(errors.Wrapf(err, "failed to update %s %s for %s", k, gvk, debugID)) - } - } - - for _, k := range toCreate { - createF(k) - } - - for _, k := range toUpdate { - updateF(k) - } - - for _, k := range toDelete { - deleteF(k) - } -} - -func compareSets(existingSet, newSet map[objectKey]runtime.Object) (toCreate, toDelete, toUpdate []objectKey) { - for k := range newSet { - if _, ok := existingSet[k]; ok { - toUpdate = append(toUpdate, k) - } else { - toCreate = append(toCreate, k) - } - } - - for k := range existingSet { - if _, ok := newSet[k]; !ok { - toDelete = append(toDelete, k) - } - } - - sortObjectKeys(toCreate) - sortObjectKeys(toDelete) - sortObjectKeys(toUpdate) - - return -} - -func sortObjectKeys(keys []objectKey) { - sort.Slice(keys, func(i, j int) bool { - return keys[i].String() < keys[j].String() - }) -} - -func addObjectToMap(objs map[objectKey]runtime.Object, obj interface{}) error { - metadata, err := meta.Accessor(obj) - if err != nil { - return err - } - - objs[objectKey{ - namespace: metadata.GetNamespace(), - name: metadata.GetName(), - }] = obj.(runtime.Object) - - return nil -} - -func list(controller controller.GenericController, objectClient *objectclient.ObjectClient, selector labels.Selector) (map[objectKey]runtime.Object, error) { - var ( - errs []error - objs = map[objectKey]runtime.Object{} - ) - - if controller == nil { - objList, err := objectClient.List(v1.ListOptions{ - LabelSelector: selector.String(), - }) - if err != nil { - return nil, err - } - - list, ok := objList.(*unstructured.UnstructuredList) - if !ok { - return nil, fmt.Errorf("invalid list type %T", objList) - } - - for _, obj := range list.Items { - copy := obj - if err := addObjectToMap(objs, ©); err != nil { - errs = append(errs, err) - } - } - - return objs, types.NewErrors(errs...) - } - - err := cache.ListAllByNamespace(controller.Informer().GetIndexer(), "", selector, func(obj interface{}) { - if err := addObjectToMap(objs, obj); err != nil { - errs = append(errs, err) - } - }) - if err != nil { - errs = append(errs, err) - } - - return objs, types.NewErrors(errs...) -} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/injectors/marshal.go b/vendor/github.com/rancher/norman/pkg/objectset/injectors/marshal.go deleted file mode 100644 index 45a4dda5ad..0000000000 --- a/vendor/github.com/rancher/norman/pkg/objectset/injectors/marshal.go +++ /dev/null @@ -1,55 +0,0 @@ -package injectors - -import ( - "bufio" - "bytes" - "io" - - "github.com/ghodss/yaml" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - yamlDecoder "k8s.io/apimachinery/pkg/util/yaml" -) - -func ToBytes(objects []runtime.Object) ([]byte, error) { - if len(objects) == 0 { - return nil, nil - } - - buffer := &bytes.Buffer{} - for i, obj := range objects { - if i > 0 { - buffer.WriteString("\n---\n") - } - - bytes, err := yaml.Marshal(obj) - if err != nil { - return nil, errors.Wrapf(err, "failed to encode %s", obj.GetObjectKind().GroupVersionKind()) - } - buffer.Write(bytes) - } - - return buffer.Bytes(), nil -} - -func FromBytes(content []byte) ([]runtime.Object, error) { - var result []runtime.Object - - reader := yamlDecoder.NewYAMLReader(bufio.NewReader(bytes.NewBuffer(content))) - for { - raw, err := reader.Read() - if err == io.EOF { - break - } - - data := map[string]interface{}{} - if err := yaml.Unmarshal(raw, &data); err != nil { - return nil, err - } - - result = append(result, &unstructured.Unstructured{Object: data}) - } - - return result, nil -} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/template.go b/vendor/github.com/rancher/norman/pkg/objectset/template.go deleted file mode 100644 index b36f092ea6..0000000000 --- a/vendor/github.com/rancher/norman/pkg/objectset/template.go +++ /dev/null @@ -1,95 +0,0 @@ -package objectset - -import ( - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/discovery" - "k8s.io/client-go/rest" -) - -type Client interface { - Generic() controller.GenericController - ObjectClient() *objectclient.ObjectClient -} - -type Patcher func(name string, o runtime.Object, patchType types.PatchType, data []byte, subresources ...string) (runtime.Object, error) - -type Processor struct { - setID string - codeVersion string - discovery discovery.DiscoveryInterface - restConfig rest.Config - allowSlowPath string - slowClient rest.HTTPClient - clients map[schema.GroupVersionKind]Client - patchers map[schema.GroupVersionKind]Patcher -} - -func NewProcessor(setID string) *Processor { - return &Processor{ - setID: setID, - clients: map[schema.GroupVersionKind]Client{}, - } -} - -func (t *Processor) SetID() string { - return t.setID -} - -func (t *Processor) CodeVersion(version string) *Processor { - t.codeVersion = version - return t -} - -func (t *Processor) AllowDiscovery(discovery discovery.DiscoveryInterface, restConfig rest.Config) *Processor { - t.discovery = discovery - t.restConfig = restConfig - return t -} - -func (t *Processor) Clients() map[schema.GroupVersionKind]Client { - return t.clients -} - -func (t *Processor) Client(clients ...Client) *Processor { - // ensure cache is enabled - for _, client := range clients { - client.Generic() - t.clients[client.ObjectClient().GroupVersionKind()] = client - } - return t -} - -func (t *Processor) Patcher(gvk schema.GroupVersionKind, patcher Patcher) *Processor { - if t.patchers == nil { - t.patchers = map[schema.GroupVersionKind]Patcher{} - } - t.patchers[gvk] = patcher - return t -} - -func (t Processor) Remove(owner runtime.Object) error { - return t.NewDesiredSet(owner, nil).Apply() -} - -func (t Processor) NewDesiredSet(owner runtime.Object, objs *ObjectSet) *DesiredSet { - remove := false - if objs == nil { - remove = true - objs = &ObjectSet{} - } - return &DesiredSet{ - discovery: t.discovery, - restConfig: t.restConfig, - remove: remove, - objs: objs, - setID: t.setID, - codeVersion: t.codeVersion, - clients: t.clients, - patchers: t.patchers, - owner: owner, - } -} diff --git a/vendor/github.com/rancher/norman/pkg/proxy/proxy_server.go b/vendor/github.com/rancher/norman/pkg/proxy/proxy_server.go deleted file mode 100644 index 3da29113b6..0000000000 --- a/vendor/github.com/rancher/norman/pkg/proxy/proxy_server.go +++ /dev/null @@ -1,65 +0,0 @@ -package proxy - -import ( - "crypto/tls" - "crypto/x509" - "net/http" - "net/url" - - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/proxy" - "k8s.io/client-go/rest" -) - -var ( - er = &errorResponder{} -) - -type errorResponder struct { -} - -func (e *errorResponder) Error(w http.ResponseWriter, req *http.Request, err error) { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(err.Error())) -} - -type SimpleProxy struct { - url *url.URL - transport http.RoundTripper - overrideHostHeader bool -} - -func NewSimpleProxy(host string, caData []byte, overrideHostHeader bool) (*SimpleProxy, error) { - hostURL, _, err := rest.DefaultServerURL(host, "", schema.GroupVersion{}, true) - if err != nil { - return nil, err - } - - ht := &http.Transport{} - if len(caData) > 0 { - certPool := x509.NewCertPool() - certPool.AppendCertsFromPEM(caData) - ht.TLSClientConfig = &tls.Config{ - RootCAs: certPool, - } - } - - return &SimpleProxy{ - url: hostURL, - transport: ht, - overrideHostHeader: overrideHostHeader, - }, nil -} - -func (s *SimpleProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - u := *s.url - u.Path = req.URL.Path - u.RawQuery = req.URL.RawQuery - req.URL.Scheme = "https" - req.URL.Host = req.Host - if s.overrideHostHeader { - req.Host = u.Host - } - httpProxy := proxy.NewUpgradeAwareHandler(&u, s.transport, false, false, er) - httpProxy.ServeHTTP(rw, req) -} diff --git a/vendor/github.com/rancher/norman/restwatch/rest.go b/vendor/github.com/rancher/norman/restwatch/rest.go deleted file mode 100644 index 25092052e2..0000000000 --- a/vendor/github.com/rancher/norman/restwatch/rest.go +++ /dev/null @@ -1,43 +0,0 @@ -package restwatch - -import ( - "time" - - "k8s.io/client-go/rest" -) - -type WatchClient interface { - WatchClient() rest.Interface -} - -func UnversionedRESTClientFor(config *rest.Config) (rest.Interface, error) { - client, err := rest.UnversionedRESTClientFor(config) - if err != nil { - return nil, err - } - - if config.Timeout == 0 { - return client, err - } - - newConfig := *config - newConfig.Timeout = time.Hour - watchClient, err := rest.UnversionedRESTClientFor(&newConfig) - if err != nil { - return nil, err - } - - return &clientWithWatch{ - RESTClient: client, - watchClient: watchClient, - }, nil -} - -type clientWithWatch struct { - *rest.RESTClient - watchClient *rest.RESTClient -} - -func (c *clientWithWatch) WatchClient() rest.Interface { - return c.watchClient -} diff --git a/vendor/github.com/rancher/norman/signal/sigterm.go b/vendor/github.com/rancher/norman/signal/sigterm.go deleted file mode 100644 index cf2e3b5576..0000000000 --- a/vendor/github.com/rancher/norman/signal/sigterm.go +++ /dev/null @@ -1,28 +0,0 @@ -package signal - -import ( - "context" - "os" - "os/signal" - "syscall" - - "github.com/sirupsen/logrus" -) - -func SigTermCancelContext(ctx context.Context) context.Context { - term := make(chan os.Signal) - signal.Notify(term, os.Interrupt, syscall.SIGTERM) - - ctx, cancel := context.WithCancel(ctx) - - go func() { - select { - case <-term: - logrus.Infof("Received SIGTERM, cancelling") - cancel() - case <-ctx.Done(): - } - }() - - return ctx -} diff --git a/vendor/github.com/rancher/norman/store/crd/init.go b/vendor/github.com/rancher/norman/store/crd/init.go deleted file mode 100644 index 6c40c0c7fa..0000000000 --- a/vendor/github.com/rancher/norman/store/crd/init.go +++ /dev/null @@ -1,224 +0,0 @@ -package crd - -import ( - "context" - "fmt" - "strings" - "sync" - "time" - - "github.com/rancher/norman/store/proxy" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/sirupsen/logrus" - apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/rest" -) - -type Factory struct { - wg sync.WaitGroup - ClientGetter proxy.ClientGetter -} - -func NewFactoryFromClientGetter(clientGetter proxy.ClientGetter) *Factory { - return &Factory{ - ClientGetter: clientGetter, - } -} - -func NewFactoryFromClient(config rest.Config) (*Factory, error) { - getter, err := proxy.NewClientGetterFromConfig(config) - if err != nil { - return nil, err - } - - return &Factory{ - ClientGetter: getter, - }, nil -} - -func (f *Factory) BatchWait() { - f.wg.Wait() -} - -func (f *Factory) BatchCreateCRDs(ctx context.Context, storageContext types.StorageContext, schemas *types.Schemas, version *types.APIVersion, schemaIDs ...string) { - f.wg.Add(1) - go func() { - defer f.wg.Done() - - var schemasToCreate []*types.Schema - - for _, schemaID := range schemaIDs { - s := schemas.Schema(version, schemaID) - if s == nil { - panic("can not find schema " + schemaID) - } - schemasToCreate = append(schemasToCreate, s) - } - - err := f.AssignStores(ctx, storageContext, schemasToCreate...) - if err != nil { - panic("creating CRD store " + err.Error()) - } - }() -} - -func (f *Factory) AssignStores(ctx context.Context, storageContext types.StorageContext, schemas ...*types.Schema) error { - schemaStatus, err := f.CreateCRDs(ctx, storageContext, schemas...) - if err != nil { - return err - } - - for _, schema := range schemas { - crd, ok := schemaStatus[schema] - if !ok { - return fmt.Errorf("failed to create create/find CRD for %s", schema.ID) - } - - schema.Store = proxy.NewProxyStore(ctx, f.ClientGetter, - storageContext, - []string{"apis"}, - crd.Spec.Group, - crd.Spec.Version, - crd.Status.AcceptedNames.Kind, - crd.Status.AcceptedNames.Plural) - } - - return nil -} - -func (f *Factory) CreateCRDs(ctx context.Context, storageContext types.StorageContext, schemas ...*types.Schema) (map[*types.Schema]*apiext.CustomResourceDefinition, error) { - schemaStatus := map[*types.Schema]*apiext.CustomResourceDefinition{} - - apiClient, err := f.ClientGetter.APIExtClient(nil, storageContext) - if err != nil { - return nil, err - } - - ready, err := f.getReadyCRDs(apiClient) - if err != nil { - return nil, err - } - - for _, schema := range schemas { - crd, err := f.createCRD(apiClient, schema, ready) - if err != nil { - return nil, err - } - schemaStatus[schema] = crd - } - - ready, err = f.getReadyCRDs(apiClient) - if err != nil { - return nil, err - } - - for schema, crd := range schemaStatus { - if readyCrd, ok := ready[crd.Name]; ok { - schemaStatus[schema] = readyCrd - } else { - if err := f.waitCRD(ctx, apiClient, crd.Name, schema, schemaStatus); err != nil { - return nil, err - } - } - } - - return schemaStatus, nil -} - -func (f *Factory) waitCRD(ctx context.Context, apiClient clientset.Interface, crdName string, schema *types.Schema, schemaStatus map[*types.Schema]*apiext.CustomResourceDefinition) error { - logrus.Infof("Waiting for CRD %s to become available", crdName) - defer logrus.Infof("Done waiting for CRD %s to become available", crdName) - - first := true - return wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) { - if !first { - logrus.Infof("Waiting for CRD %s to become available", crdName) - } - first = false - - crd, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crdName, metav1.GetOptions{}) - if err != nil { - return false, err - } - - for _, cond := range crd.Status.Conditions { - switch cond.Type { - case apiext.Established: - if cond.Status == apiext.ConditionTrue { - schemaStatus[schema] = crd - return true, err - } - case apiext.NamesAccepted: - if cond.Status == apiext.ConditionFalse { - logrus.Infof("Name conflict on %s: %v\n", crdName, cond.Reason) - } - } - } - - return false, ctx.Err() - }) -} - -func (f *Factory) createCRD(apiClient clientset.Interface, schema *types.Schema, ready map[string]*apiext.CustomResourceDefinition) (*apiext.CustomResourceDefinition, error) { - plural := strings.ToLower(schema.PluralName) - name := strings.ToLower(plural + "." + schema.Version.Group) - - crd, ok := ready[name] - if ok { - return crd, nil - } - - crd = &apiext.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: apiext.CustomResourceDefinitionSpec{ - Group: schema.Version.Group, - Version: schema.Version.Version, - Names: apiext.CustomResourceDefinitionNames{ - Plural: plural, - Kind: convert.Capitalize(schema.ID), - }, - }, - } - - if schema.Scope == types.NamespaceScope { - crd.Spec.Scope = apiext.NamespaceScoped - } else { - crd.Spec.Scope = apiext.ClusterScoped - } - - logrus.Infof("Creating CRD %s", name) - crd, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd) - if errors.IsAlreadyExists(err) { - return crd, nil - } - return crd, err -} - -func (f *Factory) getReadyCRDs(apiClient clientset.Interface) (map[string]*apiext.CustomResourceDefinition, error) { - list, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(metav1.ListOptions{}) - if err != nil { - return nil, err - } - - result := map[string]*apiext.CustomResourceDefinition{} - - for i, crd := range list.Items { - for _, cond := range crd.Status.Conditions { - switch cond.Type { - case apiext.Established: - if cond.Status == apiext.ConditionTrue { - result[crd.Name] = &list.Items[i] - } - } - } - } - - return result, nil -} diff --git a/vendor/github.com/rancher/norman/store/empty/empty_store.go b/vendor/github.com/rancher/norman/store/empty/empty_store.go deleted file mode 100644 index 64850db759..0000000000 --- a/vendor/github.com/rancher/norman/store/empty/empty_store.go +++ /dev/null @@ -1,36 +0,0 @@ -package empty - -import ( - "github.com/rancher/norman/types" -) - -type Store struct { -} - -func (e *Store) Context() types.StorageContext { - return types.DefaultStorageContext -} - -func (e *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - return nil, nil -} - -func (e *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - return nil, nil -} - -func (e *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { - return nil, nil -} - -func (e *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) { - return nil, nil -} - -func (e *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) { - return nil, nil -} - -func (e *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - return nil, nil -} diff --git a/vendor/github.com/rancher/norman/store/proxy/error_wrapper.go b/vendor/github.com/rancher/norman/store/proxy/error_wrapper.go deleted file mode 100644 index 2d5d6d23c7..0000000000 --- a/vendor/github.com/rancher/norman/store/proxy/error_wrapper.go +++ /dev/null @@ -1,52 +0,0 @@ -package proxy - -import ( - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "k8s.io/apimachinery/pkg/api/errors" -) - -type errorStore struct { - types.Store -} - -func (e *errorStore) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - data, err := e.Store.ByID(apiContext, schema, id) - return data, translateError(err) -} - -func (e *errorStore) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { - data, err := e.Store.List(apiContext, schema, opt) - return data, translateError(err) -} - -func (e *errorStore) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) { - data, err := e.Store.Create(apiContext, schema, data) - return data, translateError(err) - -} - -func (e *errorStore) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) { - data, err := e.Store.Update(apiContext, schema, data, id) - return data, translateError(err) - -} - -func (e *errorStore) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - data, err := e.Store.Delete(apiContext, schema, id) - return data, translateError(err) - -} - -func (e *errorStore) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - data, err := e.Store.Watch(apiContext, schema, opt) - return data, translateError(err) -} - -func translateError(err error) error { - if apiError, ok := err.(errors.APIStatus); ok { - status := apiError.Status() - return httperror.NewAPIErrorLong(int(status.Code), string(status.Reason), status.Message) - } - return err -} diff --git a/vendor/github.com/rancher/norman/store/proxy/proxy_store.go b/vendor/github.com/rancher/norman/store/proxy/proxy_store.go deleted file mode 100644 index 245e72a900..0000000000 --- a/vendor/github.com/rancher/norman/store/proxy/proxy_store.go +++ /dev/null @@ -1,506 +0,0 @@ -package proxy - -import ( - "context" - ejson "encoding/json" - "net/http" - "strings" - "sync" - "time" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/objectclient/dynamic" - "github.com/rancher/norman/pkg/broadcast" - "github.com/rancher/norman/restwatch" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/convert/merge" - "github.com/rancher/norman/types/values" - "github.com/sirupsen/logrus" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/apimachinery/pkg/api/errors" - 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/json" - "k8s.io/apimachinery/pkg/runtime/serializer/streaming" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/rest" - restclientwatch "k8s.io/client-go/rest/watch" -) - -var ( - userAuthHeader = "Impersonate-User" - authHeaders = []string{ - userAuthHeader, - "Impersonate-Group", - } -) - -type ClientGetter interface { - UnversionedClient(apiContext *types.APIContext, context types.StorageContext) (rest.Interface, error) - APIExtClient(apiContext *types.APIContext, context types.StorageContext) (clientset.Interface, error) -} - -type simpleClientGetter struct { - restConfig rest.Config - client rest.Interface - apiExtClient clientset.Interface -} - -func NewClientGetterFromConfig(config rest.Config) (ClientGetter, error) { - dynamicConfig := config - if dynamicConfig.NegotiatedSerializer == nil { - dynamicConfig.NegotiatedSerializer = dynamic.NegotiatedSerializer - } - - unversionedClient, err := rest.UnversionedRESTClientFor(&dynamicConfig) - if err != nil { - return nil, err - } - - apiExtClient, err := clientset.NewForConfig(&dynamicConfig) - if err != nil { - return nil, err - } - - return &simpleClientGetter{ - restConfig: config, - client: unversionedClient, - apiExtClient: apiExtClient, - }, nil -} - -func (s *simpleClientGetter) Config(apiContext *types.APIContext, context types.StorageContext) (rest.Config, error) { - return s.restConfig, nil -} - -func (s *simpleClientGetter) UnversionedClient(apiContext *types.APIContext, context types.StorageContext) (rest.Interface, error) { - return s.client, nil -} - -func (s *simpleClientGetter) APIExtClient(apiContext *types.APIContext, context types.StorageContext) (clientset.Interface, error) { - return s.apiExtClient, nil -} - -type Store struct { - sync.Mutex - - clientGetter ClientGetter - storageContext types.StorageContext - prefix []string - group string - version string - kind string - resourcePlural string - authContext map[string]string - close context.Context - broadcasters map[rest.Interface]*broadcast.Broadcaster -} - -func NewProxyStore(ctx context.Context, clientGetter ClientGetter, storageContext types.StorageContext, - prefix []string, group, version, kind, resourcePlural string) types.Store { - return &errorStore{ - Store: &Store{ - clientGetter: clientGetter, - storageContext: storageContext, - prefix: prefix, - group: group, - version: version, - kind: kind, - resourcePlural: resourcePlural, - authContext: map[string]string{ - "apiGroup": group, - "resource": resourcePlural, - }, - close: ctx, - broadcasters: map[rest.Interface]*broadcast.Broadcaster{}, - }, - } -} - -func (s *Store) getUser(apiContext *types.APIContext) string { - return apiContext.Request.Header.Get(userAuthHeader) -} - -func (s *Store) doAuthed(apiContext *types.APIContext, request *rest.Request) rest.Result { - start := time.Now() - defer func() { - logrus.Debug("GET: ", time.Now().Sub(start), s.resourcePlural) - }() - - for _, header := range authHeaders { - request.SetHeader(header, apiContext.Request.Header[http.CanonicalHeaderKey(header)]...) - } - return request.Do() -} - -func (s *Store) k8sClient(apiContext *types.APIContext) (rest.Interface, error) { - return s.clientGetter.UnversionedClient(apiContext, s.storageContext) -} - -func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - _, result, err := s.byID(apiContext, schema, id, true) - return result, err -} - -func (s *Store) byID(apiContext *types.APIContext, schema *types.Schema, id string, retry bool) (string, map[string]interface{}, error) { - splitted := strings.Split(strings.TrimSpace(id), ":") - validID := false - namespaced := schema.Scope == types.NamespaceScope - if namespaced { - validID = len(splitted) == 2 && len(strings.TrimSpace(splitted[0])) > 0 && len(strings.TrimSpace(splitted[1])) > 0 - } else { - validID = len(splitted) == 1 && len(strings.TrimSpace(splitted[0])) > 0 - } - if !validID { - return "", nil, httperror.NewAPIError(httperror.NotFound, "failed to find resource by id") - } - - namespace, id := splitID(id) - - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return "", nil, err - } - - req := s.common(namespace, k8sClient.Get()).Name(id) - if !retry { - return s.singleResult(apiContext, schema, req) - } - - var version string - var data map[string]interface{} - for i := 0; i < 3; i++ { - req = s.common(namespace, k8sClient.Get()).Name(id) - version, data, err = s.singleResult(apiContext, schema, req) - if err != nil { - if i < 2 && strings.Contains(err.Error(), "Client.Timeout exceeded") { - logrus.Warnf("Retrying GET. Error: %v", err) - continue - } - return version, data, err - } - return version, data, err - } - return version, data, err -} - -func (s *Store) Context() types.StorageContext { - return s.storageContext -} - -func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { - namespace := getNamespace(apiContext, opt) - - resultList, err := s.retryList(namespace, apiContext) - if err != nil { - return nil, err - } - - var result []map[string]interface{} - - for _, obj := range resultList.Items { - result = append(result, s.fromInternal(apiContext, schema, obj.Object)) - } - - return apiContext.AccessControl.FilterList(apiContext, schema, result, s.authContext), nil -} - -func (s *Store) retryList(namespace string, apiContext *types.APIContext) (*unstructured.UnstructuredList, error) { - var resultList *unstructured.UnstructuredList - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return nil, err - } - - for i := 0; i < 3; i++ { - req := s.common(namespace, k8sClient.Get()) - start := time.Now() - resultList = &unstructured.UnstructuredList{} - err = req.Do().Into(resultList) - logrus.Debugf("LIST: %v, %v", time.Now().Sub(start), s.resourcePlural) - if err != nil { - if i < 2 && strings.Contains(err.Error(), "Client.Timeout exceeded") { - logrus.Infof("Error on LIST %v: %v. Attempt: %v. Retrying", s.resourcePlural, err, i+1) - continue - } - return resultList, err - } - return resultList, err - } - return resultList, err -} - -func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - c, err := s.shareWatch(apiContext, schema, opt) - if err != nil { - return nil, err - } - - return convert.Chan(c, func(data map[string]interface{}) map[string]interface{} { - return apiContext.AccessControl.Filter(apiContext, schema, data, s.authContext) - }), nil -} - -func (s *Store) realWatch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - namespace := getNamespace(apiContext, opt) - - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return nil, err - } - - if watchClient, ok := k8sClient.(restwatch.WatchClient); ok { - k8sClient = watchClient.WatchClient() - } - - timeout := int64(60 * 60) - req := s.common(namespace, k8sClient.Get()) - req.VersionedParams(&metav1.ListOptions{ - Watch: true, - TimeoutSeconds: &timeout, - ResourceVersion: "0", - }, metav1.ParameterCodec) - - body, err := req.Stream() - if err != nil { - return nil, err - } - - framer := json.Framer.NewFrameReader(body) - decoder := streaming.NewDecoder(framer, &unstructuredDecoder{}) - watcher := watch.NewStreamWatcher(restclientwatch.NewDecoder(decoder, &unstructuredDecoder{})) - - watchingContext, cancelWatchingContext := context.WithCancel(apiContext.Request.Context()) - go func() { - <-watchingContext.Done() - logrus.Debugf("stopping watcher for %s", schema.ID) - watcher.Stop() - }() - - result := make(chan map[string]interface{}) - go func() { - for event := range watcher.ResultChan() { - data := event.Object.(*unstructured.Unstructured) - s.fromInternal(apiContext, schema, data.Object) - if event.Type == watch.Deleted && data.Object != nil { - data.Object[".removed"] = true - } - result <- data.Object - } - logrus.Debugf("closing watcher for %s", schema.ID) - close(result) - cancelWatchingContext() - }() - - return result, nil -} - -type unstructuredDecoder struct { -} - -func (d *unstructuredDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { - if into == nil { - into = &unstructured.Unstructured{} - } - return into, defaults, ejson.Unmarshal(data, &into) -} - -func getNamespace(apiContext *types.APIContext, opt *types.QueryOptions) string { - if val, ok := apiContext.SubContext["namespaces"]; ok { - return convert.ToString(val) - } - - for _, condition := range opt.Conditions { - mod := condition.ToCondition().Modifier - if condition.Field == "namespaceId" && condition.Value != "" && mod == types.ModifierEQ { - return condition.Value - } - if condition.Field == "namespace" && condition.Value != "" && mod == types.ModifierEQ { - return condition.Value - } - } - - return "" -} - -func (s *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) { - if err := s.toInternal(schema.Mapper, data); err != nil { - return nil, err - } - - namespace, _ := values.GetValueN(data, "metadata", "namespace").(string) - - values.PutValue(data, s.getUser(apiContext), "metadata", "annotations", "field.cattle.io/creatorId") - values.PutValue(data, "norman", "metadata", "labels", "cattle.io/creator") - - name, _ := values.GetValueN(data, "metadata", "name").(string) - if name == "" { - generated, _ := values.GetValueN(data, "metadata", "generateName").(string) - if generated == "" { - values.PutValue(data, types.GenerateName(schema.ID), "metadata", "name") - } - } - - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return nil, err - } - - req := s.common(namespace, k8sClient.Post()). - Body(&unstructured.Unstructured{ - Object: data, - }) - - _, result, err := s.singleResult(apiContext, schema, req) - return result, err -} - -func (s *Store) toInternal(mapper types.Mapper, data map[string]interface{}) error { - if mapper != nil { - if err := mapper.ToInternal(data); err != nil { - return err - } - } - - if s.group == "" { - data["apiVersion"] = s.version - } else { - data["apiVersion"] = s.group + "/" + s.version - } - data["kind"] = s.kind - return nil -} - -func (s *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) { - var ( - result map[string]interface{} - err error - ) - - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return nil, err - } - - namespace, id := splitID(id) - if err := s.toInternal(schema.Mapper, data); err != nil { - return nil, err - } - - for i := 0; i < 5; i++ { - req := s.common(namespace, k8sClient.Get()). - Name(id) - - resourceVersion, existing, rawErr := s.singleResultRaw(apiContext, schema, req) - if rawErr != nil { - return nil, rawErr - } - - existing = merge.APIUpdateMerge(schema.InternalSchema, apiContext.Schemas, existing, data, apiContext.Option("replace") == "true") - - values.PutValue(existing, resourceVersion, "metadata", "resourceVersion") - values.PutValue(existing, namespace, "metadata", "namespace") - values.PutValue(existing, id, "metadata", "name") - - req = s.common(namespace, k8sClient.Put()). - Body(&unstructured.Unstructured{ - Object: existing, - }). - Name(id) - - _, result, err = s.singleResult(apiContext, schema, req) - if errors.IsConflict(err) { - continue - } - return result, err - } - - return result, err -} - -func (s *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - k8sClient, err := s.k8sClient(apiContext) - if err != nil { - return nil, err - } - - namespace, name := splitID(id) - - prop := metav1.DeletePropagationBackground - req := s.common(namespace, k8sClient.Delete()). - Body(&metav1.DeleteOptions{ - PropagationPolicy: &prop, - }). - Name(name) - - err = s.doAuthed(apiContext, req).Error() - if err != nil { - return nil, err - } - - _, obj, err := s.byID(apiContext, schema, id, false) - if err != nil { - return nil, nil - } - return obj, nil -} - -func (s *Store) singleResult(apiContext *types.APIContext, schema *types.Schema, req *rest.Request) (string, map[string]interface{}, error) { - version, data, err := s.singleResultRaw(apiContext, schema, req) - if err != nil { - return "", nil, err - } - s.fromInternal(apiContext, schema, data) - return version, data, nil -} - -func (s *Store) singleResultRaw(apiContext *types.APIContext, schema *types.Schema, req *rest.Request) (string, map[string]interface{}, error) { - result := &unstructured.Unstructured{} - err := s.doAuthed(apiContext, req).Into(result) - if err != nil { - return "", nil, err - } - - return result.GetResourceVersion(), result.Object, nil -} - -func splitID(id string) (string, string) { - namespace := "" - parts := strings.SplitN(id, ":", 2) - if len(parts) == 2 { - namespace = parts[0] - id = parts[1] - } - - return namespace, id -} - -func (s *Store) common(namespace string, req *rest.Request) *rest.Request { - prefix := append([]string{}, s.prefix...) - if s.group != "" { - prefix = append(prefix, s.group) - } - prefix = append(prefix, s.version) - req.Prefix(prefix...). - Resource(s.resourcePlural) - - if namespace != "" { - req.Namespace(namespace) - } - - return req -} - -func (s *Store) fromInternal(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) map[string]interface{} { - if apiContext.Option("export") == "true" { - delete(data, "status") - } - if schema.Mapper != nil { - schema.Mapper.FromInternal(data) - } - - return data -} diff --git a/vendor/github.com/rancher/norman/store/proxy/share_watch.go b/vendor/github.com/rancher/norman/store/proxy/share_watch.go deleted file mode 100644 index 4a635227bf..0000000000 --- a/vendor/github.com/rancher/norman/store/proxy/share_watch.go +++ /dev/null @@ -1,28 +0,0 @@ -package proxy - -import ( - "github.com/rancher/norman/pkg/broadcast" - "github.com/rancher/norman/types" -) - -func (s *Store) shareWatch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - client, err := s.clientGetter.UnversionedClient(apiContext, s.Context()) - if err != nil { - return nil, err - } - - var b *broadcast.Broadcaster - s.Lock() - b, ok := s.broadcasters[client] - if !ok { - b = &broadcast.Broadcaster{} - s.broadcasters[client] = b - } - s.Unlock() - - return b.Subscribe(apiContext.Request.Context(), func() (chan map[string]interface{}, error) { - newAPIContext := *apiContext - newAPIContext.Request = apiContext.Request.WithContext(s.close) - return s.realWatch(&newAPIContext, schema, &types.QueryOptions{}) - }) -} diff --git a/vendor/github.com/rancher/norman/store/schema/schema_store.go b/vendor/github.com/rancher/norman/store/schema/schema_store.go deleted file mode 100644 index d86572b480..0000000000 --- a/vendor/github.com/rancher/norman/store/schema/schema_store.go +++ /dev/null @@ -1,140 +0,0 @@ -package schema - -import ( - "encoding/json" - "net/http" - "strings" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/store/empty" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/definition" - "github.com/rancher/norman/types/slice" -) - -type Store struct { - empty.Store -} - -func NewSchemaStore() types.Store { - return &Store{} -} - -func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - for _, schema := range apiContext.Schemas.SchemasForVersion(*apiContext.Version) { - if strings.EqualFold(schema.ID, id) { - schemaData := map[string]interface{}{} - - data, err := json.Marshal(s.modifyForAccessControl(apiContext, *schema)) - if err != nil { - return nil, err - } - - return schemaData, json.Unmarshal(data, &schemaData) - } - } - return nil, httperror.NewAPIError(httperror.NotFound, "no such schema") -} - -func (s *Store) modifyForAccessControl(context *types.APIContext, schema types.Schema) *types.Schema { - var resourceMethods []string - if slice.ContainsString(schema.ResourceMethods, http.MethodPut) && schema.CanUpdate(context) == nil { - resourceMethods = append(resourceMethods, http.MethodPut) - } - if slice.ContainsString(schema.ResourceMethods, http.MethodDelete) && schema.CanDelete(context) == nil { - resourceMethods = append(resourceMethods, http.MethodDelete) - } - if slice.ContainsString(schema.ResourceMethods, http.MethodGet) && schema.CanGet(context) == nil { - resourceMethods = append(resourceMethods, http.MethodGet) - } - - var collectionMethods []string - if slice.ContainsString(schema.CollectionMethods, http.MethodPost) && schema.CanCreate(context) == nil { - collectionMethods = append(collectionMethods, http.MethodPost) - } - if slice.ContainsString(schema.CollectionMethods, http.MethodGet) && schema.CanList(context) == nil { - collectionMethods = append(collectionMethods, http.MethodGet) - } - - schema.ResourceMethods = resourceMethods - schema.CollectionMethods = collectionMethods - - return &schema -} - -func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - return nil, nil -} - -func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) { - schemaMap := apiContext.Schemas.SchemasForVersion(*apiContext.Version) - schemas := make([]*types.Schema, 0, len(schemaMap)) - schemaData := make([]map[string]interface{}, 0, len(schemaMap)) - - included := map[string]bool{} - - for _, schema := range schemaMap { - if included[schema.ID] { - continue - } - - if schema.CanList(apiContext) == nil || schema.CanGet(apiContext) == nil { - schemas = s.addSchema(apiContext, schema, schemaMap, schemas, included) - } - } - - data, err := json.Marshal(schemas) - if err != nil { - return nil, err - } - - return schemaData, json.Unmarshal(data, &schemaData) -} - -func (s *Store) addSchema(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema { - included[schema.ID] = true - schemas = s.traverseAndAdd(apiContext, schema, schemaMap, schemas, included) - schemas = append(schemas, s.modifyForAccessControl(apiContext, *schema)) - return schemas -} - -func (s *Store) traverseAndAdd(apiContext *types.APIContext, schema *types.Schema, schemaMap map[string]*types.Schema, schemas []*types.Schema, included map[string]bool) []*types.Schema { - for _, field := range schema.ResourceFields { - t := "" - subType := field.Type - for subType != t { - t = subType - subType = definition.SubType(t) - } - - if refSchema, ok := schemaMap[t]; ok && !included[t] { - schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included) - } - } - - for _, action := range schema.ResourceActions { - for _, t := range []string{action.Output, action.Input} { - if t == "" { - continue - } - - if refSchema, ok := schemaMap[t]; ok && !included[t] { - schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included) - } - } - } - - for _, action := range schema.CollectionActions { - for _, t := range []string{action.Output, action.Input} { - if t == "" { - continue - } - - if refSchema, ok := schemaMap[t]; ok && !included[t] { - schemas = s.addSchema(apiContext, refSchema, schemaMap, schemas, included) - } - } - } - - return schemas -} diff --git a/vendor/github.com/rancher/norman/store/wrapper/wrapper.go b/vendor/github.com/rancher/norman/store/wrapper/wrapper.go deleted file mode 100644 index 24a9f7b2aa..0000000000 --- a/vendor/github.com/rancher/norman/store/wrapper/wrapper.go +++ /dev/null @@ -1,115 +0,0 @@ -package wrapper - -import ( - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -func Wrap(store types.Store) types.Store { - return &StoreWrapper{ - store: store, - } -} - -type StoreWrapper struct { - store types.Store -} - -func (s *StoreWrapper) Context() types.StorageContext { - return s.store.Context() -} - -func (s *StoreWrapper) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - data, err := s.store.ByID(apiContext, schema, id) - if err != nil { - return nil, err - } - - return apiContext.FilterObject(&types.QueryOptions{ - Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema), - }, schema, data), nil -} - -func (s *StoreWrapper) List(apiContext *types.APIContext, schema *types.Schema, opts *types.QueryOptions) ([]map[string]interface{}, error) { - opts.Conditions = append(opts.Conditions, apiContext.SubContextAttributeProvider.Query(apiContext, schema)...) - data, err := s.store.List(apiContext, schema, opts) - if err != nil { - return nil, err - } - - return apiContext.FilterList(opts, schema, data), nil -} - -func (s *StoreWrapper) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) { - c, err := s.store.Watch(apiContext, schema, opt) - if err != nil || c == nil { - return nil, err - } - - return convert.Chan(c, func(data map[string]interface{}) map[string]interface{} { - return apiContext.FilterObject(&types.QueryOptions{ - Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema), - }, schema, data) - }), nil -} - -func (s *StoreWrapper) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) { - for key, value := range apiContext.SubContextAttributeProvider.Create(apiContext, schema) { - if data == nil { - data = map[string]interface{}{} - } - data[key] = value - } - - data, err := s.store.Create(apiContext, schema, data) - if err != nil { - return nil, err - } - - return data, nil -} - -func (s *StoreWrapper) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) { - err := validateGet(apiContext, schema, id) - if err != nil { - return nil, err - } - - data, err = s.store.Update(apiContext, schema, data, id) - if err != nil { - return nil, err - } - - return apiContext.FilterObject(&types.QueryOptions{ - Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema), - }, schema, data), nil -} - -func (s *StoreWrapper) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) { - if err := validateGet(apiContext, schema, id); err != nil { - return nil, err - } - - return s.store.Delete(apiContext, schema, id) -} - -func validateGet(apiContext *types.APIContext, schema *types.Schema, id string) error { - store := schema.Store - if store == nil { - return nil - } - - existing, err := store.ByID(apiContext, schema, id) - if err != nil { - return err - } - - if apiContext.Filter(&types.QueryOptions{ - Conditions: apiContext.SubContextAttributeProvider.Query(apiContext, schema), - }, schema, existing) == nil { - return httperror.NewAPIError(httperror.NotFound, "failed to find "+id) - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types.go b/vendor/github.com/rancher/norman/types.go deleted file mode 100644 index c99f546aeb..0000000000 --- a/vendor/github.com/rancher/norman/types.go +++ /dev/null @@ -1,62 +0,0 @@ -package norman - -import ( - "context" - "net/http" - - "github.com/rancher/norman/api" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/store/proxy" - "github.com/rancher/norman/types" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" -) - -type ClientFactory func(context.Context, rest.Config) (context.Context, controller.Starter, error) - -type ControllerRegister func(ctx context.Context) error - -type Config struct { - Name string - EnableAPI bool - Schemas []*types.Schemas - CRDs map[*types.APIVersion][]string - Clients []ClientFactory - ClientGetter proxy.ClientGetter - CRDStorageContext types.StorageContext - K8sClient kubernetes.Interface - APIExtClient clientset.Interface - Config *rest.Config - DisableLeaderElection bool - LeaderLockNamespace string - KubeConfig string - IgnoredKubeConfigEnv bool - Threadiness int - - CustomizeSchemas func(context.Context, proxy.ClientGetter, *types.Schemas) error - GlobalSetup func(context.Context) (context.Context, error) - MasterSetup func(context.Context) (context.Context, error) - PreStart func(context.Context) error - APISetup func(context.Context, *api.Server) error - - PerServerControllers []ControllerRegister - MasterControllers []ControllerRegister -} - -type Server struct { - *Config - *Runtime -} - -type Runtime struct { - AllSchemas *types.Schemas - LocalConfig *rest.Config - UnversionedClient rest.Interface - APIHandler http.Handler -} - -type Options struct { - KubeConfig string - DisableControllers bool -} diff --git a/vendor/github.com/rancher/norman/types/condition.go b/vendor/github.com/rancher/norman/types/condition.go deleted file mode 100644 index 9be6210b81..0000000000 --- a/vendor/github.com/rancher/norman/types/condition.go +++ /dev/null @@ -1,121 +0,0 @@ -package types - -import ( - "github.com/rancher/norman/types/convert" -) - -var ( - CondEQ = QueryConditionType{ModifierEQ, 1} - CondNE = QueryConditionType{ModifierNE, 1} - CondNull = QueryConditionType{ModifierNull, 0} - CondNotNull = QueryConditionType{ModifierNotNull, 0} - CondIn = QueryConditionType{ModifierIn, -1} - CondNotIn = QueryConditionType{ModifierNotIn, -1} - CondOr = QueryConditionType{ModifierType("or"), 1} - CondAnd = QueryConditionType{ModifierType("and"), 1} - - mods = map[ModifierType]QueryConditionType{ - CondEQ.Name: CondEQ, - CondNE.Name: CondNE, - CondNull.Name: CondNull, - CondNotNull.Name: CondNotNull, - CondIn.Name: CondIn, - CondNotIn.Name: CondNotIn, - CondOr.Name: CondOr, - CondAnd.Name: CondAnd, - } -) - -type QueryConditionType struct { - Name ModifierType - Args int -} - -type QueryCondition struct { - Field string - Value string - Values map[string]bool - conditionType QueryConditionType - left, right *QueryCondition -} - -func (q *QueryCondition) Valid(schema *Schema, data map[string]interface{}) bool { - switch q.conditionType { - case CondAnd: - if q.left == nil || q.right == nil { - return false - } - return q.left.Valid(schema, data) && q.right.Valid(schema, data) - case CondOr: - if q.left == nil || q.right == nil { - return false - } - return q.left.Valid(schema, data) || q.right.Valid(schema, data) - case CondEQ: - return q.Value == convert.ToString(valueOrDefault(schema, data, q)) - case CondNE: - return q.Value != convert.ToString(valueOrDefault(schema, data, q)) - case CondIn: - return q.Values[convert.ToString(valueOrDefault(schema, data, q))] - case CondNotIn: - return !q.Values[convert.ToString(valueOrDefault(schema, data, q))] - case CondNotNull: - return convert.ToString(valueOrDefault(schema, data, q)) != "" - case CondNull: - return convert.ToString(valueOrDefault(schema, data, q)) == "" - } - - return false -} - -func valueOrDefault(schema *Schema, data map[string]interface{}, q *QueryCondition) interface{} { - value := data[q.Field] - if value == nil { - value = schema.ResourceFields[q.Field].Default - } - - return value -} - -func (q *QueryCondition) ToCondition() Condition { - cond := Condition{ - Modifier: q.conditionType.Name, - } - if q.conditionType.Args == 1 { - cond.Value = q.Value - } else if q.conditionType.Args == -1 { - stringValues := []string{} - for val := range q.Values { - stringValues = append(stringValues, val) - } - cond.Value = stringValues - } - - return cond -} - -func ValidMod(mod ModifierType) bool { - _, ok := mods[mod] - return ok -} - -func EQ(key, value string) *QueryCondition { - return NewConditionFromString(key, ModifierEQ, value) -} - -func NewConditionFromString(field string, mod ModifierType, values ...string) *QueryCondition { - q := &QueryCondition{ - Field: field, - conditionType: mods[mod], - Values: map[string]bool{}, - } - - for i, value := range values { - if i == 0 { - q.Value = value - } - q.Values[value] = true - } - - return q -} diff --git a/vendor/github.com/rancher/norman/types/convert/convert.go b/vendor/github.com/rancher/norman/types/convert/convert.go deleted file mode 100644 index ccab268556..0000000000 --- a/vendor/github.com/rancher/norman/types/convert/convert.go +++ /dev/null @@ -1,278 +0,0 @@ -package convert - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "strconv" - "strings" - "time" - "unicode" -) - -func Chan(c <-chan map[string]interface{}, f func(map[string]interface{}) map[string]interface{}) chan map[string]interface{} { - if c == nil { - return nil - } - result := make(chan map[string]interface{}) - go func() { - for data := range c { - modified := f(data) - if modified != nil { - result <- modified - } - } - close(result) - }() - return result -} - -func Singular(value interface{}) interface{} { - if slice, ok := value.([]string); ok { - if len(slice) == 0 { - return nil - } - return slice[0] - } - if slice, ok := value.([]interface{}); ok { - if len(slice) == 0 { - return nil - } - return slice[0] - } - return value -} - -func ToStringNoTrim(value interface{}) string { - if t, ok := value.(time.Time); ok { - return t.Format(time.RFC3339) - } - single := Singular(value) - if single == nil { - return "" - } - return fmt.Sprint(single) -} - -func ToString(value interface{}) string { - return strings.TrimSpace(ToStringNoTrim(value)) -} - -func ToTimestamp(value interface{}) (int64, error) { - str := ToString(value) - if str == "" { - return 0, errors.New("invalid date") - } - t, err := time.Parse(time.RFC3339, str) - if err != nil { - return 0, err - } - return t.UnixNano() / 1000000, nil -} - -func ToBool(value interface{}) bool { - value = Singular(value) - - b, ok := value.(bool) - if ok { - return b - } - - str := strings.ToLower(ToString(value)) - return str == "true" || str == "t" || str == "yes" || str == "y" -} - -func ToNumber(value interface{}) (int64, error) { - value = Singular(value) - - i, ok := value.(int64) - if ok { - return i, nil - } - f, ok := value.(float64) - if ok { - return int64(f), nil - } - if n, ok := value.(json.Number); ok { - i, err := n.Int64() - if err == nil { - return i, nil - } - f, err := n.Float64() - return int64(f), err - } - return strconv.ParseInt(ToString(value), 10, 64) -} - -func ToFloat(value interface{}) (float64, error) { - value = Singular(value) - - f64, ok := value.(float64) - if ok { - return f64, nil - } - - f32, ok := value.(float32) - if ok { - return float64(f32), nil - } - - if n, ok := value.(json.Number); ok { - i, err := n.Int64() - if err == nil { - return float64(i), nil - } - f, err := n.Float64() - return float64(f), err - } - return strconv.ParseFloat(ToString(value), 64) -} - -func Capitalize(s string) string { - if len(s) <= 1 { - return strings.ToUpper(s) - } - - return strings.ToUpper(s[:1]) + s[1:] -} - -func Uncapitalize(s string) string { - if len(s) <= 1 { - return strings.ToLower(s) - } - - return strings.ToLower(s[:1]) + s[1:] -} - -func LowerTitle(input string) string { - runes := []rune(input) - for i := 0; i < len(runes); i++ { - if unicode.IsUpper(runes[i]) && - (i == 0 || - i == len(runes)-1 || - unicode.IsUpper(runes[i+1])) { - runes[i] = unicode.ToLower(runes[i]) - } else { - break - } - } - - return string(runes) -} - -func IsAPIObjectEmpty(v interface{}) bool { - if v == nil || v == "" || v == 0 || v == false { - return true - } - if m, ok := v.(map[string]interface{}); ok { - return len(m) == 0 - } - if s, ok := v.([]interface{}); ok { - return len(s) == 0 - } - return false -} - -func ToMapInterface(obj interface{}) map[string]interface{} { - v, _ := obj.(map[string]interface{}) - return v -} - -func ToInterfaceSlice(obj interface{}) []interface{} { - if v, ok := obj.([]interface{}); ok { - return v - } - return nil -} - -func ToMapSlice(obj interface{}) []map[string]interface{} { - if v, ok := obj.([]map[string]interface{}); ok { - return v - } - vs, _ := obj.([]interface{}) - var result []map[string]interface{} - for _, item := range vs { - if v, ok := item.(map[string]interface{}); ok { - result = append(result, v) - } else { - return nil - } - } - - return result -} - -func ToStringSlice(data interface{}) []string { - if v, ok := data.([]string); ok { - return v - } - if v, ok := data.([]interface{}); ok { - var result []string - for _, item := range v { - result = append(result, ToString(item)) - } - return result - } - return nil -} - -func ToObj(data interface{}, into interface{}) error { - bytes, err := json.Marshal(data) - if err != nil { - return err - } - return json.Unmarshal(bytes, into) -} - -func EncodeToMap(obj interface{}) (map[string]interface{}, error) { - if m, ok := obj.(map[string]interface{}); ok { - return m, nil - } - - b, err := json.Marshal(obj) - if err != nil { - return nil, err - } - result := map[string]interface{}{} - dec := json.NewDecoder(bytes.NewBuffer(b)) - dec.UseNumber() - return result, dec.Decode(&result) -} - -func ToJSONKey(str string) string { - parts := strings.Split(str, "_") - for i := 1; i < len(parts); i++ { - parts[i] = strings.Title(parts[i]) - } - - return strings.Join(parts, "") -} - -func ToYAMLKey(str string) string { - var result []rune - cap := false - - for i, r := range []rune(str) { - if i == 0 { - if unicode.IsUpper(r) { - cap = true - } - result = append(result, unicode.ToLower(r)) - continue - } - - if unicode.IsUpper(r) { - if cap { - result = append(result, unicode.ToLower(r)) - } else { - result = append(result, '_', unicode.ToLower(r)) - } - } else { - cap = false - result = append(result, r) - } - } - - return string(result) -} diff --git a/vendor/github.com/rancher/norman/types/convert/merge/merge.go b/vendor/github.com/rancher/norman/types/convert/merge/merge.go deleted file mode 100644 index 3d9424a5f1..0000000000 --- a/vendor/github.com/rancher/norman/types/convert/merge/merge.go +++ /dev/null @@ -1,156 +0,0 @@ -package merge - -import ( - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" -) - -func APIUpdateMerge(schema *types.Schema, schemas *types.Schemas, dest, src map[string]interface{}, replace bool) map[string]interface{} { - result := UpdateMerge(schema, schemas, dest, src, replace) - if s, ok := dest["status"]; ok { - result["status"] = s - } - if m, ok := dest["metadata"]; ok { - result["metadata"] = mergeMetadata(convert.ToMapInterface(m), convert.ToMapInterface(src["metadata"])) - } - return result -} - -func UpdateMerge(schema *types.Schema, schemas *types.Schemas, dest, src map[string]interface{}, replace bool) map[string]interface{} { - return mergeMaps("", nil, schema, schemas, replace, dest, src) -} - -func isProtected(k string) bool { - if !strings.Contains(k, "cattle.io/") || (isField(k) && k != "field.cattle.io/creatorId") { - return false - } - return true -} - -func isField(k string) bool { - return strings.HasPrefix(k, "field.cattle.io/") -} - -func mergeProtected(dest, src map[string]interface{}) map[string]interface{} { - if src == nil { - return dest - } - - result := copyMap(dest) - - for k, v := range src { - if isProtected(k) { - continue - } - result[k] = v - } - - for k := range dest { - if isProtected(k) || isField(k) { - continue - } - if _, ok := src[k]; !ok { - delete(result, k) - } - } - - return result -} - -func mergeMetadata(dest map[string]interface{}, src map[string]interface{}) map[string]interface{} { - result := copyMap(dest) - - labels := convert.ToMapInterface(dest["labels"]) - srcLabels := convert.ToMapInterface(src["labels"]) - labels = mergeProtected(labels, srcLabels) - - annotations := convert.ToMapInterface(dest["annotations"]) - srcAnnotation := convert.ToMapInterface(src["annotations"]) - annotations = mergeProtected(annotations, srcAnnotation) - - result["labels"] = labels - result["annotations"] = annotations - - return result -} - -func merge(field, fieldType string, parentSchema, schema *types.Schema, schemas *types.Schemas, replace bool, dest, src interface{}) interface{} { - if isMap(field, schema, schemas) { - return src - } - - sm, smOk := src.(map[string]interface{}) - dm, dmOk := dest.(map[string]interface{}) - if smOk && dmOk { - fieldType, fieldSchema := getSchema(field, fieldType, parentSchema, schema, schemas) - return mergeMaps(fieldType, schema, fieldSchema, schemas, replace, dm, sm) - } - return src -} - -func getSchema(field, parentFieldType string, parentSchema, schema *types.Schema, schemas *types.Schemas) (string, *types.Schema) { - if schema == nil { - if definition.IsMapType(parentFieldType) && parentSchema != nil { - subType := definition.SubType(parentFieldType) - s := schemas.Schema(&parentSchema.Version, subType) - if s != nil && s.InternalSchema != nil { - s = s.InternalSchema - } - return subType, s - } - return "", nil - } - fieldType := schema.ResourceFields[field].Type - s := schemas.Schema(&schema.Version, fieldType) - if s != nil && s.InternalSchema != nil { - return fieldType, s.InternalSchema - } - return fieldType, s -} - -func isMap(field string, schema *types.Schema, schemas *types.Schemas) bool { - if schema == nil { - return false - } - f := schema.ResourceFields[field] - mapType := definition.IsMapType(f.Type) - if !mapType { - return false - } - - subType := definition.SubType(f.Type) - return schemas.Schema(&schema.Version, subType) == nil -} - -func mergeMaps(fieldType string, parentSchema, schema *types.Schema, schemas *types.Schemas, replace bool, dest map[string]interface{}, src map[string]interface{}) map[string]interface{} { - result := copyMapReplace(schema, dest, replace) - for k, v := range src { - result[k] = merge(k, fieldType, parentSchema, schema, schemas, replace, dest[k], v) - } - return result -} - -func copyMap(src map[string]interface{}) map[string]interface{} { - result := map[string]interface{}{} - for k, v := range src { - result[k] = v - } - return result -} - -func copyMapReplace(schema *types.Schema, src map[string]interface{}, replace bool) map[string]interface{} { - result := map[string]interface{}{} - for k, v := range src { - if replace && schema != nil { - f := schema.ResourceFields[k] - if f.Update { - continue - } - } - result[k] = v - } - return result -} diff --git a/vendor/github.com/rancher/norman/types/convert/ref.go b/vendor/github.com/rancher/norman/types/convert/ref.go deleted file mode 100644 index b269a76cd8..0000000000 --- a/vendor/github.com/rancher/norman/types/convert/ref.go +++ /dev/null @@ -1,11 +0,0 @@ -package convert - -import "fmt" - -func ToReference(typeName string) string { - return fmt.Sprintf("reference[%s]", typeName) -} - -func ToFullReference(path, typeName string) string { - return fmt.Sprintf("reference[%s/schemas/%s]", path, typeName) -} diff --git a/vendor/github.com/rancher/norman/types/convert/transform.go b/vendor/github.com/rancher/norman/types/convert/transform.go deleted file mode 100644 index 3fd9b9247a..0000000000 --- a/vendor/github.com/rancher/norman/types/convert/transform.go +++ /dev/null @@ -1,45 +0,0 @@ -package convert - -const ( - ArrayKey = "{ARRAY}" - MapKey = "{MAP}" -) - -type TransformerFunc func(input interface{}) interface{} - -func Transform(data map[string]interface{}, path []string, transformer TransformerFunc) { - if len(path) == 0 || len(data) == 0 { - return - } - - key := path[0] - path = path[1:] - value := data[key] - - if value == nil { - return - } - - if len(path) == 0 { - data[key] = transformer(value) - return - } - - // You can't end a path with ARRAY/MAP. Not supported right now - if len(path) > 1 { - switch path[0] { - case ArrayKey: - for _, valueMap := range ToMapSlice(value) { - Transform(valueMap, path[1:], transformer) - } - return - case MapKey: - for _, valueMap := range ToMapInterface(value) { - Transform(ToMapInterface(valueMap), path[1:], transformer) - } - return - } - } - - Transform(ToMapInterface(value), path, transformer) -} diff --git a/vendor/github.com/rancher/norman/types/convert/value_set_string.go b/vendor/github.com/rancher/norman/types/convert/value_set_string.go deleted file mode 100644 index d9b329fa09..0000000000 --- a/vendor/github.com/rancher/norman/types/convert/value_set_string.go +++ /dev/null @@ -1,18 +0,0 @@ -package convert - -import ( - "regexp" - "strings" -) - -var ( - splitRegexp = regexp.MustCompile("[[:space:]]*,[[:space:]]*") -) - -func ToValuesSlice(value string) []string { - value = strings.TrimSpace(value) - if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") { - return splitRegexp.Split(value[1:len(value)-1], -1) - } - return []string{value} -} diff --git a/vendor/github.com/rancher/norman/types/definition/definition.go b/vendor/github.com/rancher/norman/types/definition/definition.go deleted file mode 100644 index 40912afb3e..0000000000 --- a/vendor/github.com/rancher/norman/types/definition/definition.go +++ /dev/null @@ -1,45 +0,0 @@ -package definition - -import ( - "strings" - - "github.com/rancher/norman/types/convert" -) - -func IsMapType(fieldType string) bool { - return strings.HasPrefix(fieldType, "map[") && strings.HasSuffix(fieldType, "]") -} - -func IsArrayType(fieldType string) bool { - return strings.HasPrefix(fieldType, "array[") && strings.HasSuffix(fieldType, "]") -} - -func IsReferenceType(fieldType string) bool { - return strings.HasPrefix(fieldType, "reference[") && strings.HasSuffix(fieldType, "]") -} - -func HasReferenceType(fieldType string) bool { - return strings.Contains(fieldType, "reference[") -} - -func SubType(fieldType string) string { - i := strings.Index(fieldType, "[") - if i <= 0 || i >= len(fieldType)-1 { - return fieldType - } - - return fieldType[i+1 : len(fieldType)-1] -} - -func GetType(data map[string]interface{}) string { - return GetShortTypeFromFull(GetFullType(data)) -} - -func GetShortTypeFromFull(fullType string) string { - parts := strings.Split(fullType, "/") - return parts[len(parts)-1] -} - -func GetFullType(data map[string]interface{}) string { - return convert.ToString(data["type"]) -} diff --git a/vendor/github.com/rancher/norman/types/encoder.go b/vendor/github.com/rancher/norman/types/encoder.go deleted file mode 100644 index 1e5128cdc8..0000000000 --- a/vendor/github.com/rancher/norman/types/encoder.go +++ /dev/null @@ -1,32 +0,0 @@ -package types - -import ( - "encoding/json" - "io" - "regexp" - - "github.com/ghodss/yaml" -) - -var ( - commenter = regexp.MustCompile("(?m)^( *)zzz#\\((.*)\\)\\((.*)\\)([a-z]+.*):(.*)") -) - -func JSONEncoder(writer io.Writer, v interface{}) error { - return json.NewEncoder(writer).Encode(v) -} - -func YAMLEncoder(writer io.Writer, v interface{}) error { - data, err := json.Marshal(v) - if err != nil { - return err - } - buf, err := yaml.JSONToYAML(data) - if err != nil { - return err - } - //buf = commenter.ReplaceAll(buf, []byte("${1}# ${2}type: ${3}\n${1}# ${4}:${5}")) - buf = commenter.ReplaceAll(buf, []byte("${1}# ${4}:${5}")) - _, err = writer.Write(buf) - return err -} diff --git a/vendor/github.com/rancher/norman/types/factory/schemas.go b/vendor/github.com/rancher/norman/types/factory/schemas.go deleted file mode 100644 index d4a2555f5a..0000000000 --- a/vendor/github.com/rancher/norman/types/factory/schemas.go +++ /dev/null @@ -1,23 +0,0 @@ -package factory - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/mapper" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func Schemas(version *types.APIVersion) *types.Schemas { - s := types.NewSchemas() - s.DefaultMappers = func() []types.Mapper { - return []types.Mapper{ - mapper.NewObject(), - } - } - s.DefaultPostMappers = func() []types.Mapper { - return []types.Mapper{ - &mapper.RenameReference{}, - } - } - s.AddMapperForType(version, v1.ObjectMeta{}, mapper.NewMetadataMapper()) - return s -} diff --git a/vendor/github.com/rancher/norman/types/id.go b/vendor/github.com/rancher/norman/types/id.go deleted file mode 100644 index 9c6618d172..0000000000 --- a/vendor/github.com/rancher/norman/types/id.go +++ /dev/null @@ -1,19 +0,0 @@ -package types - -import ( - "fmt" - "regexp" - "strings" - - utilrand "k8s.io/apimachinery/pkg/util/rand" -) - -var ( - lowerChars = regexp.MustCompile("[a-z]+") -) - -func GenerateName(typeName string) string { - base := typeName[0:1] + lowerChars.ReplaceAllString(typeName[1:], "") - last := utilrand.String(5) - return fmt.Sprintf("%s-%s", strings.ToLower(base), last) -} diff --git a/vendor/github.com/rancher/norman/types/mapper.go b/vendor/github.com/rancher/norman/types/mapper.go deleted file mode 100644 index 04f1ae0b2d..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper.go +++ /dev/null @@ -1,178 +0,0 @@ -package types - -import ( - "fmt" - - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" - "github.com/rancher/norman/types/values" -) - -type Mapper interface { - FromInternal(data map[string]interface{}) - ToInternal(data map[string]interface{}) error - ModifySchema(schema *Schema, schemas *Schemas) error -} - -type Mappers []Mapper - -func (m Mappers) FromInternal(data map[string]interface{}) { - for _, mapper := range m { - mapper.FromInternal(data) - } -} - -func (m Mappers) ToInternal(data map[string]interface{}) error { - var errors []error - for i := len(m) - 1; i >= 0; i-- { - errors = append(errors, m[i].ToInternal(data)) - } - return NewErrors(errors...) -} - -func (m Mappers) ModifySchema(schema *Schema, schemas *Schemas) error { - for _, mapper := range m { - if err := mapper.ModifySchema(schema, schemas); err != nil { - return err - } - } - return nil -} - -type typeMapper struct { - Mappers []Mapper - root bool - typeName string - subSchemas map[string]*Schema - subArraySchemas map[string]*Schema - subMapSchemas map[string]*Schema -} - -func (t *typeMapper) FromInternal(data map[string]interface{}) { - name, _ := values.GetValueN(data, "metadata", "name").(string) - namespace, _ := values.GetValueN(data, "metadata", "namespace").(string) - - for fieldName, schema := range t.subSchemas { - if schema.Mapper == nil { - continue - } - fieldData, _ := data[fieldName].(map[string]interface{}) - schema.Mapper.FromInternal(fieldData) - } - - for fieldName, schema := range t.subMapSchemas { - if schema.Mapper == nil { - continue - } - datas, _ := data[fieldName].(map[string]interface{}) - for _, fieldData := range datas { - mapFieldData, _ := fieldData.(map[string]interface{}) - schema.Mapper.FromInternal(mapFieldData) - } - } - - for fieldName, schema := range t.subArraySchemas { - if schema.Mapper == nil { - continue - } - datas, _ := data[fieldName].([]interface{}) - for _, fieldData := range datas { - mapFieldData, _ := fieldData.(map[string]interface{}) - schema.Mapper.FromInternal(mapFieldData) - } - } - - if _, ok := data["type"]; !ok && data != nil { - data["type"] = t.typeName - } - - Mappers(t.Mappers).FromInternal(data) - - if data != nil && t.root { - if _, ok := data["id"]; ok { - if namespace != "" { - id, _ := data["id"].(string) - data["id"] = namespace + ":" + id - } - } else { - if name != "" { - if namespace == "" { - data["id"] = name - } else { - data["id"] = namespace + ":" + name - } - } - } - } - - if _, ok := data["type"]; !ok && data != nil { - if _, ok := data["id"]; ok { - data["type"] = t.typeName - } - } -} - -func (t *typeMapper) ToInternal(data map[string]interface{}) error { - errors := Errors{} - errors.Add(Mappers(t.Mappers).ToInternal(data)) - - for fieldName, schema := range t.subArraySchemas { - if schema.Mapper == nil { - continue - } - datas, _ := data[fieldName].([]interface{}) - for _, fieldData := range datas { - errors.Add(schema.Mapper.ToInternal(convert.ToMapInterface(fieldData))) - } - } - - for fieldName, schema := range t.subMapSchemas { - if schema.Mapper == nil { - continue - } - datas, _ := data[fieldName].(map[string]interface{}) - for _, fieldData := range datas { - errors.Add(schema.Mapper.ToInternal(convert.ToMapInterface(fieldData))) - } - } - - for fieldName, schema := range t.subSchemas { - if schema.Mapper == nil { - continue - } - fieldData, _ := data[fieldName].(map[string]interface{}) - errors.Add(schema.Mapper.ToInternal(fieldData)) - } - - return errors.Err() -} - -func (t *typeMapper) ModifySchema(schema *Schema, schemas *Schemas) error { - t.subSchemas = map[string]*Schema{} - t.subArraySchemas = map[string]*Schema{} - t.subMapSchemas = map[string]*Schema{} - t.typeName = fmt.Sprintf("%s/schemas/%s", schema.Version.Path, schema.ID) - - mapperSchema := schema - if schema.InternalSchema != nil { - mapperSchema = schema.InternalSchema - } - for name, field := range mapperSchema.ResourceFields { - fieldType := field.Type - targetMap := t.subSchemas - if definition.IsArrayType(fieldType) { - fieldType = definition.SubType(fieldType) - targetMap = t.subArraySchemas - } else if definition.IsMapType(fieldType) { - fieldType = definition.SubType(fieldType) - targetMap = t.subMapSchemas - } - - schema := schemas.Schema(&schema.Version, fieldType) - if schema != nil { - targetMap[name] = schema - } - } - - return Mappers(t.Mappers).ModifySchema(schema, schemas) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/access.go b/vendor/github.com/rancher/norman/types/mapper/access.go deleted file mode 100644 index e11400487d..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/access.go +++ /dev/null @@ -1,38 +0,0 @@ -package mapper - -import ( - "strings" - - "github.com/rancher/norman/types" -) - -type Access struct { - Fields map[string]string - Optional bool -} - -func (e Access) FromInternal(data map[string]interface{}) { -} - -func (e Access) ToInternal(data map[string]interface{}) error { - return nil -} - -func (e Access) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - for name, access := range e.Fields { - if err := ValidateField(name, schema); err != nil { - if e.Optional { - continue - } - return err - } - - field := schema.ResourceFields[name] - field.Create = strings.Contains(access, "c") - field.Update = strings.Contains(access, "u") - field.WriteOnly = strings.Contains(access, "o") - - schema.ResourceFields[name] = field - } - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/annotation_field.go b/vendor/github.com/rancher/norman/types/mapper/annotation_field.go deleted file mode 100644 index 8930712f11..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/annotation_field.go +++ /dev/null @@ -1,58 +0,0 @@ -package mapper - -import ( - "encoding/json" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/values" -) - -type AnnotationField struct { - Field string - Object bool - List bool - IgnoreDefinition bool -} - -func (e AnnotationField) FromInternal(data map[string]interface{}) { - v, ok := values.RemoveValue(data, "annotations", "field.cattle.io/"+e.Field) - if ok { - if e.Object { - data := map[string]interface{}{} - //ignore error - if err := json.Unmarshal([]byte(convert.ToString(v)), &data); err == nil { - v = data - } - } - if e.List { - var data []interface{} - if err := json.Unmarshal([]byte(convert.ToString(v)), &data); err == nil { - v = data - } - } - - data[e.Field] = v - } -} - -func (e AnnotationField) ToInternal(data map[string]interface{}) error { - v, ok := data[e.Field] - if ok { - if e.Object || e.List { - if bytes, err := json.Marshal(v); err == nil { - v = string(bytes) - } - } - values.PutValue(data, convert.ToString(v), "annotations", "field.cattle.io/"+e.Field) - } - values.RemoveValue(data, e.Field) - return nil -} - -func (e AnnotationField) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if e.IgnoreDefinition { - return nil - } - return ValidateField(e.Field, schema) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/apigroup.go b/vendor/github.com/rancher/norman/types/mapper/apigroup.go deleted file mode 100644 index 522ef0a38f..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/apigroup.go +++ /dev/null @@ -1,35 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -type APIGroup struct { - apiVersion string - kind string -} - -func (a *APIGroup) FromInternal(data map[string]interface{}) { -} - -func (a *APIGroup) ToInternal(data map[string]interface{}) error { - _, ok := data["apiVersion"] - if !ok && data != nil { - data["apiVersion"] = a.apiVersion - } - - _, ok = data["kind"] - if !ok && data != nil { - data["kind"] = a.kind - } - - return nil -} - -func (a *APIGroup) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - a.apiVersion = schema.Version.Group + "/" + schema.Version.Version - a.kind = convert.Capitalize(schema.ID) - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/base64.go b/vendor/github.com/rancher/norman/types/mapper/base64.go deleted file mode 100644 index cf2fd93ae6..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/base64.go +++ /dev/null @@ -1,63 +0,0 @@ -package mapper - -import ( - "encoding/base64" - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/values" -) - -type Base64 struct { - Field string - IgnoreDefinition bool - Separator string -} - -func (m Base64) FromInternal(data map[string]interface{}) { - if v, ok := values.RemoveValue(data, strings.Split(m.Field, m.getSep())...); ok { - str := convert.ToString(v) - if str == "" { - return - } - - newData, err := base64.StdEncoding.DecodeString(str) - if err != nil { - log.Errorf("failed to base64 decode data") - } - - values.PutValue(data, string(newData), strings.Split(m.Field, m.getSep())...) - } -} - -func (m Base64) ToInternal(data map[string]interface{}) error { - if v, ok := values.RemoveValue(data, strings.Split(m.Field, m.getSep())...); ok { - str := convert.ToString(v) - if str == "" { - return nil - } - - newData := base64.StdEncoding.EncodeToString([]byte(str)) - values.PutValue(data, newData, strings.Split(m.Field, m.getSep())...) - } - - return nil -} - -func (m Base64) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - if !m.IgnoreDefinition { - if err := ValidateField(m.Field, s); err != nil { - return err - } - } - - return nil -} - -func (m Base64) getSep() string { - if m.Separator == "" { - return "/" - } - return m.Separator -} diff --git a/vendor/github.com/rancher/norman/types/mapper/batchmove.go b/vendor/github.com/rancher/norman/types/mapper/batchmove.go deleted file mode 100644 index 051c8b1393..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/batchmove.go +++ /dev/null @@ -1,48 +0,0 @@ -package mapper - -import ( - "path" - - "github.com/rancher/norman/types" -) - -type BatchMove struct { - From []string - To string - DestDefined bool - NoDeleteFromField bool - moves []Move -} - -func (b *BatchMove) FromInternal(data map[string]interface{}) { - for _, m := range b.moves { - m.FromInternal(data) - } -} - -func (b *BatchMove) ToInternal(data map[string]interface{}) error { - errors := types.Errors{} - for i := len(b.moves) - 1; i >= 0; i-- { - errors.Add(b.moves[i].ToInternal(data)) - } - return errors.Err() -} - -func (b *BatchMove) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - for _, from := range b.From { - b.moves = append(b.moves, Move{ - From: from, - To: path.Join(b.To, from), - DestDefined: b.DestDefined, - NoDeleteFromField: b.NoDeleteFromField, - }) - } - - for _, m := range b.moves { - if err := m.ModifySchema(s, schemas); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/changetype.go b/vendor/github.com/rancher/norman/types/mapper/changetype.go deleted file mode 100644 index 1b8c54aa08..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/changetype.go +++ /dev/null @@ -1,28 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type ChangeType struct { - Field string - Type string -} - -func (c ChangeType) FromInternal(data map[string]interface{}) { -} - -func (c ChangeType) ToInternal(data map[string]interface{}) error { - return nil -} - -func (c ChangeType) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if err := ValidateField(c.Field, schema); err != nil { - return err - } - - f := schema.ResourceFields[c.Field] - f.Type = c.Type - schema.ResourceFields[c.Field] = f - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/check.go b/vendor/github.com/rancher/norman/types/mapper/check.go deleted file mode 100644 index b31bbc076a..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/check.go +++ /dev/null @@ -1,15 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -func ValidateField(field string, schema *types.Schema) error { - if _, ok := schema.ResourceFields[field]; !ok { - return fmt.Errorf("field %s missing on schema %s", field, schema.ID) - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/condition.go b/vendor/github.com/rancher/norman/types/mapper/condition.go deleted file mode 100644 index acb8a71ef4..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/condition.go +++ /dev/null @@ -1,28 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Condition struct { - Field string - Value interface{} - Mapper types.Mapper -} - -func (m Condition) FromInternal(data map[string]interface{}) { - if data[m.Field] == m.Value { - m.Mapper.FromInternal(data) - } -} - -func (m Condition) ToInternal(data map[string]interface{}) error { - if data[m.Field] == m.Value { - return m.Mapper.ToInternal(data) - } - return nil -} - -func (m Condition) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - return m.Mapper.ModifySchema(s, schemas) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/copy.go b/vendor/github.com/rancher/norman/types/mapper/copy.go deleted file mode 100644 index da1888a564..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/copy.go +++ /dev/null @@ -1,44 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -type Copy struct { - From, To string -} - -func (c Copy) FromInternal(data map[string]interface{}) { - if data == nil { - return - } - v, ok := data[c.From] - if ok { - data[c.To] = v - } -} - -func (c Copy) ToInternal(data map[string]interface{}) error { - if data == nil { - return nil - } - t, tok := data[c.To] - _, fok := data[c.From] - if tok && !fok { - data[c.From] = t - } - - return nil -} - -func (c Copy) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - f, ok := s.ResourceFields[c.From] - if !ok { - return fmt.Errorf("field %s missing on schema %s", c.From, s.ID) - } - - s.ResourceFields[c.To] = f - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/display_name.go b/vendor/github.com/rancher/norman/types/mapper/display_name.go deleted file mode 100644 index 85ac3ab734..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/display_name.go +++ /dev/null @@ -1,29 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -var displayNameMappers = types.Mappers{ - &Move{From: "name", To: "id"}, - &Move{From: "displayName", To: "name"}, - Access{Fields: map[string]string{ - "id": "", - "name": "cru", - }}, -} - -type DisplayName struct { -} - -func (d DisplayName) FromInternal(data map[string]interface{}) { - displayNameMappers.FromInternal(data) -} - -func (d DisplayName) ToInternal(data map[string]interface{}) error { - return displayNameMappers.ToInternal(data) -} - -func (d DisplayName) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - return displayNameMappers.ModifySchema(schema, schemas) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/drop.go b/vendor/github.com/rancher/norman/types/mapper/drop.go deleted file mode 100644 index 3bb75e68b1..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/drop.go +++ /dev/null @@ -1,31 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -type Drop struct { - Field string - IgnoreDefinition bool -} - -func (d Drop) FromInternal(data map[string]interface{}) { - delete(data, d.Field) -} - -func (d Drop) ToInternal(data map[string]interface{}) error { - return nil -} - -func (d Drop) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if _, ok := schema.ResourceFields[d.Field]; !ok { - if !d.IgnoreDefinition { - return fmt.Errorf("can not drop missing field %s on %s", d.Field, schema.ID) - } - } - - delete(schema.ResourceFields, d.Field) - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/embed.go b/vendor/github.com/rancher/norman/types/mapper/embed.go deleted file mode 100644 index b1d35d9818..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/embed.go +++ /dev/null @@ -1,106 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" -) - -type Embed struct { - Field string - Optional bool - ReadOnly bool - Ignore []string - ignoreOverride bool - embeddedFields []string - EmptyValueOk bool -} - -func (e *Embed) FromInternal(data map[string]interface{}) { - sub, _ := data[e.Field].(map[string]interface{}) - for _, fieldName := range e.embeddedFields { - if v, ok := sub[fieldName]; ok { - data[fieldName] = v - } - } - delete(data, e.Field) -} - -func (e *Embed) ToInternal(data map[string]interface{}) error { - if data == nil { - return nil - } - - sub := map[string]interface{}{} - for _, fieldName := range e.embeddedFields { - if v, ok := data[fieldName]; ok { - sub[fieldName] = v - } - - delete(data, fieldName) - } - if len(sub) == 0 { - if e.EmptyValueOk { - data[e.Field] = nil - } - return nil - } - data[e.Field] = sub - return nil -} - -func (e *Embed) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - err := ValidateField(e.Field, schema) - if err != nil { - if e.Optional { - return nil - } - return err - } - - e.embeddedFields = []string{} - - embeddedSchemaID := schema.ResourceFields[e.Field].Type - embeddedSchema := schemas.Schema(&schema.Version, embeddedSchemaID) - if embeddedSchema == nil { - if e.Optional { - return nil - } - return fmt.Errorf("failed to find schema %s for embedding", embeddedSchemaID) - } - - deleteField := true -outer: - for name, field := range embeddedSchema.ResourceFields { - for _, ignore := range e.Ignore { - if ignore == name { - continue outer - } - } - - if name == e.Field { - deleteField = false - } else { - if !e.ignoreOverride { - if _, ok := schema.ResourceFields[name]; ok { - return fmt.Errorf("embedding field %s on %s will overwrite the field %s", - e.Field, schema.ID, name) - } - } - } - - if e.ReadOnly { - field.Create = false - field.Update = false - } - - schema.ResourceFields[name] = field - e.embeddedFields = append(e.embeddedFields, name) - } - - if deleteField { - delete(schema.ResourceFields, e.Field) - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/enum.go b/vendor/github.com/rancher/norman/types/mapper/enum.go deleted file mode 100644 index 9cb892c355..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/enum.go +++ /dev/null @@ -1,29 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Enum struct { - Field string - Options []string -} - -func (e Enum) FromInternal(data map[string]interface{}) { -} - -func (e Enum) ToInternal(data map[string]interface{}) error { - return nil -} - -func (e Enum) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if err := ValidateField(e.Field, schema); err != nil { - return err - } - - f := schema.ResourceFields[e.Field] - f.Type = "enum" - f.Options = e.Options - schema.ResourceFields[e.Field] = f - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/json_encode.go b/vendor/github.com/rancher/norman/types/mapper/json_encode.go deleted file mode 100644 index dc9e5cc97b..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/json_encode.go +++ /dev/null @@ -1,52 +0,0 @@ -package mapper - -import ( - "strings" - - "encoding/json" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/values" -) - -type JSONEncode struct { - Field string - IgnoreDefinition bool - Separator string -} - -func (m JSONEncode) FromInternal(data map[string]interface{}) { - if v, ok := values.RemoveValue(data, strings.Split(m.Field, m.getSep())...); ok { - obj := map[string]interface{}{} - if err := json.Unmarshal([]byte(convert.ToString(v)), &obj); err == nil { - values.PutValue(data, obj, strings.Split(m.Field, m.getSep())...) - } else { - log.Errorf("Failed to unmarshal json field: %v", err) - } - } -} - -func (m JSONEncode) ToInternal(data map[string]interface{}) error { - if v, ok := values.RemoveValue(data, strings.Split(m.Field, m.getSep())...); ok && v != nil { - if bytes, err := json.Marshal(v); err == nil { - values.PutValue(data, string(bytes), strings.Split(m.Field, m.getSep())...) - } - } - return nil -} - -func (m JSONEncode) getSep() string { - if m.Separator == "" { - return "/" - } - return m.Separator -} - -func (m JSONEncode) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - if m.IgnoreDefinition { - return nil - } - - return ValidateField(m.Field, s) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/label_field.go b/vendor/github.com/rancher/norman/types/mapper/label_field.go deleted file mode 100644 index 971cbe04d5..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/label_field.go +++ /dev/null @@ -1,29 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/values" -) - -type LabelField struct { - Field string -} - -func (e LabelField) FromInternal(data map[string]interface{}) { - v, ok := values.RemoveValue(data, "labels", "field.cattle.io/"+e.Field) - if ok { - data[e.Field] = v - } -} - -func (e LabelField) ToInternal(data map[string]interface{}) error { - v, ok := data[e.Field] - if ok { - values.PutValue(data, v, "labels", "field.cattle.io/"+e.Field) - } - return nil -} - -func (e LabelField) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - return ValidateField(e.Field, schema) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/log.go b/vendor/github.com/rancher/norman/types/mapper/log.go deleted file mode 100644 index 0743c40328..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package mapper - -import "github.com/sirupsen/logrus" - -var ( - log = logrus.WithField("component", "norman/mapper") -) diff --git a/vendor/github.com/rancher/norman/types/mapper/metadata.go b/vendor/github.com/rancher/norman/types/mapper/metadata.go deleted file mode 100644 index 2661050904..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/metadata.go +++ /dev/null @@ -1,29 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -func NewMetadataMapper() types.Mapper { - return types.Mappers{ - ChangeType{Field: "name", Type: "dnsLabel"}, - Drop{Field: "generateName"}, - Move{From: "uid", To: "uuid", CodeName: "UUID"}, - Drop{Field: "resourceVersion"}, - Drop{Field: "generation"}, - Move{From: "creationTimestamp", To: "created"}, - Move{From: "deletionTimestamp", To: "removed"}, - Drop{Field: "deletionGracePeriodSeconds"}, - Drop{Field: "initializers"}, - Drop{Field: "clusterName"}, - ReadOnly{Field: "*"}, - Access{ - Fields: map[string]string{ - "name": "c", - "namespace": "c", - "labels": "cu", - "annotations": "cu", - }, - }, - } -} diff --git a/vendor/github.com/rancher/norman/types/mapper/move.go b/vendor/github.com/rancher/norman/types/mapper/move.go deleted file mode 100644 index 03629a64f8..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/move.go +++ /dev/null @@ -1,89 +0,0 @@ -package mapper - -import ( - "fmt" - - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" - "github.com/rancher/norman/types/values" -) - -type Move struct { - From, To, CodeName string - DestDefined bool - NoDeleteFromField bool -} - -func (m Move) FromInternal(data map[string]interface{}) { - if v, ok := values.RemoveValue(data, strings.Split(m.From, "/")...); ok { - values.PutValue(data, v, strings.Split(m.To, "/")...) - } -} - -func (m Move) ToInternal(data map[string]interface{}) error { - if v, ok := values.RemoveValue(data, strings.Split(m.To, "/")...); ok { - values.PutValue(data, v, strings.Split(m.From, "/")...) - } - return nil -} - -func (m Move) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - fromSchema, _, fromField, ok, err := getField(s, schemas, m.From) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("failed to find field %s on schema %s", m.From, s.ID) - } - - toSchema, toFieldName, _, ok, err := getField(s, schemas, m.To) - if err != nil { - return err - } - _, ok = toSchema.ResourceFields[toFieldName] - if ok && !strings.Contains(m.To, "/") && !m.DestDefined { - return fmt.Errorf("field %s already exists on schema %s", m.To, s.ID) - } - - if !m.NoDeleteFromField { - delete(fromSchema.ResourceFields, m.From) - } - - if !m.DestDefined { - if m.CodeName == "" { - fromField.CodeName = convert.Capitalize(toFieldName) - } else { - fromField.CodeName = m.CodeName - } - toSchema.ResourceFields[toFieldName] = fromField - } - - return nil -} - -func getField(schema *types.Schema, schemas *types.Schemas, target string) (*types.Schema, string, types.Field, bool, error) { - parts := strings.Split(target, "/") - for i, part := range parts { - if i == len(parts)-1 { - continue - } - - fieldType := schema.ResourceFields[part].Type - if definition.IsArrayType(fieldType) { - fieldType = definition.SubType(fieldType) - } - subSchema := schemas.Schema(&schema.Version, fieldType) - if subSchema == nil { - return nil, "", types.Field{}, false, fmt.Errorf("failed to find field or schema for %s on %s", part, schema.ID) - } - - schema = subSchema - } - - name := parts[len(parts)-1] - f, ok := schema.ResourceFields[name] - return schema, name, f, ok, nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/object.go b/vendor/github.com/rancher/norman/types/mapper/object.go deleted file mode 100644 index 07503a1169..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/object.go +++ /dev/null @@ -1,30 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Object struct { - types.Mappers -} - -func NewObject(mappers ...types.Mapper) Object { - return Object{ - Mappers: append([]types.Mapper{ - &APIGroup{}, - &Embed{Field: "metadata"}, - &Embed{Field: "spec", Optional: true}, - &ReadOnly{Field: "status", Optional: true, SubFields: true}, - Drop{Field: "kind"}, - Drop{Field: "apiVersion"}, - Move{From: "selfLink", To: ".selfLink", DestDefined: true}, - &Scope{ - IfNot: types.NamespaceScope, - Mappers: []types.Mapper{ - &Drop{Field: "namespace"}, - }, - }, - Drop{Field: "finalizers", IgnoreDefinition: true}, - }, mappers...), - } -} diff --git a/vendor/github.com/rancher/norman/types/mapper/pendingstatus.go b/vendor/github.com/rancher/norman/types/mapper/pendingstatus.go deleted file mode 100644 index bba86461c2..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/pendingstatus.go +++ /dev/null @@ -1,35 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/values" -) - -type PendingStatus struct { -} - -func (s PendingStatus) FromInternal(data map[string]interface{}) { - if data == nil { - return - } - - if data["state"] != "active" { - return - } - - conditions := convert.ToMapSlice(values.GetValueN(data, "status", "conditions")) - if len(conditions) > 0 { - return - } - - data["state"] = "pending" -} - -func (s PendingStatus) ToInternal(data map[string]interface{}) error { - return nil -} - -func (s PendingStatus) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/read_only.go b/vendor/github.com/rancher/norman/types/mapper/read_only.go deleted file mode 100644 index 916205f847..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/read_only.go +++ /dev/null @@ -1,57 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type ReadOnly struct { - Field string - Optional bool - SubFields bool -} - -func (r ReadOnly) FromInternal(data map[string]interface{}) { -} - -func (r ReadOnly) ToInternal(data map[string]interface{}) error { - return nil -} - -func (r ReadOnly) readOnly(field types.Field, schema *types.Schema, schemas *types.Schemas) types.Field { - field.Create = false - field.Update = false - - if r.SubFields { - subSchema := schemas.Schema(&schema.Version, field.Type) - if subSchema != nil { - for name, field := range subSchema.ResourceFields { - field.Create = false - field.Update = false - subSchema.ResourceFields[name] = field - } - } - } - - return field -} - -func (r ReadOnly) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if r.Field == "*" { - for name, field := range schema.ResourceFields { - schema.ResourceFields[name] = r.readOnly(field, schema, schemas) - } - return nil - } - - if err := ValidateField(r.Field, schema); err != nil { - if r.Optional { - return nil - } - return err - } - - field := schema.ResourceFields[r.Field] - schema.ResourceFields[r.Field] = r.readOnly(field, schema, schemas) - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/rename_reference.go b/vendor/github.com/rancher/norman/types/mapper/rename_reference.go deleted file mode 100644 index d63fb5e64c..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/rename_reference.go +++ /dev/null @@ -1,57 +0,0 @@ -package mapper - -import ( - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" -) - -type RenameReference struct { - mapper types.Mapper -} - -func (r *RenameReference) FromInternal(data map[string]interface{}) { - if r.mapper != nil { - r.mapper.FromInternal(data) - } -} - -func (r *RenameReference) ToInternal(data map[string]interface{}) error { - if r.mapper != nil { - return r.mapper.ToInternal(data) - } - return nil -} - -func (r *RenameReference) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - var mappers []types.Mapper - for name, field := range schema.ResourceFields { - if definition.IsReferenceType(field.Type) && strings.HasSuffix(name, "Name") { - newName := strings.TrimSuffix(name, "Name") + "Id" - newCodeName := convert.Capitalize(strings.TrimSuffix(name, "Name") + "ID") - move := Move{From: name, To: newName, CodeName: newCodeName} - if err := move.ModifySchema(schema, schemas); err != nil { - return err - } - - mappers = append(mappers, move) - } else if definition.IsArrayType(field.Type) && definition.IsReferenceType(definition.SubType(field.Type)) && strings.HasSuffix(name, "Names") { - newName := strings.TrimSuffix(name, "Names") + "Ids" - newCodeName := convert.Capitalize(strings.TrimSuffix(name, "Names") + "IDs") - move := Move{From: name, To: newName, CodeName: newCodeName} - if err := move.ModifySchema(schema, schemas); err != nil { - return err - } - - mappers = append(mappers, move) - } - } - - if len(mappers) > 0 { - r.mapper = types.Mappers(mappers) - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/required.go b/vendor/github.com/rancher/norman/types/mapper/required.go deleted file mode 100644 index 7c4c5da625..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/required.go +++ /dev/null @@ -1,30 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Required struct { - Fields []string -} - -func (e Required) FromInternal(data map[string]interface{}) { -} - -func (e Required) ToInternal(data map[string]interface{}) error { - return nil -} - -func (e Required) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - for _, field := range e.Fields { - if err := ValidateField(field, schema); err != nil { - return err - } - - f := schema.ResourceFields[field] - f.Required = true - schema.ResourceFields[field] = f - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/root.go b/vendor/github.com/rancher/norman/types/mapper/root.go deleted file mode 100644 index 407b60e3bb..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/root.go +++ /dev/null @@ -1,31 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Root struct { - enabled bool - Mapper types.Mapper -} - -func (m *Root) FromInternal(data map[string]interface{}) { - if m.enabled { - m.Mapper.FromInternal(data) - } -} - -func (m *Root) ToInternal(data map[string]interface{}) error { - if m.enabled { - return m.Mapper.ToInternal(data) - } - return nil -} - -func (m *Root) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - if s.CanList(nil) == nil { - m.enabled = true - return m.Mapper.ModifySchema(s, schemas) - } - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/scope.go b/vendor/github.com/rancher/norman/types/mapper/scope.go deleted file mode 100644 index 5c6437206b..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/scope.go +++ /dev/null @@ -1,38 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" -) - -type Scope struct { - If types.TypeScope - IfNot types.TypeScope - Mappers []types.Mapper - run bool -} - -func (s *Scope) FromInternal(data map[string]interface{}) { - if s.run { - types.Mappers(s.Mappers).FromInternal(data) - } -} - -func (s *Scope) ToInternal(data map[string]interface{}) error { - if s.run { - return types.Mappers(s.Mappers).ToInternal(data) - } - return nil -} - -func (s *Scope) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if s.If != "" { - s.run = schema.Scope == s.If - } - if s.IfNot != "" { - s.run = schema.Scope != s.IfNot - } - if s.run { - return types.Mappers(s.Mappers).ModifySchema(schema, schemas) - } - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/set_value.go b/vendor/github.com/rancher/norman/types/mapper/set_value.go deleted file mode 100644 index 745a7716f2..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/set_value.go +++ /dev/null @@ -1,71 +0,0 @@ -package mapper - -import ( - "fmt" - - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/values" -) - -type SetValue struct { - Field, To string - Value interface{} - IfEq interface{} - IgnoreDefinition bool -} - -func (s SetValue) FromInternal(data map[string]interface{}) { - if s.IfEq == nil { - values.PutValue(data, s.Value, strings.Split(s.getTo(), "/")...) - return - } - - v, ok := values.GetValue(data, strings.Split(s.Field, "/")...) - if !ok { - return - } - - if v == s.IfEq { - values.PutValue(data, s.Value, strings.Split(s.getTo(), "/")...) - } -} - -func (s SetValue) getTo() string { - if s.To == "" { - return s.Field - } - return s.To -} - -func (s SetValue) ToInternal(data map[string]interface{}) error { - v, ok := values.GetValue(data, strings.Split(s.getTo(), "/")...) - if !ok { - return nil - } - - if s.IfEq == nil { - values.RemoveValue(data, strings.Split(s.Field, "/")...) - } else if v == s.Value { - values.PutValue(data, s.IfEq, strings.Split(s.Field, "/")...) - } - - return nil -} - -func (s SetValue) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if s.IgnoreDefinition { - return nil - } - - _, _, _, ok, err := getField(schema, schemas, s.getTo()) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("failed to find defined field for %s on schemas %s", s.getTo(), schema.ID) - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/slice_merge.go b/vendor/github.com/rancher/norman/types/mapper/slice_merge.go deleted file mode 100644 index 5cefe96629..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/slice_merge.go +++ /dev/null @@ -1,48 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -type SliceMerge struct { - From []string - To string - IgnoreDefinition bool -} - -func (s SliceMerge) FromInternal(data map[string]interface{}) { - var result []interface{} - for _, name := range s.From { - val, ok := data[name] - if !ok { - continue - } - result = append(result, convert.ToInterfaceSlice(val)...) - } - - if result != nil { - data[s.To] = result - } -} - -func (s SliceMerge) ToInternal(data map[string]interface{}) error { - return nil -} - -func (s SliceMerge) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if s.IgnoreDefinition { - return nil - } - - for _, from := range s.From { - if err := ValidateField(from, schema); err != nil { - return err - } - if from != s.To { - delete(schema.ResourceFields, from) - } - } - - return ValidateField(s.To, schema) -} diff --git a/vendor/github.com/rancher/norman/types/mapper/slice_to_map.go b/vendor/github.com/rancher/norman/types/mapper/slice_to_map.go deleted file mode 100644 index 79c95247cd..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/slice_to_map.go +++ /dev/null @@ -1,75 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/definition" -) - -type SliceToMap struct { - Field string - Key string -} - -func (s SliceToMap) FromInternal(data map[string]interface{}) { - datas, _ := data[s.Field].([]interface{}) - result := map[string]interface{}{} - - for _, item := range datas { - if mapItem, ok := item.(map[string]interface{}); ok { - name, _ := mapItem[s.Key].(string) - delete(mapItem, s.Key) - result[name] = mapItem - } - } - - if len(result) > 0 { - data[s.Field] = result - } -} - -func (s SliceToMap) ToInternal(data map[string]interface{}) error { - datas, _ := data[s.Field].(map[string]interface{}) - var result []interface{} - - for name, item := range datas { - mapItem, _ := item.(map[string]interface{}) - if mapItem != nil { - mapItem[s.Key] = name - result = append(result, mapItem) - } - } - - if len(result) > 0 { - data[s.Field] = result - } else if datas != nil { - data[s.Field] = result - } - - return nil -} - -func (s SliceToMap) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - err := ValidateField(s.Field, schema) - if err != nil { - return err - } - - subSchema, subFieldName, _, _, err := getField(schema, schemas, fmt.Sprintf("%s/%s", s.Field, s.Key)) - if err != nil { - return err - } - - field := schema.ResourceFields[s.Field] - if !definition.IsArrayType(field.Type) { - return fmt.Errorf("field %s on %s is not an array", s.Field, schema.ID) - } - - field.Type = "map[" + definition.SubType(field.Type) + "]" - schema.ResourceFields[s.Field] = field - - delete(subSchema.ResourceFields, subFieldName) - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/union_embed.go b/vendor/github.com/rancher/norman/types/mapper/union_embed.go deleted file mode 100644 index e0766f3237..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/union_embed.go +++ /dev/null @@ -1,69 +0,0 @@ -package mapper - -import ( - "fmt" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/convert" -) - -type UnionMapping struct { - FieldName string - CheckFields []string -} - -type UnionEmbed struct { - Fields []UnionMapping - embeds map[string]Embed -} - -func (u *UnionEmbed) FromInternal(data map[string]interface{}) { - for _, embed := range u.embeds { - embed.FromInternal(data) - } -} - -func (u *UnionEmbed) ToInternal(data map[string]interface{}) error { -outer: - for _, mapper := range u.Fields { - if len(mapper.CheckFields) == 0 { - continue - } - - for _, check := range mapper.CheckFields { - v, ok := data[check] - if !ok || convert.IsAPIObjectEmpty(v) { - continue outer - } - } - - embed := u.embeds[mapper.FieldName] - return embed.ToInternal(data) - } - - return nil -} - -func (u *UnionEmbed) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - u.embeds = map[string]Embed{} - - for _, mapping := range u.Fields { - embed := Embed{ - Field: mapping.FieldName, - ignoreOverride: true, - } - if err := embed.ModifySchema(schema, schemas); err != nil { - return err - } - - for _, checkField := range mapping.CheckFields { - if _, ok := schema.ResourceFields[checkField]; !ok { - return fmt.Errorf("missing check field %s on schema %s", checkField, schema.ID) - } - } - - u.embeds[mapping.FieldName] = embed - } - - return nil -} diff --git a/vendor/github.com/rancher/norman/types/mapper/untyped_move.go b/vendor/github.com/rancher/norman/types/mapper/untyped_move.go deleted file mode 100644 index e46a38b3a4..0000000000 --- a/vendor/github.com/rancher/norman/types/mapper/untyped_move.go +++ /dev/null @@ -1,38 +0,0 @@ -package mapper - -import ( - "strings" - - "github.com/rancher/norman/types" - "github.com/rancher/norman/types/values" -) - -type UntypedMove struct { - From, To string - Separator string -} - -func (m UntypedMove) FromInternal(data map[string]interface{}) { - if v, ok := values.RemoveValue(data, strings.Split(m.From, m.getSep())...); ok { - values.PutValue(data, v, strings.Split(m.To, m.getSep())...) - } -} - -func (m UntypedMove) ToInternal(data map[string]interface{}) error { - if v, ok := values.RemoveValue(data, strings.Split(m.To, m.getSep())...); ok { - values.PutValue(data, v, strings.Split(m.From, m.getSep())...) - } - - return nil -} - -func (m UntypedMove) getSep() string { - if m.Separator == "" { - return "/" - } - return m.Separator -} - -func (m UntypedMove) ModifySchema(s *types.Schema, schemas *types.Schemas) error { - return nil -} diff --git a/vendor/github.com/rancher/norman/types/reflection.go b/vendor/github.com/rancher/norman/types/reflection.go deleted file mode 100644 index 33295c32f1..0000000000 --- a/vendor/github.com/rancher/norman/types/reflection.go +++ /dev/null @@ -1,507 +0,0 @@ -package types - -import ( - "fmt" - "net/http" - "reflect" - "strconv" - "strings" - - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" - "github.com/rancher/norman/types/slice" - "github.com/sirupsen/logrus" -) - -var ( - namespacedType = reflect.TypeOf(Namespaced{}) - resourceType = reflect.TypeOf(Resource{}) - blacklistNames = map[string]bool{ - "links": true, - "actions": true, - } -) - -func (s *Schemas) TypeName(name string, obj interface{}) *Schemas { - s.typeNames[reflect.TypeOf(obj)] = name - return s -} - -func (s *Schemas) getTypeName(t reflect.Type) string { - if name, ok := s.typeNames[t]; ok { - return name - } - return convert.LowerTitle(t.Name()) -} - -func (s *Schemas) AddMapperForType(version *APIVersion, obj interface{}, mapper ...Mapper) *Schemas { - if len(mapper) == 0 { - return s - } - - t := reflect.TypeOf(obj) - typeName := s.getTypeName(t) - if len(mapper) == 1 { - return s.AddMapper(version, typeName, mapper[0]) - } - return s.AddMapper(version, typeName, Mappers(mapper)) -} - -func (s *Schemas) MustImport(version *APIVersion, obj interface{}, externalOverrides ...interface{}) *Schemas { - if reflect.ValueOf(obj).Kind() == reflect.Ptr { - panic(fmt.Errorf("obj cannot be a pointer")) - } - - if _, err := s.Import(version, obj, externalOverrides...); err != nil { - panic(err) - } - return s -} - -func (s *Schemas) MustImportAndCustomize(version *APIVersion, obj interface{}, f func(*Schema), externalOverrides ...interface{}) *Schemas { - return s.MustImport(version, obj, externalOverrides...). - MustCustomizeType(version, obj, f) -} - -func (s *Schemas) Import(version *APIVersion, obj interface{}, externalOverrides ...interface{}) (*Schema, error) { - var types []reflect.Type - for _, override := range externalOverrides { - types = append(types, reflect.TypeOf(override)) - } - - return s.importType(version, reflect.TypeOf(obj), types...) -} - -func (s *Schemas) newSchemaFromType(version *APIVersion, t reflect.Type, typeName string) (*Schema, error) { - schema := &Schema{ - ID: typeName, - Version: *version, - CodeName: t.Name(), - PkgName: t.PkgPath(), - ResourceFields: map[string]Field{}, - ResourceActions: map[string]Action{}, - CollectionActions: map[string]Action{}, - } - - s.processingTypes[t] = schema - defer delete(s.processingTypes, t) - - if err := s.readFields(schema, t); err != nil { - return nil, err - } - - return schema, nil -} - -func (s *Schemas) setupFilters(schema *Schema) { - if !slice.ContainsString(schema.CollectionMethods, http.MethodGet) { - return - } - for fieldName, field := range schema.ResourceFields { - var mods []ModifierType - switch field.Type { - case "enum": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "date": - fallthrough - case "dnsLabel": - fallthrough - case "hostname": - fallthrough - case "string": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "int": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "boolean": - mods = []ModifierType{ModifierEQ, ModifierNE} - default: - if definition.IsReferenceType(field.Type) { - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - } - } - - if len(mods) > 0 { - if schema.CollectionFilters == nil { - schema.CollectionFilters = map[string]Filter{} - } - schema.CollectionFilters[fieldName] = Filter{ - Modifiers: mods, - } - } - } -} - -func (s *Schemas) MustCustomizeType(version *APIVersion, obj interface{}, f func(*Schema)) *Schemas { - name := s.getTypeName(reflect.TypeOf(obj)) - schema := s.Schema(version, name) - if schema == nil { - panic("Failed to find schema " + name) - } - - f(schema) - - return s -} - -func (s *Schemas) importType(version *APIVersion, t reflect.Type, overrides ...reflect.Type) (*Schema, error) { - typeName := s.getTypeName(t) - - existing := s.Schema(version, typeName) - if existing != nil { - return existing, nil - } - - if s, ok := s.processingTypes[t]; ok { - logrus.Debugf("Returning half built schema %s for %v", typeName, t) - return s, nil - } - - logrus.Debugf("Inspecting schema %s for %v", typeName, t) - - schema, err := s.newSchemaFromType(version, t, typeName) - if err != nil { - return nil, err - } - - mappers := s.mapper(&schema.Version, schema.ID) - if s.DefaultMappers != nil { - if schema.CanList(nil) == nil { - mappers = append(s.DefaultMappers(), mappers...) - } - } - if s.DefaultPostMappers != nil { - mappers = append(mappers, s.DefaultPostMappers()...) - } - - if len(mappers) > 0 { - copy, err := s.newSchemaFromType(version, t, typeName) - if err != nil { - return nil, err - } - schema.InternalSchema = copy - } - - for _, override := range overrides { - if err := s.readFields(schema, override); err != nil { - return nil, err - } - } - - mapper := &typeMapper{ - Mappers: mappers, - root: schema.CanList(nil) == nil, - } - - if err := mapper.ModifySchema(schema, s); err != nil { - return nil, err - } - - s.setupFilters(schema) - - schema.Mapper = mapper - s.AddSchema(*schema) - - return s.Schema(&schema.Version, schema.ID), s.Err() -} - -func jsonName(f reflect.StructField) string { - return strings.SplitN(f.Tag.Get("json"), ",", 2)[0] -} - -func k8sType(field reflect.StructField) bool { - return field.Type.Name() == "TypeMeta" && - strings.HasSuffix(field.Type.PkgPath(), "k8s.io/apimachinery/pkg/apis/meta/v1") -} - -func k8sObject(field reflect.StructField) bool { - return field.Type.Name() == "ObjectMeta" && - strings.HasSuffix(field.Type.PkgPath(), "k8s.io/apimachinery/pkg/apis/meta/v1") -} - -func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { - if t == resourceType { - schema.CollectionMethods = []string{"GET", "POST"} - schema.ResourceMethods = []string{"GET", "PUT", "DELETE"} - } - - hasType := false - hasMeta := false - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - - if field.PkgPath != "" { - // unexported field - continue - } - - jsonName := jsonName(field) - if jsonName == "-" { - continue - } - - if field.Anonymous && jsonName == "" && k8sType(field) { - hasType = true - } - - if field.Anonymous && jsonName == "metadata" && k8sObject(field) { - hasMeta = true - } - - if field.Anonymous && jsonName == "" { - t := field.Type - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - if t.Kind() == reflect.Struct { - if t == namespacedType { - schema.Scope = NamespaceScope - } - if err := s.readFields(schema, t); err != nil { - return err - } - } - continue - } - - fieldName := jsonName - if fieldName == "" { - fieldName = convert.LowerTitle(field.Name) - if strings.HasSuffix(fieldName, "ID") { - fieldName = strings.TrimSuffix(fieldName, "ID") + "Id" - } - } - - if blacklistNames[fieldName] { - logrus.Debugf("Ignoring blacklisted field %s.%s for %v", schema.ID, fieldName, field) - continue - } - - logrus.Debugf("Inspecting field %s.%s for %v", schema.ID, fieldName, field) - - schemaField := Field{ - Create: true, - Update: true, - Nullable: true, - CodeName: field.Name, - } - - fieldType := field.Type - if fieldType.Kind() == reflect.Ptr { - schemaField.Nullable = true - fieldType = fieldType.Elem() - } else if fieldType.Kind() == reflect.Bool { - schemaField.Nullable = false - schemaField.Default = false - } else if fieldType.Kind() == reflect.Int || - fieldType.Kind() == reflect.Uint32 || - fieldType.Kind() == reflect.Int32 || - fieldType.Kind() == reflect.Uint64 || - fieldType.Kind() == reflect.Int64 || - fieldType.Kind() == reflect.Float32 || - fieldType.Kind() == reflect.Float64 { - schemaField.Nullable = false - schemaField.Default = 0 - } - - if err := applyTag(&field, &schemaField); err != nil { - return err - } - - if schemaField.Type == "" { - inferedType, err := s.determineSchemaType(&schema.Version, fieldType) - if err != nil { - return fmt.Errorf("failed inspecting type %s, field %s: %v", t, fieldName, err) - } - schemaField.Type = inferedType - } - - if schemaField.Default != nil { - switch schemaField.Type { - case "int": - n, err := convert.ToNumber(schemaField.Default) - if err != nil { - return err - } - schemaField.Default = n - case "float": - n, err := convert.ToFloat(schemaField.Default) - if err != nil { - return err - } - schemaField.Default = n - case "boolean": - schemaField.Default = convert.ToBool(schemaField.Default) - } - } - - logrus.Debugf("Setting field %s.%s: %#v", schema.ID, fieldName, schemaField) - schema.ResourceFields[fieldName] = schemaField - } - - if hasType && hasMeta { - schema.CollectionMethods = []string{"GET", "POST"} - schema.ResourceMethods = []string{"GET", "PUT", "DELETE"} - } - - return nil -} - -func applyTag(structField *reflect.StructField, field *Field) error { - for _, part := range strings.Split(structField.Tag.Get("norman"), ",") { - if part == "" { - continue - } - - var err error - key, value := getKeyValue(part) - - switch key { - case "type": - field.Type = value - case "codeName": - field.CodeName = value - case "default": - field.Default = value - case "nullable": - field.Nullable = true - case "notnullable": - field.Nullable = false - case "nocreate": - field.Create = false - case "writeOnly": - field.WriteOnly = true - case "required": - field.Required = true - case "noupdate": - field.Update = false - case "minLength": - field.MinLength, err = toInt(value, structField) - case "maxLength": - field.MaxLength, err = toInt(value, structField) - case "min": - field.Min, err = toInt(value, structField) - case "max": - field.Max, err = toInt(value, structField) - case "options": - field.Options = split(value) - if field.Type == "" { - field.Type = "enum" - } - case "validChars": - field.ValidChars = value - case "invalidChars": - field.InvalidChars = value - default: - return fmt.Errorf("invalid tag %s on field %s", key, structField.Name) - } - - if err != nil { - return err - } - } - - return nil -} - -func toInt(value string, structField *reflect.StructField) (*int64, error) { - i, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return nil, fmt.Errorf("invalid number on field %s: %v", structField.Name, err) - } - return &i, nil -} - -func split(input string) []string { - result := []string{} - for _, i := range strings.Split(input, "|") { - for _, part := range strings.Split(i, " ") { - part = strings.TrimSpace(part) - if len(part) > 0 { - result = append(result, part) - } - } - } - - return result -} - -func getKeyValue(input string) (string, string) { - var ( - key, value string - ) - parts := strings.SplitN(input, "=", 2) - key = parts[0] - if len(parts) > 1 { - value = parts[1] - } - - return key, value -} - -func deRef(p reflect.Type) reflect.Type { - if p.Kind() == reflect.Ptr { - return p.Elem() - } - return p -} - -func (s *Schemas) determineSchemaType(version *APIVersion, t reflect.Type) (string, error) { - switch t.Kind() { - case reflect.Uint8: - return "byte", nil - case reflect.Bool: - return "boolean", nil - case reflect.Int: - fallthrough - case reflect.Int32: - fallthrough - case reflect.Uint32: - fallthrough - case reflect.Uint64: - fallthrough - case reflect.Int64: - return "int", nil - case reflect.Float32: - fallthrough - case reflect.Float64: - return "float", nil - case reflect.Interface: - return "json", nil - case reflect.Map: - subType, err := s.determineSchemaType(version, deRef(t.Elem())) - if err != nil { - return "", err - } - return fmt.Sprintf("map[%s]", subType), nil - case reflect.Slice: - subType, err := s.determineSchemaType(version, deRef(t.Elem())) - if err != nil { - return "", err - } - if subType == "byte" { - return "base64", nil - } - return fmt.Sprintf("array[%s]", subType), nil - case reflect.String: - return "string", nil - case reflect.Struct: - if t.Name() == "Time" { - return "date", nil - } - if t.Name() == "IntOrString" { - return "intOrString", nil - } - if t.Name() == "Quantity" { - return "string", nil - } - schema, err := s.importType(version, t) - if err != nil { - return "", err - } - return schema.ID, nil - default: - return "", fmt.Errorf("unknown type kind %s", t.Kind()) - } - -} diff --git a/vendor/github.com/rancher/norman/types/schema_funcs.go b/vendor/github.com/rancher/norman/types/schema_funcs.go deleted file mode 100644 index f104728af6..0000000000 --- a/vendor/github.com/rancher/norman/types/schema_funcs.go +++ /dev/null @@ -1,73 +0,0 @@ -package types - -import ( - "net/http" - - "github.com/rancher/norman/httperror" - "github.com/rancher/norman/types/slice" -) - -func (s *Schema) MustCustomizeField(name string, f func(f Field) Field) *Schema { - field, ok := s.ResourceFields[name] - if !ok { - panic("Failed to find field " + name + " on schema " + s.ID) - } - s.ResourceFields[name] = f(field) - return s -} - -func (v *APIVersion) Equals(other *APIVersion) bool { - return v.Version == other.Version && - v.Group == other.Group && - v.Path == other.Path -} - -func (s *Schema) CanList(context *APIContext) error { - if context == nil { - if slice.ContainsString(s.CollectionMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not list "+s.ID) - } - return context.AccessControl.CanList(context, s) -} - -func (s *Schema) CanGet(context *APIContext) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not get "+s.ID) - } - return context.AccessControl.CanGet(context, s) -} - -func (s *Schema) CanCreate(context *APIContext) error { - if context == nil { - if slice.ContainsString(s.CollectionMethods, http.MethodPost) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not create "+s.ID) - } - return context.AccessControl.CanCreate(context, s) -} - -func (s *Schema) CanUpdate(context *APIContext) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodPut) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not update "+s.ID) - } - return context.AccessControl.CanUpdate(context, nil, s) -} - -func (s *Schema) CanDelete(context *APIContext) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodDelete) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not delete "+s.ID) - } - return context.AccessControl.CanDelete(context, nil, s) -} diff --git a/vendor/github.com/rancher/norman/types/schemas.go b/vendor/github.com/rancher/norman/types/schemas.go deleted file mode 100644 index 0e72a1787e..0000000000 --- a/vendor/github.com/rancher/norman/types/schemas.go +++ /dev/null @@ -1,392 +0,0 @@ -package types - -import ( - "bytes" - "fmt" - "reflect" - "strings" - "sync" - - "github.com/rancher/norman/name" - "github.com/rancher/norman/types/convert" - "github.com/rancher/norman/types/definition" -) - -type SchemaCollection struct { - Data []Schema -} - -type SchemasInitFunc func(*Schemas) *Schemas - -type SchemaHook func(*Schema) - -type MappersFactory func() []Mapper - -type BackReference struct { - FieldName string - Schema *Schema -} - -type Schemas struct { - sync.Mutex - processingTypes map[reflect.Type]*Schema - typeNames map[reflect.Type]string - schemasByPath map[string]map[string]*Schema - mappers map[string]map[string][]Mapper - references map[string][]BackReference - embedded map[string]*Schema - DefaultMappers MappersFactory - DefaultPostMappers MappersFactory - versions []APIVersion - schemas []*Schema - AddHook SchemaHook - errors []error -} - -func NewSchemas() *Schemas { - return &Schemas{ - processingTypes: map[reflect.Type]*Schema{}, - typeNames: map[reflect.Type]string{}, - schemasByPath: map[string]map[string]*Schema{}, - mappers: map[string]map[string][]Mapper{}, - references: map[string][]BackReference{}, - embedded: map[string]*Schema{}, - } -} - -func (s *Schemas) Init(initFunc SchemasInitFunc) *Schemas { - return initFunc(s) -} - -func (s *Schemas) Err() error { - return NewErrors(s.errors...) -} - -func (s *Schemas) AddSchemas(schema *Schemas) *Schemas { - for _, schema := range schema.Schemas() { - s.AddSchema(*schema) - } - return s -} - -func (s *Schemas) RemoveSchema(schema Schema) *Schemas { - s.Lock() - defer s.Unlock() - return s.doRemoveSchema(schema) -} - -func (s *Schemas) doRemoveSchema(schema Schema) *Schemas { - delete(s.schemasByPath[schema.Version.Path], schema.ID) - - s.removeReferences(&schema) - - if schema.Embed { - s.removeEmbed(&schema) - } - - return s -} - -func (s *Schemas) removeReferences(schema *Schema) { - for name, values := range s.references { - changed := false - var modified []BackReference - for _, value := range values { - if value.Schema.ID == schema.ID && value.Schema.Version.Path == schema.Version.Path { - changed = true - continue - } - modified = append(modified, value) - } - - if changed { - s.references[name] = modified - } - } -} - -func (s *Schemas) AddSchema(schema Schema) *Schemas { - s.Lock() - defer s.Unlock() - return s.doAddSchema(schema) -} - -func (s *Schemas) doAddSchema(schema Schema) *Schemas { - s.setupDefaults(&schema) - - if s.AddHook != nil { - s.AddHook(&schema) - } - - schemas, ok := s.schemasByPath[schema.Version.Path] - if !ok { - schemas = map[string]*Schema{} - s.schemasByPath[schema.Version.Path] = schemas - s.versions = append(s.versions, schema.Version) - } - - if _, ok := schemas[schema.ID]; !ok { - schemas[schema.ID] = &schema - s.schemas = append(s.schemas, &schema) - - if !schema.Embed { - s.addReferences(&schema) - } - } - - if schema.Embed { - s.embed(&schema) - } - - return s -} - -func (s *Schemas) removeEmbed(schema *Schema) { - target := s.doSchema(&schema.Version, schema.EmbedType, false) - if target == nil { - return - } - - newSchema := *target - newSchema.ResourceFields = map[string]Field{} - - for k, v := range target.ResourceFields { - newSchema.ResourceFields[k] = v - } - - for k := range schema.ResourceFields { - delete(newSchema.ResourceFields, k) - } - - s.doRemoveSchema(*target) - s.doAddSchema(newSchema) -} - -func (s *Schemas) embed(schema *Schema) { - target := s.doSchema(&schema.Version, schema.EmbedType, false) - if target == nil { - return - } - - newSchema := *target - newSchema.ResourceFields = map[string]Field{} - - for k, v := range target.ResourceFields { - // We remove the dynamic fields off the existing schema in case - // they've been removed from the dynamic schema so they won't - // be accidentally left over - if !v.DynamicField { - newSchema.ResourceFields[k] = v - } - } - for k, v := range schema.ResourceFields { - newSchema.ResourceFields[k] = v - } - - s.doRemoveSchema(*target) - s.doAddSchema(newSchema) -} - -func (s *Schemas) addReferences(schema *Schema) { - for name, field := range schema.ResourceFields { - if !definition.IsReferenceType(field.Type) { - continue - } - - refType := definition.SubType(field.Type) - if !strings.HasPrefix(refType, "/") { - refType = convert.ToFullReference(schema.Version.Path, refType) - } - - s.references[refType] = append(s.references[refType], BackReference{ - FieldName: name, - Schema: schema, - }) - } -} - -func (s *Schemas) setupDefaults(schema *Schema) { - schema.Type = "/meta/schemas/schema" - if schema.ID == "" { - s.errors = append(s.errors, fmt.Errorf("ID is not set on schema: %v", schema)) - return - } - if schema.Version.Path == "" || schema.Version.Version == "" { - s.errors = append(s.errors, fmt.Errorf("version is not set on schema: %s", schema.ID)) - return - } - if schema.PluralName == "" { - schema.PluralName = name.GuessPluralName(schema.ID) - } - if schema.CodeName == "" { - schema.CodeName = convert.Capitalize(schema.ID) - } - if schema.CodeNamePlural == "" { - schema.CodeNamePlural = name.GuessPluralName(schema.CodeName) - } - if schema.BaseType == "" { - schema.BaseType = schema.ID - } -} - -func (s *Schemas) References(schema *Schema) []BackReference { - refType := convert.ToFullReference(schema.Version.Path, schema.ID) - s.Lock() - defer s.Unlock() - return s.references[refType] -} - -func (s *Schemas) AddMapper(version *APIVersion, schemaID string, mapper Mapper) *Schemas { - mappers, ok := s.mappers[version.Path] - if !ok { - mappers = map[string][]Mapper{} - s.mappers[version.Path] = mappers - } - - mappers[schemaID] = append(mappers[schemaID], mapper) - return s -} - -func (s *Schemas) SchemasForVersion(version APIVersion) map[string]*Schema { - s.Lock() - defer s.Unlock() - return s.schemasByPath[version.Path] -} - -func (s *Schemas) Versions() []APIVersion { - return s.versions -} - -func (s *Schemas) Schemas() []*Schema { - return s.schemas -} - -func (s *Schemas) mapper(version *APIVersion, name string) []Mapper { - var ( - path string - ) - - if strings.Contains(name, "/") { - idx := strings.LastIndex(name, "/") - path = name[0:idx] - name = name[idx+1:] - } else if version != nil { - path = version.Path - } else { - path = "core" - } - - mappers, ok := s.mappers[path] - if !ok { - return nil - } - - mapper := mappers[name] - if mapper != nil { - return mapper - } - - return nil -} - -func (s *Schemas) Schema(version *APIVersion, name string) *Schema { - return s.doSchema(version, name, true) -} - -func (s *Schemas) doSchema(version *APIVersion, name string, lock bool) *Schema { - var ( - path string - ) - - if strings.Contains(name, "/schemas/") { - parts := strings.SplitN(name, "/schemas/", 2) - path = parts[0] - name = parts[1] - } else if version != nil { - path = version.Path - } else { - path = "core" - } - - if lock { - s.Lock() - } - schemas, ok := s.schemasByPath[path] - if lock { - s.Unlock() - } - if !ok { - return nil - } - - schema := schemas[name] - if schema != nil { - return schema - } - - for _, check := range schemas { - if strings.EqualFold(check.ID, name) || strings.EqualFold(check.PluralName, name) { - return check - } - } - - return nil -} - -func (s *Schemas) SubContextVersionForSchema(schema *Schema) *APIVersion { - fullName := fmt.Sprintf("%s/schemas/%s", schema.Version.Path, schema.ID) - for _, version := range s.Versions() { - if version.SubContextSchema == fullName { - return &version - } - } - return nil -} - -type MultiErrors struct { - Errors []error -} - -type Errors struct { - errors []error -} - -func (e *Errors) Add(err error) { - if err != nil { - e.errors = append(e.errors, err) - } -} - -func (e *Errors) Err() error { - return NewErrors(e.errors...) -} - -func NewErrors(inErrors ...error) error { - var errors []error - for _, err := range inErrors { - if err != nil { - errors = append(errors, err) - } - } - - if len(errors) == 0 { - return nil - } else if len(errors) == 1 { - return errors[0] - } - return &MultiErrors{ - Errors: errors, - } -} - -func (m *MultiErrors) Error() string { - buf := bytes.NewBuffer(nil) - for _, err := range m.Errors { - if buf.Len() > 0 { - buf.WriteString(", ") - } - buf.WriteString(err.Error()) - } - - return buf.String() -} diff --git a/vendor/github.com/rancher/norman/types/server_types.go b/vendor/github.com/rancher/norman/types/server_types.go deleted file mode 100644 index 7fede86f13..0000000000 --- a/vendor/github.com/rancher/norman/types/server_types.go +++ /dev/null @@ -1,226 +0,0 @@ -package types - -import ( - "context" - "encoding/json" - "net/http" - "net/url" -) - -type ValuesMap struct { - Foo map[string]interface{} -} - -type RawResource struct { - ID string `json:"id,omitempty" yaml:"id,omitempty"` - Type string `json:"type,omitempty" yaml:"type,omitempty"` - Schema *Schema `json:"-" yaml:"-"` - Links map[string]string `json:"links,omitempty" yaml:"links,omitempty"` - Actions map[string]string `json:"actions,omitempty" yaml:"actions,omitempty"` - Values map[string]interface{} `json:",inline" yaml:",inline"` - ActionLinks bool `json:"-" yaml:"-"` - DropReadOnly bool `json:"-" yaml:"-"` -} - -func (r *RawResource) AddAction(apiContext *APIContext, name string) { - r.Actions[name] = apiContext.URLBuilder.Action(name, r) -} - -func (r *RawResource) MarshalJSON() ([]byte, error) { - return json.Marshal(r.ToMap()) -} - -func (r *RawResource) ToMap() map[string]interface{} { - data := map[string]interface{}{} - for k, v := range r.Values { - data[k] = v - } - - if r.ID != "" && !r.DropReadOnly { - data["id"] = r.ID - } - - if r.Type != "" && !r.DropReadOnly { - data["type"] = r.Type - } - if r.Schema.BaseType != "" && !r.DropReadOnly { - data["baseType"] = r.Schema.BaseType - } - - if len(r.Links) > 0 && !r.DropReadOnly { - data["links"] = r.Links - } - - if len(r.Actions) > 0 && !r.DropReadOnly { - if r.ActionLinks { - data["actionLinks"] = r.Actions - } else { - data["actions"] = r.Actions - } - } - return data -} - -type ActionHandler func(actionName string, action *Action, request *APIContext) error - -type RequestHandler func(request *APIContext, next RequestHandler) error - -type QueryFilter func(opts *QueryOptions, schema *Schema, data []map[string]interface{}) []map[string]interface{} - -type Validator func(request *APIContext, schema *Schema, data map[string]interface{}) error - -type InputFormatter func(request *APIContext, schema *Schema, data map[string]interface{}, create bool) error - -type Formatter func(request *APIContext, resource *RawResource) - -type CollectionFormatter func(request *APIContext, collection *GenericCollection) - -type ErrorHandler func(request *APIContext, err error) - -type SubContextAttributeProvider interface { - Query(apiContext *APIContext, schema *Schema) []*QueryCondition - Create(apiContext *APIContext, schema *Schema) map[string]interface{} -} - -type ResponseWriter interface { - Write(apiContext *APIContext, code int, obj interface{}) -} - -type AccessControl interface { - CanCreate(apiContext *APIContext, schema *Schema) error - CanList(apiContext *APIContext, schema *Schema) error - CanGet(apiContext *APIContext, schema *Schema) error - CanUpdate(apiContext *APIContext, obj map[string]interface{}, schema *Schema) error - CanDelete(apiContext *APIContext, obj map[string]interface{}, schema *Schema) error - // CanDo function should not yet be used if a corresponding specific method exists. It has been added to - // satisfy a specific usecase for the short term until full-blown dynamic RBAC can be implemented. - CanDo(apiGroup, resource, verb string, apiContext *APIContext, obj map[string]interface{}, schema *Schema) error - - Filter(apiContext *APIContext, schema *Schema, obj map[string]interface{}, context map[string]string) map[string]interface{} - FilterList(apiContext *APIContext, schema *Schema, obj []map[string]interface{}, context map[string]string) []map[string]interface{} -} - -type APIContext struct { - Action string - ID string - Type string - Link string - Method string - Schema *Schema - Schemas *Schemas - Version *APIVersion - SchemasVersion *APIVersion - Query url.Values - ResponseFormat string - ReferenceValidator ReferenceValidator - ResponseWriter ResponseWriter - QueryFilter QueryFilter - SubContextAttributeProvider SubContextAttributeProvider - URLBuilder URLBuilder - AccessControl AccessControl - SubContext map[string]string - Pagination *Pagination - - Request *http.Request - Response http.ResponseWriter -} - -type apiContextKey struct{} - -func NewAPIContext(req *http.Request, resp http.ResponseWriter, schemas *Schemas) *APIContext { - apiCtx := &APIContext{ - Response: resp, - Schemas: schemas, - } - ctx := context.WithValue(req.Context(), apiContextKey{}, apiCtx) - apiCtx.Request = req.WithContext(ctx) - return apiCtx -} - -func GetAPIContext(ctx context.Context) *APIContext { - apiContext, _ := ctx.Value(apiContextKey{}).(*APIContext) - return apiContext -} - -func (r *APIContext) Option(key string) string { - return r.Query.Get("_" + key) -} - -func (r *APIContext) WriteResponse(code int, obj interface{}) { - r.ResponseWriter.Write(r, code, obj) -} - -func (r *APIContext) FilterList(opts *QueryOptions, schema *Schema, obj []map[string]interface{}) []map[string]interface{} { - return r.QueryFilter(opts, schema, obj) -} - -func (r *APIContext) FilterObject(opts *QueryOptions, schema *Schema, obj map[string]interface{}) map[string]interface{} { - opts.Pagination = nil - result := r.QueryFilter(opts, schema, []map[string]interface{}{obj}) - if len(result) == 0 { - return nil - } - return result[0] -} - -func (r *APIContext) Filter(opts *QueryOptions, schema *Schema, obj interface{}) interface{} { - switch v := obj.(type) { - case []map[string]interface{}: - return r.FilterList(opts, schema, v) - case map[string]interface{}: - return r.FilterObject(opts, schema, v) - } - - return nil -} - -var ( - ASC = SortOrder("asc") - DESC = SortOrder("desc") -) - -type QueryOptions struct { - Sort Sort - Pagination *Pagination - Conditions []*QueryCondition - Options map[string]string -} - -type ReferenceValidator interface { - Validate(resourceType, resourceID string) bool - Lookup(resourceType, resourceID string) *RawResource -} - -type URLBuilder interface { - Current() string - Collection(schema *Schema, versionOverride *APIVersion) string - CollectionAction(schema *Schema, versionOverride *APIVersion, action string) string - SubContextCollection(subContext *Schema, contextName string, schema *Schema) string - SchemaLink(schema *Schema) string - ResourceLink(resource *RawResource) string - Link(linkName string, resource *RawResource) string - RelativeToRoot(path string) string - Version(version APIVersion) string - Marker(marker string) string - ReverseSort(order SortOrder) string - Sort(field string) string - SetSubContext(subContext string) - FilterLink(schema *Schema, fieldName string, value string) string - Action(action string, resource *RawResource) string - ResourceLinkByID(schema *Schema, id string) string - ActionLinkByID(schema *Schema, id string, action string) string -} - -type StorageContext string - -var DefaultStorageContext StorageContext - -type Store interface { - Context() StorageContext - ByID(apiContext *APIContext, schema *Schema, id string) (map[string]interface{}, error) - List(apiContext *APIContext, schema *Schema, opt *QueryOptions) ([]map[string]interface{}, error) - Create(apiContext *APIContext, schema *Schema, data map[string]interface{}) (map[string]interface{}, error) - Update(apiContext *APIContext, schema *Schema, data map[string]interface{}, id string) (map[string]interface{}, error) - Delete(apiContext *APIContext, schema *Schema, id string) (map[string]interface{}, error) - Watch(apiContext *APIContext, schema *Schema, opt *QueryOptions) (chan map[string]interface{}, error) -} diff --git a/vendor/github.com/rancher/norman/types/types.go b/vendor/github.com/rancher/norman/types/types.go deleted file mode 100644 index 21106f5a16..0000000000 --- a/vendor/github.com/rancher/norman/types/types.go +++ /dev/null @@ -1,168 +0,0 @@ -package types - -const ( - ResourceFieldID = "id" -) - -type Collection struct { - Type string `json:"type,omitempty"` - Links map[string]string `json:"links"` - CreateTypes map[string]string `json:"createTypes,omitempty"` - Actions map[string]string `json:"actions"` - Pagination *Pagination `json:"pagination,omitempty"` - Sort *Sort `json:"sort,omitempty"` - Filters map[string][]Condition `json:"filters,omitempty"` - ResourceType string `json:"resourceType"` -} - -type GenericCollection struct { - Collection - Data []interface{} `json:"data"` -} - -type ResourceCollection struct { - Collection - Data []Resource `json:"data,omitempty"` -} - -type SortOrder string - -type Sort struct { - Name string `json:"name,omitempty"` - Order SortOrder `json:"order,omitempty"` - Reverse string `json:"reverse,omitempty"` - Links map[string]string `json:"links,omitempty"` -} - -var ( - ModifierEQ ModifierType = "eq" - ModifierNE ModifierType = "ne" - ModifierNull ModifierType = "null" - ModifierNotNull ModifierType = "notnull" - ModifierIn ModifierType = "in" - ModifierNotIn ModifierType = "notin" -) - -type ModifierType string - -type Condition struct { - Modifier ModifierType `json:"modifier,omitempty"` - Value interface{} `json:"value,omitempty"` -} - -type Pagination struct { - Marker string `json:"marker,omitempty"` - First string `json:"first,omitempty"` - Previous string `json:"previous,omitempty"` - Next string `json:"next,omitempty"` - Last string `json:"last,omitempty"` - Limit *int64 `json:"limit,omitempty"` - Total *int64 `json:"total,omitempty"` - Partial bool `json:"partial,omitempty"` -} - -type Resource struct { - ID string `json:"id,omitempty"` - Type string `json:"type,omitempty"` - Links map[string]string `json:"links"` - Actions map[string]string `json:"actions"` -} - -type NamedResource struct { - Resource - Name string `json:"name"` - Description string `json:"description"` -} - -type NamedResourceCollection struct { - Collection - Data []NamedResource `json:"data,omitempty"` -} - -type APIVersion struct { - Group string `json:"group,omitempty"` - Version string `json:"version,omitempty"` - Path string `json:"path,omitempty"` - SubContext bool `json:"subContext,omitempty"` - SubContextSchema string `json:"filterField,omitempty"` -} - -type Namespaced struct{} - -var NamespaceScope TypeScope = "namespace" - -type TypeScope string - -type Schema struct { - ID string `json:"id,omitempty"` - Embed bool `json:"embed,omitempty"` - EmbedType string `json:"embedType,omitempty"` - CodeName string `json:"-"` - CodeNamePlural string `json:"-"` - PkgName string `json:"-"` - Type string `json:"type,omitempty"` - BaseType string `json:"baseType,omitempty"` - Links map[string]string `json:"links"` - Version APIVersion `json:"version"` - PluralName string `json:"pluralName,omitempty"` - ResourceMethods []string `json:"resourceMethods,omitempty"` - ResourceFields map[string]Field `json:"resourceFields"` - ResourceActions map[string]Action `json:"resourceActions,omitempty"` - CollectionMethods []string `json:"collectionMethods,omitempty"` - CollectionFields map[string]Field `json:"collectionFields,omitempty"` - CollectionActions map[string]Action `json:"collectionActions,omitempty"` - CollectionFilters map[string]Filter `json:"collectionFilters,omitempty"` - Scope TypeScope `json:"-"` - - InternalSchema *Schema `json:"-"` - Mapper Mapper `json:"-"` - ActionHandler ActionHandler `json:"-"` - LinkHandler RequestHandler `json:"-"` - ListHandler RequestHandler `json:"-"` - CreateHandler RequestHandler `json:"-"` - DeleteHandler RequestHandler `json:"-"` - UpdateHandler RequestHandler `json:"-"` - InputFormatter InputFormatter `json:"-"` - Formatter Formatter `json:"-"` - CollectionFormatter CollectionFormatter `json:"-"` - ErrorHandler ErrorHandler `json:"-"` - Validator Validator `json:"-"` - Store Store `json:"-"` -} - -type Field struct { - Type string `json:"type,omitempty"` - Default interface{} `json:"default,omitempty"` - Nullable bool `json:"nullable,omitempty"` - Create bool `json:"create"` - WriteOnly bool `json:"writeOnly,omitempty"` - Required bool `json:"required,omitempty"` - Update bool `json:"update"` - MinLength *int64 `json:"minLength,omitempty"` - MaxLength *int64 `json:"maxLength,omitempty"` - Min *int64 `json:"min,omitempty"` - Max *int64 `json:"max,omitempty"` - Options []string `json:"options,omitempty"` - ValidChars string `json:"validChars,omitempty"` - InvalidChars string `json:"invalidChars,omitempty"` - Description string `json:"description,omitempty"` - CodeName string `json:"-"` - DynamicField bool `json:"dynamicField,omitempty"` -} - -type Action struct { - Input string `json:"input,omitempty"` - Output string `json:"output,omitempty"` -} - -type Filter struct { - Modifiers []ModifierType `json:"modifiers,omitempty"` -} - -type ListOpts struct { - Filters map[string]interface{} -} - -func (c *Collection) AddAction(apiContext *APIContext, name string) { - c.Actions[name] = apiContext.URLBuilder.CollectionAction(apiContext.Schema, nil, name) -} diff --git a/vendor/github.com/rancher/norman/types/values/values.go b/vendor/github.com/rancher/norman/types/values/values.go deleted file mode 100644 index 0ec044578b..0000000000 --- a/vendor/github.com/rancher/norman/types/values/values.go +++ /dev/null @@ -1,111 +0,0 @@ -package values - -import "github.com/rancher/norman/types/convert" - -func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) { - for i, key := range keys { - if i == len(keys)-1 { - val, ok := data[key] - delete(data, key) - return val, ok - } - data, _ = data[key].(map[string]interface{}) - } - - return nil, false -} - -func GetStringSlice(data map[string]interface{}, keys ...string) ([]string, bool) { - val, ok := GetValue(data, keys...) - if !ok { - return nil, ok - } - - slice, typeOk := val.([]string) - if typeOk { - return slice, typeOk - } - - sliceNext, typeOk := val.([]interface{}) - if !typeOk { - return nil, typeOk - } - - var result []string - for _, item := range sliceNext { - result = append(result, convert.ToString(item)) - } - - return result, true -} - -func GetSlice(data map[string]interface{}, keys ...string) ([]map[string]interface{}, bool) { - val, ok := GetValue(data, keys...) - if !ok { - return nil, ok - } - - slice, typeOk := val.([]map[string]interface{}) - if typeOk { - return slice, typeOk - } - - sliceNext, typeOk := val.([]interface{}) - if !typeOk { - return nil, typeOk - } - - result := []map[string]interface{}{} - for _, val := range sliceNext { - if v, ok := val.(map[string]interface{}); ok { - result = append(result, v) - } - } - - return result, true - -} - -func GetValueN(data map[string]interface{}, keys ...string) interface{} { - val, _ := GetValue(data, keys...) - return val -} - -func GetValue(data map[string]interface{}, keys ...string) (interface{}, bool) { - for i, key := range keys { - if i == len(keys)-1 { - val, ok := data[key] - return val, ok - } - data, _ = data[key].(map[string]interface{}) - } - - return nil, false -} - -func PutValue(data map[string]interface{}, val interface{}, keys ...string) { - if data == nil { - return - } - - // This is so ugly - for i, key := range keys { - if i == len(keys)-1 { - data[key] = val - } else { - newData, ok := data[key] - if ok { - newMap, ok := newData.(map[string]interface{}) - if ok { - data = newMap - } else { - return - } - } else { - newMap := map[string]interface{}{} - data[key] = newMap - data = newMap - } - } - } -} diff --git a/vendor/github.com/rancher/norman/urlbuilder/url.go b/vendor/github.com/rancher/norman/urlbuilder/url.go deleted file mode 100644 index 8b1652f0d7..0000000000 --- a/vendor/github.com/rancher/norman/urlbuilder/url.go +++ /dev/null @@ -1,273 +0,0 @@ -package urlbuilder - -import ( - "bytes" - "fmt" - "net/http" - "net/url" - "strings" - - "github.com/rancher/norman/name" - "github.com/rancher/norman/types" -) - -const ( - PrefixHeader = "X-API-URL-Prefix" - ForwardedHostHeader = "X-Forwarded-Host" - ForwardedProtoHeader = "X-Forwarded-Proto" - ForwardedPortHeader = "X-Forwarded-Port" -) - -func New(r *http.Request, version types.APIVersion, schemas *types.Schemas) (types.URLBuilder, error) { - requestURL := parseRequestURL(r) - responseURLBase, err := parseResponseURLBase(requestURL, r) - if err != nil { - return nil, err - } - - builder := &urlBuilder{ - schemas: schemas, - requestURL: requestURL, - responseURLBase: responseURLBase, - apiVersion: version, - query: r.URL.Query(), - } - - return builder, nil -} - -type urlBuilder struct { - schemas *types.Schemas - requestURL string - responseURLBase string - apiVersion types.APIVersion - subContext string - query url.Values -} - -func (u *urlBuilder) SetSubContext(subContext string) { - u.subContext = subContext -} - -func (u *urlBuilder) SchemaLink(schema *types.Schema) string { - return u.constructBasicURL(schema.Version, "schemas", schema.ID) -} - -func (u *urlBuilder) Link(linkName string, resource *types.RawResource) string { - if resource.ID == "" || linkName == "" { - return "" - } - - if self, ok := resource.Links["self"]; ok { - return self + "/" + strings.ToLower(linkName) - } - - return u.constructBasicURL(resource.Schema.Version, resource.Schema.PluralName, resource.ID, strings.ToLower(linkName)) -} - -func (u *urlBuilder) ResourceLink(resource *types.RawResource) string { - if resource.ID == "" { - return "" - } - - return u.constructBasicURL(resource.Schema.Version, resource.Schema.PluralName, resource.ID) -} - -func (u *urlBuilder) Marker(marker string) string { - newValues := url.Values{} - for k, v := range u.query { - newValues[k] = v - } - newValues.Set("marker", marker) - return u.requestURL + "?" + newValues.Encode() -} - -func (u *urlBuilder) ReverseSort(order types.SortOrder) string { - newValues := url.Values{} - for k, v := range u.query { - newValues[k] = v - } - newValues.Del("order") - newValues.Del("marker") - if order == types.ASC { - newValues.Add("order", string(types.DESC)) - } else { - newValues.Add("order", string(types.ASC)) - } - - return u.requestURL + "?" + newValues.Encode() -} - -func (u *urlBuilder) Current() string { - return u.requestURL -} - -func (u *urlBuilder) RelativeToRoot(path string) string { - return u.responseURLBase + path -} - -func (u *urlBuilder) Sort(field string) string { - newValues := url.Values{} - for k, v := range u.query { - newValues[k] = v - } - newValues.Del("order") - newValues.Del("marker") - newValues.Set("sort", field) - return u.requestURL + "?" + newValues.Encode() -} - -func (u *urlBuilder) Collection(schema *types.Schema, versionOverride *types.APIVersion) string { - plural := u.getPluralName(schema) - if versionOverride == nil { - return u.constructBasicURL(schema.Version, plural) - } - return u.constructBasicURL(*versionOverride, plural) -} - -func (u *urlBuilder) SubContextCollection(subContext *types.Schema, contextName string, schema *types.Schema) string { - return u.constructBasicURL(subContext.Version, subContext.PluralName, contextName, u.getPluralName(schema)) -} - -func (u *urlBuilder) Version(version types.APIVersion) string { - return u.constructBasicURL(version) -} - -func (u *urlBuilder) FilterLink(schema *types.Schema, fieldName string, value string) string { - return u.constructBasicURL(schema.Version, schema.PluralName) + "?" + - url.QueryEscape(fieldName) + "=" + url.QueryEscape(value) -} - -func (u *urlBuilder) ResourceLinkByID(schema *types.Schema, id string) string { - return u.constructBasicURL(schema.Version, schema.PluralName, id) -} - -func (u *urlBuilder) constructBasicURL(version types.APIVersion, parts ...string) string { - buffer := bytes.Buffer{} - - buffer.WriteString(u.responseURLBase) - if version.Path == "" { - buffer.WriteString(u.apiVersion.Path) - } else { - buffer.WriteString(version.Path) - } - buffer.WriteString(u.subContext) - - for _, part := range parts { - if part == "" { - return "" - } - buffer.WriteString("/") - buffer.WriteString(part) - } - - return buffer.String() -} - -func (u *urlBuilder) getPluralName(schema *types.Schema) string { - if schema.PluralName == "" { - return strings.ToLower(name.GuessPluralName(schema.ID)) - } - return strings.ToLower(schema.PluralName) -} - -// Constructs the request URL based off of standard headers in the request, falling back to the HttpServletRequest.getRequestURL() -// if the headers aren't available. Here is the ordered list of how we'll attempt to construct the URL: -// - x-forwarded-proto://x-forwarded-host:x-forwarded-port/HttpServletRequest.getRequestURI() -// - x-forwarded-proto://x-forwarded-host/HttpServletRequest.getRequestURI() -// - x-forwarded-proto://host:x-forwarded-port/HttpServletRequest.getRequestURI() -// - x-forwarded-proto://host/HttpServletRequest.getRequestURI() request.getRequestURL() -// -// Additional notes: -// - If the x-forwarded-host/host header has a port and x-forwarded-port has been passed, x-forwarded-port will be used. -func parseRequestURL(r *http.Request) string { - // Get url from standard headers - requestURL := getURLFromStandardHeaders(r) - if requestURL != "" { - return requestURL - } - - // Use incoming url - scheme := "http" - if r.TLS != nil { - scheme = "https" - } - return fmt.Sprintf("%s://%s%s%s", scheme, r.Host, r.Header.Get(PrefixHeader), r.URL.Path) -} - -func getURLFromStandardHeaders(r *http.Request) string { - xForwardedProto := getOverrideHeader(r, ForwardedProtoHeader, "") - if xForwardedProto == "" { - return "" - } - - host := getOverrideHeader(r, ForwardedHostHeader, "") - if host == "" { - host = r.Host - } - - if host == "" { - return "" - } - - port := getOverrideHeader(r, ForwardedPortHeader, "") - if port == "443" || port == "80" { - port = "" // Don't include default ports in url - } - - if port != "" && strings.Contains(host, ":") { - // Have to strip the port that is in the host. Handle IPv6, which has this format: [::1]:8080 - if (strings.HasPrefix(host, "[") && strings.Contains(host, "]:")) || !strings.HasPrefix(host, "[") { - host = host[0:strings.LastIndex(host, ":")] - } - } - - if port != "" { - port = ":" + port - } - - return fmt.Sprintf("%s://%s%s%s%s", xForwardedProto, host, port, r.Header.Get(PrefixHeader), r.URL.Path) -} - -func getOverrideHeader(r *http.Request, header string, defaultValue string) string { - // Need to handle comma separated hosts in X-Forwarded-For - value := r.Header.Get(header) - if value != "" { - return strings.TrimSpace(strings.Split(value, ",")[0]) - } - return defaultValue -} - -func parseResponseURLBase(requestURL string, r *http.Request) (string, error) { - path := r.URL.Path - - index := strings.LastIndex(requestURL, path) - if index == -1 { - // Fallback, if we can't find path in requestURL, then we just assume the base is the root of the web request - u, err := url.Parse(requestURL) - if err != nil { - return "", err - } - - buffer := bytes.Buffer{} - buffer.WriteString(u.Scheme) - buffer.WriteString("://") - buffer.WriteString(u.Host) - return buffer.String(), nil - } - - return requestURL[0:index], nil -} - -func (u *urlBuilder) Action(action string, resource *types.RawResource) string { - return u.constructBasicURL(resource.Schema.Version, resource.Schema.PluralName, resource.ID) + "?action=" + url.QueryEscape(action) -} - -func (u *urlBuilder) CollectionAction(schema *types.Schema, versionOverride *types.APIVersion, action string) string { - collectionURL := u.Collection(schema, versionOverride) - return collectionURL + "?action=" + url.QueryEscape(action) -} - -func (u *urlBuilder) ActionLinkByID(schema *types.Schema, id string, action string) string { - return u.constructBasicURL(schema.Version, schema.PluralName, id) + "?action=" + url.QueryEscape(action) -} diff --git a/vendor/github.com/rancher/norman/vendor.conf b/vendor/github.com/rancher/norman/vendor.conf deleted file mode 100644 index 9286708d1a..0000000000 --- a/vendor/github.com/rancher/norman/vendor.conf +++ /dev/null @@ -1,9 +0,0 @@ -# package -github.com/rancher/norman - -k8s.io/kubernetes v1.12.2-lite1 https://github.com/ibuildthecloud/k3s.git transitive=true,staging=true -github.com/maruel/panicparse c0182c169410cfa80c7e8f046dad208eaef91338 -bitbucket.org/ww/goautoneg a547fc61f48d567d5b4ec6f8aee5573d8efce11d https://github.com/rancher/goautoneg.git -golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5 -github.com/gorilla/mux v1.6.1 -golang.org/x/crypto/acme 505ab145d0a99da450461ae2c1a9f6cd10d1f447 diff --git a/vendor/github.com/rancher/remotedialer/LICENSE b/vendor/github.com/rancher/remotedialer/LICENSE new file mode 100644 index 0000000000..e454a52586 --- /dev/null +++ b/vendor/github.com/rancher/remotedialer/LICENSE @@ -0,0 +1,178 @@ + + 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 + diff --git a/vendor/github.com/rancher/remotedialer/README.md b/vendor/github.com/rancher/remotedialer/README.md new file mode 100644 index 0000000000..d4807587bb --- /dev/null +++ b/vendor/github.com/rancher/remotedialer/README.md @@ -0,0 +1,10 @@ +Reverse Tunneling Dialer +======================== + +Client makes an outbound connection to a server. The server can now do net.Dial from the +server that will actually do a net.Dial on the client and pipe all bytes back and forth. + +Fun times! + +Refer to `server/` and `client/` how to use. Or don't.... This framework can hurt your head +trying to conceptualize. diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/client.go b/vendor/github.com/rancher/remotedialer/client.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/client.go rename to vendor/github.com/rancher/remotedialer/client.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/client_dialer.go b/vendor/github.com/rancher/remotedialer/client_dialer.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/client_dialer.go rename to vendor/github.com/rancher/remotedialer/client_dialer.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/connection.go b/vendor/github.com/rancher/remotedialer/connection.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/connection.go rename to vendor/github.com/rancher/remotedialer/connection.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/dialer.go b/vendor/github.com/rancher/remotedialer/dialer.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/dialer.go rename to vendor/github.com/rancher/remotedialer/dialer.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/message.go b/vendor/github.com/rancher/remotedialer/message.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/message.go rename to vendor/github.com/rancher/remotedialer/message.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/peer.go b/vendor/github.com/rancher/remotedialer/peer.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/peer.go rename to vendor/github.com/rancher/remotedialer/peer.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/server.go b/vendor/github.com/rancher/remotedialer/server.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/server.go rename to vendor/github.com/rancher/remotedialer/server.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/session.go b/vendor/github.com/rancher/remotedialer/session.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/session.go rename to vendor/github.com/rancher/remotedialer/session.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/session_manager.go b/vendor/github.com/rancher/remotedialer/session_manager.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/session_manager.go rename to vendor/github.com/rancher/remotedialer/session_manager.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/session_windows.go b/vendor/github.com/rancher/remotedialer/session_windows.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/session_windows.go rename to vendor/github.com/rancher/remotedialer/session_windows.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/types.go b/vendor/github.com/rancher/remotedialer/types.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/types.go rename to vendor/github.com/rancher/remotedialer/types.go diff --git a/vendor/github.com/rancher/norman/pkg/remotedialer/wsconn.go b/vendor/github.com/rancher/remotedialer/wsconn.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/remotedialer/wsconn.go rename to vendor/github.com/rancher/remotedialer/wsconn.go diff --git a/vendor/github.com/rancher/wrangler-api/.dockerignore b/vendor/github.com/rancher/wrangler-api/.dockerignore new file mode 100644 index 0000000000..bec10c10c9 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/.dockerignore @@ -0,0 +1,3 @@ +./.dapper +./.cache +./dist diff --git a/vendor/github.com/rancher/wrangler-api/.drone.yml b/vendor/github.com/rancher/wrangler-api/.drone.yml new file mode 100644 index 0000000000..88f6445c7f --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/.drone.yml @@ -0,0 +1,221 @@ +--- +kind: pipeline +name: amd64 + +platform: + os: linux + arch: amd64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-amd64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/wrangler-api" + tag: "${DRONE_TAG}-amd64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm64 + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-arm64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/wrangler-api" + tag: "${DRONE_TAG}-arm64" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: arm + +platform: + os: linux + arch: arm + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-arm.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +- name: docker-publish + image: plugins/docker + settings: + dockerfile: package/Dockerfile + password: + from_secret: docker_password + repo: "rancher/wrangler-api" + tag: "${DRONE_TAG}-arm" + username: + from_secret: docker_username + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: manifest + +platform: + os: linux + arch: amd64 + +steps: +- name: manifest + image: plugins/manifest:1.0.2 + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + platforms: + - linux/amd64 + - linux/arm64 + - linux/arm + target: "rancher/wrangler-api:${DRONE_TAG}" + template: "rancher/wrangler-api:${DRONE_TAG}-ARCH" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +depends_on: +- amd64 +- arm64 +- arm diff --git a/vendor/github.com/rancher/wrangler-api/.gitignore b/vendor/github.com/rancher/wrangler-api/.gitignore new file mode 100644 index 0000000000..4d32884980 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/.gitignore @@ -0,0 +1,6 @@ +/.dapper +/.cache +/bin +/dist +*.swp +.idea diff --git a/vendor/github.com/rancher/wrangler-api/.golangci.json b/vendor/github.com/rancher/wrangler-api/.golangci.json new file mode 100644 index 0000000000..f317e3171c --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/.golangci.json @@ -0,0 +1,19 @@ +{ + "linters": { + "disable-all": true, + "enable": [ + "govet", + "golint", + "goimports", + "misspell", + "ineffassign", + "gofmt" + ] + }, + "run": { + "skip-files": [ + "/zz_generated_" + ], + "deadline": "5m" + } +} diff --git a/vendor/github.com/rancher/wrangler-api/Dockerfile.dapper b/vendor/github.com/rancher/wrangler-api/Dockerfile.dapper new file mode 100644 index 0000000000..a3ca5c5371 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/Dockerfile.dapper @@ -0,0 +1,28 @@ +FROM golang:1.12.1-alpine3.9 + +ARG DAPPER_HOST_ARCH +ENV ARCH $DAPPER_HOST_ARCH + +RUN apk -U add bash git gcc musl-dev docker vim less file curl wget ca-certificates +RUN go get -d golang.org/x/lint/golint && \ + git -C /go/src/golang.org/x/lint/golint checkout -b current 06c8688daad7faa9da5a0c2f163a3d14aac986ca && \ + go install golang.org/x/lint/golint && \ + rm -rf /go/src /go/pkg +RUN mkdir -p /go/src/golang.org/x && \ + cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \ + git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \ + go install golang.org/x/tools/cmd/goimports +RUN rm -rf /go/src /go/pkg +RUN if [ "${ARCH}" == "amd64" ]; then \ + curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ + fi + +ENV DAPPER_ENV REPO TAG DRONE_TAG +ENV DAPPER_SOURCE /go/src/github.com/rancher/wrangler-api/ +ENV DAPPER_OUTPUT ./bin ./dist +ENV DAPPER_DOCKER_SOCKET true +ENV HOME ${DAPPER_SOURCE} +WORKDIR ${DAPPER_SOURCE} + +ENTRYPOINT ["./scripts/entry"] +CMD ["ci"] diff --git a/vendor/github.com/rancher/wrangler-api/LICENSE b/vendor/github.com/rancher/wrangler-api/LICENSE new file mode 100644 index 0000000000..f433b1a53f --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/LICENSE @@ -0,0 +1,177 @@ + + 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 diff --git a/vendor/github.com/rancher/norman/Makefile b/vendor/github.com/rancher/wrangler-api/Makefile similarity index 92% rename from vendor/github.com/rancher/norman/Makefile rename to vendor/github.com/rancher/wrangler-api/Makefile index 78839b9be5..a0649db7a3 100644 --- a/vendor/github.com/rancher/norman/Makefile +++ b/vendor/github.com/rancher/wrangler-api/Makefile @@ -10,6 +10,6 @@ TARGETS := $(shell ls scripts) $(TARGETS): .dapper ./.dapper $@ -.DEFAULT_GOAL := ci +.DEFAULT_GOAL := default .PHONY: $(TARGETS) diff --git a/vendor/github.com/rancher/norman/README.md b/vendor/github.com/rancher/wrangler-api/README.md similarity index 65% rename from vendor/github.com/rancher/norman/README.md rename to vendor/github.com/rancher/wrangler-api/README.md index 3ab28f91e6..4b2b336710 100644 --- a/vendor/github.com/rancher/norman/README.md +++ b/vendor/github.com/rancher/wrangler-api/README.md @@ -1,14 +1,15 @@ -Norman +wrangler-api ======== -An API framework for Building [Rancher Style APIs](https://github.com/rancher/api-spec/) backed by K8s CustomResources and their controllers. +This repo holds generated wrangler controller for third party projects, namely +core Kubernetes. -## Example +## Building -Refer to https://github.com/rancher/go-skel for skeleton norman controller projects +`go generate` ## License -Copyright (c) 2014-2017 [Rancher Labs, Inc.](http://rancher.com) +Copyright (c) 2019 [Rancher Labs, Inc.](http://rancher.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/rancher/wrangler-api/go.mod b/vendor/github.com/rancher/wrangler-api/go.mod new file mode 100644 index 0000000000..eb48016625 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/go.mod @@ -0,0 +1,22 @@ +module github.com/rancher/wrangler-api + +go 1.12 + +replace ( + github.com/knative/pkg => github.com/rancher/pkg v0.0.0-20190514055449-b30ab9de040e + github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 +) + +require ( + github.com/google/go-cmp v0.3.0 // indirect + github.com/jetstack/cert-manager v0.7.2 + github.com/knative/build v0.6.0 + github.com/knative/pkg v0.0.0-20190514205332-5e4512dcb2ca + github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a // indirect + github.com/rancher/wrangler v0.1.3 + github.com/sirupsen/logrus v1.4.1 + k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b + k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 + k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d + k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible +) diff --git a/vendor/github.com/rancher/wrangler-api/go.sum b/vendor/github.com/rancher/wrangler-api/go.sum new file mode 100644 index 0000000000..16d2c71341 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/go.sum @@ -0,0 +1,173 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jetstack/cert-manager v0.7.2 h1:NroJN9tEuW3CCwkKqRfHs8hCCsVvFl1InCKwI/Obd9k= +github.com/jetstack/cert-manager v0.7.2/go.mod h1:nbddmhjWxYGt04bxvwVGUSeLhZ2PCyNvd7MpXdq+yWY= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knative/build v0.6.0 h1:tAhqGbRL3/wFOfEc4srO8XDNV8DxUE+z6TzKW0JPWsE= +github.com/knative/build v0.6.0/go.mod h1:/sU74ZQkwlYA5FwYDJhYTy61i/Kn+5eWfln2jDbw3Qo= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a h1:+J2gw7Bw77w/fbK7wnNJJDKmw1IbWft2Ul5BzrG1Qm8= +github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c h1:Hww8mOyEKTeON4bZn7FrlLismspbPc1teNRUVH7wLQ8= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c h1:eSfnfIuwhxZyULg1NNuZycJcYkjYVGYe7FczwQReM6U= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 h1:Xsxh7fX3+2wAUJtPy8g2lZh0cYuyifqhBL0vxCIYojs= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U= +github.com/rancher/pkg v0.0.0-20190514055449-b30ab9de040e h1:j6+HqCET/NLPBtew2m5apL7jWw/PStQ7iGwXjgAqdvo= +github.com/rancher/pkg v0.0.0-20190514055449-b30ab9de040e/go.mod h1:XbYHTPaXuw8ZY9bylhYKQh/nJxDaTKk3YhAxPl4Qy/k= +github.com/rancher/wrangler v0.0.0-20190516065845-c1b3a51a1fac h1:7cLgBAOmh8FQSajbJ2hVIJ22U4lQiHMhFa2f4AN1+nc= +github.com/rancher/wrangler v0.0.0-20190516065845-c1b3a51a1fac/go.mod h1:HM0BuhAugqM5cGtQn2hrMwpbExuLQe7NCUTD+crAxV0= +github.com/rancher/wrangler v0.0.0-20190516181950-a7cf48fa83ef h1:7oP1PQw+BXenm/UqZXPPdZiNvRjnYmzO3JSb4TJd6zU= +github.com/rancher/wrangler v0.0.0-20190516181950-a7cf48fa83ef/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.1 h1:Xz0i5RtpWaqV/83xisxESOBIjf3JnsPExukR+3fiD8M= +github.com/rancher/wrangler v0.1.1/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.2 h1:+oehkcBDInF6dcnG1ZWczL/tV/c7J8ILP3qEFCme7lw= +github.com/rancher/wrangler v0.1.2/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler v0.1.3 h1:WVMLj7kxTOx2pQyAnUKbbFhuFqhAuzkrsSvk37VaYwY= +github.com/rancher/wrangler v0.1.3/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff h1:VARhShG49tiji6mdRNp7JTNDtJ0FhuprF93GBQ37xGU= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 h1:q1Qvjzs/iEdXF6A1a8H3AKVFDzJNcJn3nXMs6R6qFtA= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70 h1:lgPp615xLHxN84RBd+viA/oHzJfI0miFYFH4T9wpPQ4= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d h1:QY1FeareEgkYrWnF2D2XxZFlF0k5Ir4uE8YjD1kHi94= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d/go.mod h1:rVrFWfTVftGH7bb972nWC6N4QkJ4LU7FOXu8GH2UkJo= +k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a h1:QoHVuRquf80YZ+/bovwxoMO3Q/A3nt3yTgS0/0nejuk= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 h1:IrnrEIp9du1SngrzGC1fdYEdos7Il6I6EVxwFQHJwCg= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/factory.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/factory.go new file mode 100644 index 0000000000..5d7fe91b1a --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package apps + +import ( + "context" + "time" + + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + informers "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) Apps() Interface { + return New(c.controllerManager, c.informerFactory.Apps(), c.clientset) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/interface.go new file mode 100644 index 0000000000..40179e4c76 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package apps + +import ( + v1 "github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1" + "github.com/rancher/wrangler/pkg/generic" + informers "k8s.io/client-go/informers/apps" + clientset "k8s.io/client-go/kubernetes" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.AppsV1(), g.informers.V1()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/daemonset.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/daemonset.go new file mode 100644 index 0000000000..2507da0e11 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/daemonset.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/apps/v1" + clientset "k8s.io/client-go/kubernetes/typed/apps/v1" + listers "k8s.io/client-go/listers/apps/v1" + "k8s.io/client-go/tools/cache" +) + +type DaemonSetHandler func(string, *v1.DaemonSet) (*v1.DaemonSet, error) + +type DaemonSetController interface { + DaemonSetClient + + OnChange(ctx context.Context, name string, sync DaemonSetHandler) + OnRemove(ctx context.Context, name string, sync DaemonSetHandler) + Enqueue(namespace, name string) + + Cache() DaemonSetCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type DaemonSetClient interface { + Create(*v1.DaemonSet) (*v1.DaemonSet, error) + Update(*v1.DaemonSet) (*v1.DaemonSet, error) + UpdateStatus(*v1.DaemonSet) (*v1.DaemonSet, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.DaemonSet, error) + List(namespace string, opts metav1.ListOptions) (*v1.DaemonSetList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.DaemonSet, err error) +} + +type DaemonSetCache interface { + Get(namespace, name string) (*v1.DaemonSet, error) + List(namespace string, selector labels.Selector) ([]*v1.DaemonSet, error) + + AddIndexer(indexName string, indexer DaemonSetIndexer) + GetByIndex(indexName, key string) ([]*v1.DaemonSet, error) +} + +type DaemonSetIndexer func(obj *v1.DaemonSet) ([]string, error) + +type daemonSetController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.DaemonSetsGetter + informer informers.DaemonSetInformer + gvk schema.GroupVersionKind +} + +func NewDaemonSetController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.DaemonSetsGetter, informer informers.DaemonSetInformer) DaemonSetController { + return &daemonSetController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromDaemonSetHandlerToHandler(sync DaemonSetHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.DaemonSet + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.DaemonSet)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *daemonSetController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.DaemonSet)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateDaemonSetOnChange(updater generic.Updater, handler DaemonSetHandler) DaemonSetHandler { + return func(key string, obj *v1.DaemonSet) (*v1.DaemonSet, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.DaemonSet) + } + } + + return copyObj, err + } +} + +func (c *daemonSetController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *daemonSetController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *daemonSetController) OnChange(ctx context.Context, name string, sync DaemonSetHandler) { + c.AddGenericHandler(ctx, name, FromDaemonSetHandlerToHandler(sync)) +} + +func (c *daemonSetController) OnRemove(ctx context.Context, name string, sync DaemonSetHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromDaemonSetHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *daemonSetController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *daemonSetController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *daemonSetController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *daemonSetController) Cache() DaemonSetCache { + return &daemonSetCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *daemonSetController) Create(obj *v1.DaemonSet) (*v1.DaemonSet, error) { + return c.clientGetter.DaemonSets(obj.Namespace).Create(obj) +} + +func (c *daemonSetController) Update(obj *v1.DaemonSet) (*v1.DaemonSet, error) { + return c.clientGetter.DaemonSets(obj.Namespace).Update(obj) +} + +func (c *daemonSetController) UpdateStatus(obj *v1.DaemonSet) (*v1.DaemonSet, error) { + return c.clientGetter.DaemonSets(obj.Namespace).UpdateStatus(obj) +} + +func (c *daemonSetController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.DaemonSets(namespace).Delete(name, options) +} + +func (c *daemonSetController) Get(namespace, name string, options metav1.GetOptions) (*v1.DaemonSet, error) { + return c.clientGetter.DaemonSets(namespace).Get(name, options) +} + +func (c *daemonSetController) List(namespace string, opts metav1.ListOptions) (*v1.DaemonSetList, error) { + return c.clientGetter.DaemonSets(namespace).List(opts) +} + +func (c *daemonSetController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.DaemonSets(namespace).Watch(opts) +} + +func (c *daemonSetController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.DaemonSet, err error) { + return c.clientGetter.DaemonSets(namespace).Patch(name, pt, data, subresources...) +} + +type daemonSetCache struct { + lister listers.DaemonSetLister + indexer cache.Indexer +} + +func (c *daemonSetCache) Get(namespace, name string) (*v1.DaemonSet, error) { + return c.lister.DaemonSets(namespace).Get(name) +} + +func (c *daemonSetCache) List(namespace string, selector labels.Selector) ([]*v1.DaemonSet, error) { + return c.lister.DaemonSets(namespace).List(selector) +} + +func (c *daemonSetCache) AddIndexer(indexName string, indexer DaemonSetIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.DaemonSet)) + }, + })) +} + +func (c *daemonSetCache) GetByIndex(indexName, key string) (result []*v1.DaemonSet, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.DaemonSet)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/deployment.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/deployment.go new file mode 100644 index 0000000000..41651a95c6 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/deployment.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/apps/v1" + clientset "k8s.io/client-go/kubernetes/typed/apps/v1" + listers "k8s.io/client-go/listers/apps/v1" + "k8s.io/client-go/tools/cache" +) + +type DeploymentHandler func(string, *v1.Deployment) (*v1.Deployment, error) + +type DeploymentController interface { + DeploymentClient + + OnChange(ctx context.Context, name string, sync DeploymentHandler) + OnRemove(ctx context.Context, name string, sync DeploymentHandler) + Enqueue(namespace, name string) + + Cache() DeploymentCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type DeploymentClient interface { + Create(*v1.Deployment) (*v1.Deployment, error) + Update(*v1.Deployment) (*v1.Deployment, error) + UpdateStatus(*v1.Deployment) (*v1.Deployment, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Deployment, error) + List(namespace string, opts metav1.ListOptions) (*v1.DeploymentList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Deployment, err error) +} + +type DeploymentCache interface { + Get(namespace, name string) (*v1.Deployment, error) + List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) + + AddIndexer(indexName string, indexer DeploymentIndexer) + GetByIndex(indexName, key string) ([]*v1.Deployment, error) +} + +type DeploymentIndexer func(obj *v1.Deployment) ([]string, error) + +type deploymentController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.DeploymentsGetter + informer informers.DeploymentInformer + gvk schema.GroupVersionKind +} + +func NewDeploymentController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.DeploymentsGetter, informer informers.DeploymentInformer) DeploymentController { + return &deploymentController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromDeploymentHandlerToHandler(sync DeploymentHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Deployment + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Deployment)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *deploymentController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Deployment)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateDeploymentOnChange(updater generic.Updater, handler DeploymentHandler) DeploymentHandler { + return func(key string, obj *v1.Deployment) (*v1.Deployment, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Deployment) + } + } + + return copyObj, err + } +} + +func (c *deploymentController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *deploymentController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *deploymentController) OnChange(ctx context.Context, name string, sync DeploymentHandler) { + c.AddGenericHandler(ctx, name, FromDeploymentHandlerToHandler(sync)) +} + +func (c *deploymentController) OnRemove(ctx context.Context, name string, sync DeploymentHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromDeploymentHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *deploymentController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *deploymentController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *deploymentController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *deploymentController) Cache() DeploymentCache { + return &deploymentCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *deploymentController) Create(obj *v1.Deployment) (*v1.Deployment, error) { + return c.clientGetter.Deployments(obj.Namespace).Create(obj) +} + +func (c *deploymentController) Update(obj *v1.Deployment) (*v1.Deployment, error) { + return c.clientGetter.Deployments(obj.Namespace).Update(obj) +} + +func (c *deploymentController) UpdateStatus(obj *v1.Deployment) (*v1.Deployment, error) { + return c.clientGetter.Deployments(obj.Namespace).UpdateStatus(obj) +} + +func (c *deploymentController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Deployments(namespace).Delete(name, options) +} + +func (c *deploymentController) Get(namespace, name string, options metav1.GetOptions) (*v1.Deployment, error) { + return c.clientGetter.Deployments(namespace).Get(name, options) +} + +func (c *deploymentController) List(namespace string, opts metav1.ListOptions) (*v1.DeploymentList, error) { + return c.clientGetter.Deployments(namespace).List(opts) +} + +func (c *deploymentController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Deployments(namespace).Watch(opts) +} + +func (c *deploymentController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Deployment, err error) { + return c.clientGetter.Deployments(namespace).Patch(name, pt, data, subresources...) +} + +type deploymentCache struct { + lister listers.DeploymentLister + indexer cache.Indexer +} + +func (c *deploymentCache) Get(namespace, name string) (*v1.Deployment, error) { + return c.lister.Deployments(namespace).Get(name) +} + +func (c *deploymentCache) List(namespace string, selector labels.Selector) ([]*v1.Deployment, error) { + return c.lister.Deployments(namespace).List(selector) +} + +func (c *deploymentCache) AddIndexer(indexName string, indexer DeploymentIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Deployment)) + }, + })) +} + +func (c *deploymentCache) GetByIndex(indexName, key string) (result []*v1.Deployment, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Deployment)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/interface.go new file mode 100644 index 0000000000..0ad9947473 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1/interface.go @@ -0,0 +1,53 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/apps/v1" + informers "k8s.io/client-go/informers/apps/v1" + clientset "k8s.io/client-go/kubernetes/typed/apps/v1" +) + +type Interface interface { + DaemonSet() DaemonSetController + Deployment() DeploymentController +} + +func New(controllerManager *generic.ControllerManager, client clientset.AppsV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.AppsV1Interface +} + +func (c *version) DaemonSet() DaemonSetController { + return NewDaemonSetController(v1.SchemeGroupVersion.WithKind("DaemonSet"), c.controllerManager, c.client, c.informers.DaemonSets()) +} +func (c *version) Deployment() DeploymentController { + return NewDeploymentController(v1.SchemeGroupVersion.WithKind("Deployment"), c.controllerManager, c.client, c.informers.Deployments()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/factory.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/factory.go new file mode 100644 index 0000000000..eb1e229603 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package batch + +import ( + "context" + "time" + + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + informers "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) Batch() Interface { + return New(c.controllerManager, c.informerFactory.Batch(), c.clientset) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/interface.go new file mode 100644 index 0000000000..77da90250d --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package batch + +import ( + v1 "github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1" + "github.com/rancher/wrangler/pkg/generic" + informers "k8s.io/client-go/informers/batch" + clientset "k8s.io/client-go/kubernetes" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.BatchV1(), g.informers.V1()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/interface.go new file mode 100644 index 0000000000..27edcfb5de --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/interface.go @@ -0,0 +1,49 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/batch/v1" + informers "k8s.io/client-go/informers/batch/v1" + clientset "k8s.io/client-go/kubernetes/typed/batch/v1" +) + +type Interface interface { + Job() JobController +} + +func New(controllerManager *generic.ControllerManager, client clientset.BatchV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.BatchV1Interface +} + +func (c *version) Job() JobController { + return NewJobController(v1.SchemeGroupVersion.WithKind("Job"), c.controllerManager, c.client, c.informers.Jobs()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/job.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/job.go new file mode 100644 index 0000000000..be24a7a528 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/batch/v1/job.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/batch/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/batch/v1" + clientset "k8s.io/client-go/kubernetes/typed/batch/v1" + listers "k8s.io/client-go/listers/batch/v1" + "k8s.io/client-go/tools/cache" +) + +type JobHandler func(string, *v1.Job) (*v1.Job, error) + +type JobController interface { + JobClient + + OnChange(ctx context.Context, name string, sync JobHandler) + OnRemove(ctx context.Context, name string, sync JobHandler) + Enqueue(namespace, name string) + + Cache() JobCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type JobClient interface { + Create(*v1.Job) (*v1.Job, error) + Update(*v1.Job) (*v1.Job, error) + UpdateStatus(*v1.Job) (*v1.Job, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Job, error) + List(namespace string, opts metav1.ListOptions) (*v1.JobList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Job, err error) +} + +type JobCache interface { + Get(namespace, name string) (*v1.Job, error) + List(namespace string, selector labels.Selector) ([]*v1.Job, error) + + AddIndexer(indexName string, indexer JobIndexer) + GetByIndex(indexName, key string) ([]*v1.Job, error) +} + +type JobIndexer func(obj *v1.Job) ([]string, error) + +type jobController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.JobsGetter + informer informers.JobInformer + gvk schema.GroupVersionKind +} + +func NewJobController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.JobsGetter, informer informers.JobInformer) JobController { + return &jobController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromJobHandlerToHandler(sync JobHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Job + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Job)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *jobController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Job)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateJobOnChange(updater generic.Updater, handler JobHandler) JobHandler { + return func(key string, obj *v1.Job) (*v1.Job, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Job) + } + } + + return copyObj, err + } +} + +func (c *jobController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *jobController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *jobController) OnChange(ctx context.Context, name string, sync JobHandler) { + c.AddGenericHandler(ctx, name, FromJobHandlerToHandler(sync)) +} + +func (c *jobController) OnRemove(ctx context.Context, name string, sync JobHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromJobHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *jobController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *jobController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *jobController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *jobController) Cache() JobCache { + return &jobCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *jobController) Create(obj *v1.Job) (*v1.Job, error) { + return c.clientGetter.Jobs(obj.Namespace).Create(obj) +} + +func (c *jobController) Update(obj *v1.Job) (*v1.Job, error) { + return c.clientGetter.Jobs(obj.Namespace).Update(obj) +} + +func (c *jobController) UpdateStatus(obj *v1.Job) (*v1.Job, error) { + return c.clientGetter.Jobs(obj.Namespace).UpdateStatus(obj) +} + +func (c *jobController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Jobs(namespace).Delete(name, options) +} + +func (c *jobController) Get(namespace, name string, options metav1.GetOptions) (*v1.Job, error) { + return c.clientGetter.Jobs(namespace).Get(name, options) +} + +func (c *jobController) List(namespace string, opts metav1.ListOptions) (*v1.JobList, error) { + return c.clientGetter.Jobs(namespace).List(opts) +} + +func (c *jobController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Jobs(namespace).Watch(opts) +} + +func (c *jobController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Job, err error) { + return c.clientGetter.Jobs(namespace).Patch(name, pt, data, subresources...) +} + +type jobCache struct { + lister listers.JobLister + indexer cache.Indexer +} + +func (c *jobCache) Get(namespace, name string) (*v1.Job, error) { + return c.lister.Jobs(namespace).Get(name) +} + +func (c *jobCache) List(namespace string, selector labels.Selector) ([]*v1.Job, error) { + return c.lister.Jobs(namespace).List(selector) +} + +func (c *jobCache) AddIndexer(indexName string, indexer JobIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Job)) + }, + })) +} + +func (c *jobCache) GetByIndex(indexName, key string) (result []*v1.Job, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Job)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/factory.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/factory.go new file mode 100644 index 0000000000..37bdd4ff6f --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package core + +import ( + "context" + "time" + + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + informers "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) Core() Interface { + return New(c.controllerManager, c.informerFactory.Core(), c.clientset) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/interface.go new file mode 100644 index 0000000000..51d1216ed9 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package core + +import ( + v1 "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" + "github.com/rancher/wrangler/pkg/generic" + informers "k8s.io/client-go/informers/core" + clientset "k8s.io/client-go/kubernetes" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.CoreV1(), g.informers.V1()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/configmap.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/configmap.go new file mode 100644 index 0000000000..913530ddb8 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/configmap.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type ConfigMapHandler func(string, *v1.ConfigMap) (*v1.ConfigMap, error) + +type ConfigMapController interface { + ConfigMapClient + + OnChange(ctx context.Context, name string, sync ConfigMapHandler) + OnRemove(ctx context.Context, name string, sync ConfigMapHandler) + Enqueue(namespace, name string) + + Cache() ConfigMapCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ConfigMapClient interface { + Create(*v1.ConfigMap) (*v1.ConfigMap, error) + Update(*v1.ConfigMap) (*v1.ConfigMap, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.ConfigMap, error) + List(namespace string, opts metav1.ListOptions) (*v1.ConfigMapList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConfigMap, err error) +} + +type ConfigMapCache interface { + Get(namespace, name string) (*v1.ConfigMap, error) + List(namespace string, selector labels.Selector) ([]*v1.ConfigMap, error) + + AddIndexer(indexName string, indexer ConfigMapIndexer) + GetByIndex(indexName, key string) ([]*v1.ConfigMap, error) +} + +type ConfigMapIndexer func(obj *v1.ConfigMap) ([]string, error) + +type configMapController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ConfigMapsGetter + informer informers.ConfigMapInformer + gvk schema.GroupVersionKind +} + +func NewConfigMapController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ConfigMapsGetter, informer informers.ConfigMapInformer) ConfigMapController { + return &configMapController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromConfigMapHandlerToHandler(sync ConfigMapHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.ConfigMap + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.ConfigMap)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *configMapController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.ConfigMap)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateConfigMapOnChange(updater generic.Updater, handler ConfigMapHandler) ConfigMapHandler { + return func(key string, obj *v1.ConfigMap) (*v1.ConfigMap, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.ConfigMap) + } + } + + return copyObj, err + } +} + +func (c *configMapController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *configMapController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *configMapController) OnChange(ctx context.Context, name string, sync ConfigMapHandler) { + c.AddGenericHandler(ctx, name, FromConfigMapHandlerToHandler(sync)) +} + +func (c *configMapController) OnRemove(ctx context.Context, name string, sync ConfigMapHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromConfigMapHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *configMapController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *configMapController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *configMapController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *configMapController) Cache() ConfigMapCache { + return &configMapCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *configMapController) Create(obj *v1.ConfigMap) (*v1.ConfigMap, error) { + return c.clientGetter.ConfigMaps(obj.Namespace).Create(obj) +} + +func (c *configMapController) Update(obj *v1.ConfigMap) (*v1.ConfigMap, error) { + return c.clientGetter.ConfigMaps(obj.Namespace).Update(obj) +} + +func (c *configMapController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.ConfigMaps(namespace).Delete(name, options) +} + +func (c *configMapController) Get(namespace, name string, options metav1.GetOptions) (*v1.ConfigMap, error) { + return c.clientGetter.ConfigMaps(namespace).Get(name, options) +} + +func (c *configMapController) List(namespace string, opts metav1.ListOptions) (*v1.ConfigMapList, error) { + return c.clientGetter.ConfigMaps(namespace).List(opts) +} + +func (c *configMapController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.ConfigMaps(namespace).Watch(opts) +} + +func (c *configMapController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConfigMap, err error) { + return c.clientGetter.ConfigMaps(namespace).Patch(name, pt, data, subresources...) +} + +type configMapCache struct { + lister listers.ConfigMapLister + indexer cache.Indexer +} + +func (c *configMapCache) Get(namespace, name string) (*v1.ConfigMap, error) { + return c.lister.ConfigMaps(namespace).Get(name) +} + +func (c *configMapCache) List(namespace string, selector labels.Selector) ([]*v1.ConfigMap, error) { + return c.lister.ConfigMaps(namespace).List(selector) +} + +func (c *configMapCache) AddIndexer(indexName string, indexer ConfigMapIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.ConfigMap)) + }, + })) +} + +func (c *configMapCache) GetByIndex(indexName, key string) (result []*v1.ConfigMap, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.ConfigMap)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/endpoints.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/endpoints.go new file mode 100644 index 0000000000..49f5eb0d8b --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/endpoints.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type EndpointsHandler func(string, *v1.Endpoints) (*v1.Endpoints, error) + +type EndpointsController interface { + EndpointsClient + + OnChange(ctx context.Context, name string, sync EndpointsHandler) + OnRemove(ctx context.Context, name string, sync EndpointsHandler) + Enqueue(namespace, name string) + + Cache() EndpointsCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type EndpointsClient interface { + Create(*v1.Endpoints) (*v1.Endpoints, error) + Update(*v1.Endpoints) (*v1.Endpoints, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Endpoints, error) + List(namespace string, opts metav1.ListOptions) (*v1.EndpointsList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Endpoints, err error) +} + +type EndpointsCache interface { + Get(namespace, name string) (*v1.Endpoints, error) + List(namespace string, selector labels.Selector) ([]*v1.Endpoints, error) + + AddIndexer(indexName string, indexer EndpointsIndexer) + GetByIndex(indexName, key string) ([]*v1.Endpoints, error) +} + +type EndpointsIndexer func(obj *v1.Endpoints) ([]string, error) + +type endpointsController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.EndpointsGetter + informer informers.EndpointsInformer + gvk schema.GroupVersionKind +} + +func NewEndpointsController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.EndpointsGetter, informer informers.EndpointsInformer) EndpointsController { + return &endpointsController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromEndpointsHandlerToHandler(sync EndpointsHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Endpoints + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Endpoints)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *endpointsController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Endpoints)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateEndpointsOnChange(updater generic.Updater, handler EndpointsHandler) EndpointsHandler { + return func(key string, obj *v1.Endpoints) (*v1.Endpoints, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Endpoints) + } + } + + return copyObj, err + } +} + +func (c *endpointsController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *endpointsController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *endpointsController) OnChange(ctx context.Context, name string, sync EndpointsHandler) { + c.AddGenericHandler(ctx, name, FromEndpointsHandlerToHandler(sync)) +} + +func (c *endpointsController) OnRemove(ctx context.Context, name string, sync EndpointsHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromEndpointsHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *endpointsController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *endpointsController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *endpointsController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *endpointsController) Cache() EndpointsCache { + return &endpointsCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *endpointsController) Create(obj *v1.Endpoints) (*v1.Endpoints, error) { + return c.clientGetter.Endpoints(obj.Namespace).Create(obj) +} + +func (c *endpointsController) Update(obj *v1.Endpoints) (*v1.Endpoints, error) { + return c.clientGetter.Endpoints(obj.Namespace).Update(obj) +} + +func (c *endpointsController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Endpoints(namespace).Delete(name, options) +} + +func (c *endpointsController) Get(namespace, name string, options metav1.GetOptions) (*v1.Endpoints, error) { + return c.clientGetter.Endpoints(namespace).Get(name, options) +} + +func (c *endpointsController) List(namespace string, opts metav1.ListOptions) (*v1.EndpointsList, error) { + return c.clientGetter.Endpoints(namespace).List(opts) +} + +func (c *endpointsController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Endpoints(namespace).Watch(opts) +} + +func (c *endpointsController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Endpoints, err error) { + return c.clientGetter.Endpoints(namespace).Patch(name, pt, data, subresources...) +} + +type endpointsCache struct { + lister listers.EndpointsLister + indexer cache.Indexer +} + +func (c *endpointsCache) Get(namespace, name string) (*v1.Endpoints, error) { + return c.lister.Endpoints(namespace).Get(name) +} + +func (c *endpointsCache) List(namespace string, selector labels.Selector) ([]*v1.Endpoints, error) { + return c.lister.Endpoints(namespace).List(selector) +} + +func (c *endpointsCache) AddIndexer(indexName string, indexer EndpointsIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Endpoints)) + }, + })) +} + +func (c *endpointsCache) GetByIndex(indexName, key string) (result []*v1.Endpoints, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Endpoints)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/interface.go new file mode 100644 index 0000000000..80d7e53fc3 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/interface.go @@ -0,0 +1,81 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" +) + +type Interface interface { + ConfigMap() ConfigMapController + Endpoints() EndpointsController + Namespace() NamespaceController + Node() NodeController + PersistentVolumeClaim() PersistentVolumeClaimController + Pod() PodController + Secret() SecretController + Service() ServiceController + ServiceAccount() ServiceAccountController +} + +func New(controllerManager *generic.ControllerManager, client clientset.CoreV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.CoreV1Interface +} + +func (c *version) ConfigMap() ConfigMapController { + return NewConfigMapController(v1.SchemeGroupVersion.WithKind("ConfigMap"), c.controllerManager, c.client, c.informers.ConfigMaps()) +} +func (c *version) Endpoints() EndpointsController { + return NewEndpointsController(v1.SchemeGroupVersion.WithKind("Endpoints"), c.controllerManager, c.client, c.informers.Endpoints()) +} +func (c *version) Namespace() NamespaceController { + return NewNamespaceController(v1.SchemeGroupVersion.WithKind("Namespace"), c.controllerManager, c.client, c.informers.Namespaces()) +} +func (c *version) Node() NodeController { + return NewNodeController(v1.SchemeGroupVersion.WithKind("Node"), c.controllerManager, c.client, c.informers.Nodes()) +} +func (c *version) PersistentVolumeClaim() PersistentVolumeClaimController { + return NewPersistentVolumeClaimController(v1.SchemeGroupVersion.WithKind("PersistentVolumeClaim"), c.controllerManager, c.client, c.informers.PersistentVolumeClaims()) +} +func (c *version) Pod() PodController { + return NewPodController(v1.SchemeGroupVersion.WithKind("Pod"), c.controllerManager, c.client, c.informers.Pods()) +} +func (c *version) Secret() SecretController { + return NewSecretController(v1.SchemeGroupVersion.WithKind("Secret"), c.controllerManager, c.client, c.informers.Secrets()) +} +func (c *version) Service() ServiceController { + return NewServiceController(v1.SchemeGroupVersion.WithKind("Service"), c.controllerManager, c.client, c.informers.Services()) +} +func (c *version) ServiceAccount() ServiceAccountController { + return NewServiceAccountController(v1.SchemeGroupVersion.WithKind("ServiceAccount"), c.controllerManager, c.client, c.informers.ServiceAccounts()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/namespace.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/namespace.go new file mode 100644 index 0000000000..4af1e427f9 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/namespace.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type NamespaceHandler func(string, *v1.Namespace) (*v1.Namespace, error) + +type NamespaceController interface { + NamespaceClient + + OnChange(ctx context.Context, name string, sync NamespaceHandler) + OnRemove(ctx context.Context, name string, sync NamespaceHandler) + Enqueue(name string) + + Cache() NamespaceCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type NamespaceClient interface { + Create(*v1.Namespace) (*v1.Namespace, error) + Update(*v1.Namespace) (*v1.Namespace, error) + UpdateStatus(*v1.Namespace) (*v1.Namespace, error) + Delete(name string, options *metav1.DeleteOptions) error + Get(name string, options metav1.GetOptions) (*v1.Namespace, error) + List(opts metav1.ListOptions) (*v1.NamespaceList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Namespace, err error) +} + +type NamespaceCache interface { + Get(name string) (*v1.Namespace, error) + List(selector labels.Selector) ([]*v1.Namespace, error) + + AddIndexer(indexName string, indexer NamespaceIndexer) + GetByIndex(indexName, key string) ([]*v1.Namespace, error) +} + +type NamespaceIndexer func(obj *v1.Namespace) ([]string, error) + +type namespaceController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.NamespacesGetter + informer informers.NamespaceInformer + gvk schema.GroupVersionKind +} + +func NewNamespaceController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.NamespacesGetter, informer informers.NamespaceInformer) NamespaceController { + return &namespaceController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromNamespaceHandlerToHandler(sync NamespaceHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Namespace + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Namespace)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *namespaceController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Namespace)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateNamespaceOnChange(updater generic.Updater, handler NamespaceHandler) NamespaceHandler { + return func(key string, obj *v1.Namespace) (*v1.Namespace, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Namespace) + } + } + + return copyObj, err + } +} + +func (c *namespaceController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *namespaceController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *namespaceController) OnChange(ctx context.Context, name string, sync NamespaceHandler) { + c.AddGenericHandler(ctx, name, FromNamespaceHandlerToHandler(sync)) +} + +func (c *namespaceController) OnRemove(ctx context.Context, name string, sync NamespaceHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromNamespaceHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *namespaceController) Enqueue(name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), "", name) +} + +func (c *namespaceController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *namespaceController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *namespaceController) Cache() NamespaceCache { + return &namespaceCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *namespaceController) Create(obj *v1.Namespace) (*v1.Namespace, error) { + return c.clientGetter.Namespaces().Create(obj) +} + +func (c *namespaceController) Update(obj *v1.Namespace) (*v1.Namespace, error) { + return c.clientGetter.Namespaces().Update(obj) +} + +func (c *namespaceController) UpdateStatus(obj *v1.Namespace) (*v1.Namespace, error) { + return c.clientGetter.Namespaces().UpdateStatus(obj) +} + +func (c *namespaceController) Delete(name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Namespaces().Delete(name, options) +} + +func (c *namespaceController) Get(name string, options metav1.GetOptions) (*v1.Namespace, error) { + return c.clientGetter.Namespaces().Get(name, options) +} + +func (c *namespaceController) List(opts metav1.ListOptions) (*v1.NamespaceList, error) { + return c.clientGetter.Namespaces().List(opts) +} + +func (c *namespaceController) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Namespaces().Watch(opts) +} + +func (c *namespaceController) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Namespace, err error) { + return c.clientGetter.Namespaces().Patch(name, pt, data, subresources...) +} + +type namespaceCache struct { + lister listers.NamespaceLister + indexer cache.Indexer +} + +func (c *namespaceCache) Get(name string) (*v1.Namespace, error) { + return c.lister.Get(name) +} + +func (c *namespaceCache) List(selector labels.Selector) ([]*v1.Namespace, error) { + return c.lister.List(selector) +} + +func (c *namespaceCache) AddIndexer(indexName string, indexer NamespaceIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Namespace)) + }, + })) +} + +func (c *namespaceCache) GetByIndex(indexName, key string) (result []*v1.Namespace, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Namespace)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/node.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/node.go new file mode 100644 index 0000000000..b38f3b4a9d --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/node.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type NodeHandler func(string, *v1.Node) (*v1.Node, error) + +type NodeController interface { + NodeClient + + OnChange(ctx context.Context, name string, sync NodeHandler) + OnRemove(ctx context.Context, name string, sync NodeHandler) + Enqueue(name string) + + Cache() NodeCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type NodeClient interface { + Create(*v1.Node) (*v1.Node, error) + Update(*v1.Node) (*v1.Node, error) + UpdateStatus(*v1.Node) (*v1.Node, error) + Delete(name string, options *metav1.DeleteOptions) error + Get(name string, options metav1.GetOptions) (*v1.Node, error) + List(opts metav1.ListOptions) (*v1.NodeList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Node, err error) +} + +type NodeCache interface { + Get(name string) (*v1.Node, error) + List(selector labels.Selector) ([]*v1.Node, error) + + AddIndexer(indexName string, indexer NodeIndexer) + GetByIndex(indexName, key string) ([]*v1.Node, error) +} + +type NodeIndexer func(obj *v1.Node) ([]string, error) + +type nodeController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.NodesGetter + informer informers.NodeInformer + gvk schema.GroupVersionKind +} + +func NewNodeController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.NodesGetter, informer informers.NodeInformer) NodeController { + return &nodeController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromNodeHandlerToHandler(sync NodeHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Node + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Node)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *nodeController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Node)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateNodeOnChange(updater generic.Updater, handler NodeHandler) NodeHandler { + return func(key string, obj *v1.Node) (*v1.Node, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Node) + } + } + + return copyObj, err + } +} + +func (c *nodeController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *nodeController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *nodeController) OnChange(ctx context.Context, name string, sync NodeHandler) { + c.AddGenericHandler(ctx, name, FromNodeHandlerToHandler(sync)) +} + +func (c *nodeController) OnRemove(ctx context.Context, name string, sync NodeHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromNodeHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *nodeController) Enqueue(name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), "", name) +} + +func (c *nodeController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *nodeController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *nodeController) Cache() NodeCache { + return &nodeCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *nodeController) Create(obj *v1.Node) (*v1.Node, error) { + return c.clientGetter.Nodes().Create(obj) +} + +func (c *nodeController) Update(obj *v1.Node) (*v1.Node, error) { + return c.clientGetter.Nodes().Update(obj) +} + +func (c *nodeController) UpdateStatus(obj *v1.Node) (*v1.Node, error) { + return c.clientGetter.Nodes().UpdateStatus(obj) +} + +func (c *nodeController) Delete(name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Nodes().Delete(name, options) +} + +func (c *nodeController) Get(name string, options metav1.GetOptions) (*v1.Node, error) { + return c.clientGetter.Nodes().Get(name, options) +} + +func (c *nodeController) List(opts metav1.ListOptions) (*v1.NodeList, error) { + return c.clientGetter.Nodes().List(opts) +} + +func (c *nodeController) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Nodes().Watch(opts) +} + +func (c *nodeController) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Node, err error) { + return c.clientGetter.Nodes().Patch(name, pt, data, subresources...) +} + +type nodeCache struct { + lister listers.NodeLister + indexer cache.Indexer +} + +func (c *nodeCache) Get(name string) (*v1.Node, error) { + return c.lister.Get(name) +} + +func (c *nodeCache) List(selector labels.Selector) ([]*v1.Node, error) { + return c.lister.List(selector) +} + +func (c *nodeCache) AddIndexer(indexName string, indexer NodeIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Node)) + }, + })) +} + +func (c *nodeCache) GetByIndex(indexName, key string) (result []*v1.Node, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Node)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/persistentvolumeclaim.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/persistentvolumeclaim.go new file mode 100644 index 0000000000..2ec2f0b2a5 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/persistentvolumeclaim.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type PersistentVolumeClaimHandler func(string, *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) + +type PersistentVolumeClaimController interface { + PersistentVolumeClaimClient + + OnChange(ctx context.Context, name string, sync PersistentVolumeClaimHandler) + OnRemove(ctx context.Context, name string, sync PersistentVolumeClaimHandler) + Enqueue(namespace, name string) + + Cache() PersistentVolumeClaimCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type PersistentVolumeClaimClient interface { + Create(*v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) + Update(*v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) + UpdateStatus(*v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.PersistentVolumeClaim, error) + List(namespace string, opts metav1.ListOptions) (*v1.PersistentVolumeClaimList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.PersistentVolumeClaim, err error) +} + +type PersistentVolumeClaimCache interface { + Get(namespace, name string) (*v1.PersistentVolumeClaim, error) + List(namespace string, selector labels.Selector) ([]*v1.PersistentVolumeClaim, error) + + AddIndexer(indexName string, indexer PersistentVolumeClaimIndexer) + GetByIndex(indexName, key string) ([]*v1.PersistentVolumeClaim, error) +} + +type PersistentVolumeClaimIndexer func(obj *v1.PersistentVolumeClaim) ([]string, error) + +type persistentVolumeClaimController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.PersistentVolumeClaimsGetter + informer informers.PersistentVolumeClaimInformer + gvk schema.GroupVersionKind +} + +func NewPersistentVolumeClaimController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.PersistentVolumeClaimsGetter, informer informers.PersistentVolumeClaimInformer) PersistentVolumeClaimController { + return &persistentVolumeClaimController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromPersistentVolumeClaimHandlerToHandler(sync PersistentVolumeClaimHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.PersistentVolumeClaim + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.PersistentVolumeClaim)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *persistentVolumeClaimController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.PersistentVolumeClaim)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdatePersistentVolumeClaimOnChange(updater generic.Updater, handler PersistentVolumeClaimHandler) PersistentVolumeClaimHandler { + return func(key string, obj *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.PersistentVolumeClaim) + } + } + + return copyObj, err + } +} + +func (c *persistentVolumeClaimController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *persistentVolumeClaimController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *persistentVolumeClaimController) OnChange(ctx context.Context, name string, sync PersistentVolumeClaimHandler) { + c.AddGenericHandler(ctx, name, FromPersistentVolumeClaimHandlerToHandler(sync)) +} + +func (c *persistentVolumeClaimController) OnRemove(ctx context.Context, name string, sync PersistentVolumeClaimHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromPersistentVolumeClaimHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *persistentVolumeClaimController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *persistentVolumeClaimController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *persistentVolumeClaimController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *persistentVolumeClaimController) Cache() PersistentVolumeClaimCache { + return &persistentVolumeClaimCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *persistentVolumeClaimController) Create(obj *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) { + return c.clientGetter.PersistentVolumeClaims(obj.Namespace).Create(obj) +} + +func (c *persistentVolumeClaimController) Update(obj *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) { + return c.clientGetter.PersistentVolumeClaims(obj.Namespace).Update(obj) +} + +func (c *persistentVolumeClaimController) UpdateStatus(obj *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) { + return c.clientGetter.PersistentVolumeClaims(obj.Namespace).UpdateStatus(obj) +} + +func (c *persistentVolumeClaimController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.PersistentVolumeClaims(namespace).Delete(name, options) +} + +func (c *persistentVolumeClaimController) Get(namespace, name string, options metav1.GetOptions) (*v1.PersistentVolumeClaim, error) { + return c.clientGetter.PersistentVolumeClaims(namespace).Get(name, options) +} + +func (c *persistentVolumeClaimController) List(namespace string, opts metav1.ListOptions) (*v1.PersistentVolumeClaimList, error) { + return c.clientGetter.PersistentVolumeClaims(namespace).List(opts) +} + +func (c *persistentVolumeClaimController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.PersistentVolumeClaims(namespace).Watch(opts) +} + +func (c *persistentVolumeClaimController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.PersistentVolumeClaim, err error) { + return c.clientGetter.PersistentVolumeClaims(namespace).Patch(name, pt, data, subresources...) +} + +type persistentVolumeClaimCache struct { + lister listers.PersistentVolumeClaimLister + indexer cache.Indexer +} + +func (c *persistentVolumeClaimCache) Get(namespace, name string) (*v1.PersistentVolumeClaim, error) { + return c.lister.PersistentVolumeClaims(namespace).Get(name) +} + +func (c *persistentVolumeClaimCache) List(namespace string, selector labels.Selector) ([]*v1.PersistentVolumeClaim, error) { + return c.lister.PersistentVolumeClaims(namespace).List(selector) +} + +func (c *persistentVolumeClaimCache) AddIndexer(indexName string, indexer PersistentVolumeClaimIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.PersistentVolumeClaim)) + }, + })) +} + +func (c *persistentVolumeClaimCache) GetByIndex(indexName, key string) (result []*v1.PersistentVolumeClaim, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.PersistentVolumeClaim)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/pod.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/pod.go new file mode 100644 index 0000000000..4b81066196 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/pod.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type PodHandler func(string, *v1.Pod) (*v1.Pod, error) + +type PodController interface { + PodClient + + OnChange(ctx context.Context, name string, sync PodHandler) + OnRemove(ctx context.Context, name string, sync PodHandler) + Enqueue(namespace, name string) + + Cache() PodCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type PodClient interface { + Create(*v1.Pod) (*v1.Pod, error) + Update(*v1.Pod) (*v1.Pod, error) + UpdateStatus(*v1.Pod) (*v1.Pod, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Pod, error) + List(namespace string, opts metav1.ListOptions) (*v1.PodList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Pod, err error) +} + +type PodCache interface { + Get(namespace, name string) (*v1.Pod, error) + List(namespace string, selector labels.Selector) ([]*v1.Pod, error) + + AddIndexer(indexName string, indexer PodIndexer) + GetByIndex(indexName, key string) ([]*v1.Pod, error) +} + +type PodIndexer func(obj *v1.Pod) ([]string, error) + +type podController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.PodsGetter + informer informers.PodInformer + gvk schema.GroupVersionKind +} + +func NewPodController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.PodsGetter, informer informers.PodInformer) PodController { + return &podController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromPodHandlerToHandler(sync PodHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Pod + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Pod)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *podController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Pod)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdatePodOnChange(updater generic.Updater, handler PodHandler) PodHandler { + return func(key string, obj *v1.Pod) (*v1.Pod, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Pod) + } + } + + return copyObj, err + } +} + +func (c *podController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *podController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *podController) OnChange(ctx context.Context, name string, sync PodHandler) { + c.AddGenericHandler(ctx, name, FromPodHandlerToHandler(sync)) +} + +func (c *podController) OnRemove(ctx context.Context, name string, sync PodHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromPodHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *podController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *podController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *podController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *podController) Cache() PodCache { + return &podCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *podController) Create(obj *v1.Pod) (*v1.Pod, error) { + return c.clientGetter.Pods(obj.Namespace).Create(obj) +} + +func (c *podController) Update(obj *v1.Pod) (*v1.Pod, error) { + return c.clientGetter.Pods(obj.Namespace).Update(obj) +} + +func (c *podController) UpdateStatus(obj *v1.Pod) (*v1.Pod, error) { + return c.clientGetter.Pods(obj.Namespace).UpdateStatus(obj) +} + +func (c *podController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Pods(namespace).Delete(name, options) +} + +func (c *podController) Get(namespace, name string, options metav1.GetOptions) (*v1.Pod, error) { + return c.clientGetter.Pods(namespace).Get(name, options) +} + +func (c *podController) List(namespace string, opts metav1.ListOptions) (*v1.PodList, error) { + return c.clientGetter.Pods(namespace).List(opts) +} + +func (c *podController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Pods(namespace).Watch(opts) +} + +func (c *podController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Pod, err error) { + return c.clientGetter.Pods(namespace).Patch(name, pt, data, subresources...) +} + +type podCache struct { + lister listers.PodLister + indexer cache.Indexer +} + +func (c *podCache) Get(namespace, name string) (*v1.Pod, error) { + return c.lister.Pods(namespace).Get(name) +} + +func (c *podCache) List(namespace string, selector labels.Selector) ([]*v1.Pod, error) { + return c.lister.Pods(namespace).List(selector) +} + +func (c *podCache) AddIndexer(indexName string, indexer PodIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Pod)) + }, + })) +} + +func (c *podCache) GetByIndex(indexName, key string) (result []*v1.Pod, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Pod)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/secret.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/secret.go new file mode 100644 index 0000000000..7b66db9eb8 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/secret.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type SecretHandler func(string, *v1.Secret) (*v1.Secret, error) + +type SecretController interface { + SecretClient + + OnChange(ctx context.Context, name string, sync SecretHandler) + OnRemove(ctx context.Context, name string, sync SecretHandler) + Enqueue(namespace, name string) + + Cache() SecretCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type SecretClient interface { + Create(*v1.Secret) (*v1.Secret, error) + Update(*v1.Secret) (*v1.Secret, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Secret, error) + List(namespace string, opts metav1.ListOptions) (*v1.SecretList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Secret, err error) +} + +type SecretCache interface { + Get(namespace, name string) (*v1.Secret, error) + List(namespace string, selector labels.Selector) ([]*v1.Secret, error) + + AddIndexer(indexName string, indexer SecretIndexer) + GetByIndex(indexName, key string) ([]*v1.Secret, error) +} + +type SecretIndexer func(obj *v1.Secret) ([]string, error) + +type secretController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.SecretsGetter + informer informers.SecretInformer + gvk schema.GroupVersionKind +} + +func NewSecretController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.SecretsGetter, informer informers.SecretInformer) SecretController { + return &secretController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromSecretHandlerToHandler(sync SecretHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Secret + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Secret)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *secretController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Secret)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateSecretOnChange(updater generic.Updater, handler SecretHandler) SecretHandler { + return func(key string, obj *v1.Secret) (*v1.Secret, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Secret) + } + } + + return copyObj, err + } +} + +func (c *secretController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *secretController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *secretController) OnChange(ctx context.Context, name string, sync SecretHandler) { + c.AddGenericHandler(ctx, name, FromSecretHandlerToHandler(sync)) +} + +func (c *secretController) OnRemove(ctx context.Context, name string, sync SecretHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromSecretHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *secretController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *secretController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *secretController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *secretController) Cache() SecretCache { + return &secretCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *secretController) Create(obj *v1.Secret) (*v1.Secret, error) { + return c.clientGetter.Secrets(obj.Namespace).Create(obj) +} + +func (c *secretController) Update(obj *v1.Secret) (*v1.Secret, error) { + return c.clientGetter.Secrets(obj.Namespace).Update(obj) +} + +func (c *secretController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Secrets(namespace).Delete(name, options) +} + +func (c *secretController) Get(namespace, name string, options metav1.GetOptions) (*v1.Secret, error) { + return c.clientGetter.Secrets(namespace).Get(name, options) +} + +func (c *secretController) List(namespace string, opts metav1.ListOptions) (*v1.SecretList, error) { + return c.clientGetter.Secrets(namespace).List(opts) +} + +func (c *secretController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Secrets(namespace).Watch(opts) +} + +func (c *secretController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Secret, err error) { + return c.clientGetter.Secrets(namespace).Patch(name, pt, data, subresources...) +} + +type secretCache struct { + lister listers.SecretLister + indexer cache.Indexer +} + +func (c *secretCache) Get(namespace, name string) (*v1.Secret, error) { + return c.lister.Secrets(namespace).Get(name) +} + +func (c *secretCache) List(namespace string, selector labels.Selector) ([]*v1.Secret, error) { + return c.lister.Secrets(namespace).List(selector) +} + +func (c *secretCache) AddIndexer(indexName string, indexer SecretIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Secret)) + }, + })) +} + +func (c *secretCache) GetByIndex(indexName, key string) (result []*v1.Secret, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Secret)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/service.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/service.go new file mode 100644 index 0000000000..98df59990d --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/service.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type ServiceHandler func(string, *v1.Service) (*v1.Service, error) + +type ServiceController interface { + ServiceClient + + OnChange(ctx context.Context, name string, sync ServiceHandler) + OnRemove(ctx context.Context, name string, sync ServiceHandler) + Enqueue(namespace, name string) + + Cache() ServiceCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ServiceClient interface { + Create(*v1.Service) (*v1.Service, error) + Update(*v1.Service) (*v1.Service, error) + UpdateStatus(*v1.Service) (*v1.Service, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Service, error) + List(namespace string, opts metav1.ListOptions) (*v1.ServiceList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error) +} + +type ServiceCache interface { + Get(namespace, name string) (*v1.Service, error) + List(namespace string, selector labels.Selector) ([]*v1.Service, error) + + AddIndexer(indexName string, indexer ServiceIndexer) + GetByIndex(indexName, key string) ([]*v1.Service, error) +} + +type ServiceIndexer func(obj *v1.Service) ([]string, error) + +type serviceController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ServicesGetter + informer informers.ServiceInformer + gvk schema.GroupVersionKind +} + +func NewServiceController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ServicesGetter, informer informers.ServiceInformer) ServiceController { + return &serviceController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromServiceHandlerToHandler(sync ServiceHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Service + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Service)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *serviceController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Service)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateServiceOnChange(updater generic.Updater, handler ServiceHandler) ServiceHandler { + return func(key string, obj *v1.Service) (*v1.Service, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Service) + } + } + + return copyObj, err + } +} + +func (c *serviceController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *serviceController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *serviceController) OnChange(ctx context.Context, name string, sync ServiceHandler) { + c.AddGenericHandler(ctx, name, FromServiceHandlerToHandler(sync)) +} + +func (c *serviceController) OnRemove(ctx context.Context, name string, sync ServiceHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromServiceHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *serviceController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *serviceController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *serviceController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *serviceController) Cache() ServiceCache { + return &serviceCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *serviceController) Create(obj *v1.Service) (*v1.Service, error) { + return c.clientGetter.Services(obj.Namespace).Create(obj) +} + +func (c *serviceController) Update(obj *v1.Service) (*v1.Service, error) { + return c.clientGetter.Services(obj.Namespace).Update(obj) +} + +func (c *serviceController) UpdateStatus(obj *v1.Service) (*v1.Service, error) { + return c.clientGetter.Services(obj.Namespace).UpdateStatus(obj) +} + +func (c *serviceController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Services(namespace).Delete(name, options) +} + +func (c *serviceController) Get(namespace, name string, options metav1.GetOptions) (*v1.Service, error) { + return c.clientGetter.Services(namespace).Get(name, options) +} + +func (c *serviceController) List(namespace string, opts metav1.ListOptions) (*v1.ServiceList, error) { + return c.clientGetter.Services(namespace).List(opts) +} + +func (c *serviceController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Services(namespace).Watch(opts) +} + +func (c *serviceController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error) { + return c.clientGetter.Services(namespace).Patch(name, pt, data, subresources...) +} + +type serviceCache struct { + lister listers.ServiceLister + indexer cache.Indexer +} + +func (c *serviceCache) Get(namespace, name string) (*v1.Service, error) { + return c.lister.Services(namespace).Get(name) +} + +func (c *serviceCache) List(namespace string, selector labels.Selector) ([]*v1.Service, error) { + return c.lister.Services(namespace).List(selector) +} + +func (c *serviceCache) AddIndexer(indexName string, indexer ServiceIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Service)) + }, + })) +} + +func (c *serviceCache) GetByIndex(indexName, key string) (result []*v1.Service, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Service)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/serviceaccount.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/serviceaccount.go new file mode 100644 index 0000000000..cd08348be8 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1/serviceaccount.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/core/v1" + clientset "k8s.io/client-go/kubernetes/typed/core/v1" + listers "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" +) + +type ServiceAccountHandler func(string, *v1.ServiceAccount) (*v1.ServiceAccount, error) + +type ServiceAccountController interface { + ServiceAccountClient + + OnChange(ctx context.Context, name string, sync ServiceAccountHandler) + OnRemove(ctx context.Context, name string, sync ServiceAccountHandler) + Enqueue(namespace, name string) + + Cache() ServiceAccountCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ServiceAccountClient interface { + Create(*v1.ServiceAccount) (*v1.ServiceAccount, error) + Update(*v1.ServiceAccount) (*v1.ServiceAccount, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.ServiceAccount, error) + List(namespace string, opts metav1.ListOptions) (*v1.ServiceAccountList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ServiceAccount, err error) +} + +type ServiceAccountCache interface { + Get(namespace, name string) (*v1.ServiceAccount, error) + List(namespace string, selector labels.Selector) ([]*v1.ServiceAccount, error) + + AddIndexer(indexName string, indexer ServiceAccountIndexer) + GetByIndex(indexName, key string) ([]*v1.ServiceAccount, error) +} + +type ServiceAccountIndexer func(obj *v1.ServiceAccount) ([]string, error) + +type serviceAccountController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ServiceAccountsGetter + informer informers.ServiceAccountInformer + gvk schema.GroupVersionKind +} + +func NewServiceAccountController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ServiceAccountsGetter, informer informers.ServiceAccountInformer) ServiceAccountController { + return &serviceAccountController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromServiceAccountHandlerToHandler(sync ServiceAccountHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.ServiceAccount + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.ServiceAccount)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *serviceAccountController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.ServiceAccount)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateServiceAccountOnChange(updater generic.Updater, handler ServiceAccountHandler) ServiceAccountHandler { + return func(key string, obj *v1.ServiceAccount) (*v1.ServiceAccount, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.ServiceAccount) + } + } + + return copyObj, err + } +} + +func (c *serviceAccountController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *serviceAccountController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *serviceAccountController) OnChange(ctx context.Context, name string, sync ServiceAccountHandler) { + c.AddGenericHandler(ctx, name, FromServiceAccountHandlerToHandler(sync)) +} + +func (c *serviceAccountController) OnRemove(ctx context.Context, name string, sync ServiceAccountHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromServiceAccountHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *serviceAccountController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *serviceAccountController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *serviceAccountController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *serviceAccountController) Cache() ServiceAccountCache { + return &serviceAccountCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *serviceAccountController) Create(obj *v1.ServiceAccount) (*v1.ServiceAccount, error) { + return c.clientGetter.ServiceAccounts(obj.Namespace).Create(obj) +} + +func (c *serviceAccountController) Update(obj *v1.ServiceAccount) (*v1.ServiceAccount, error) { + return c.clientGetter.ServiceAccounts(obj.Namespace).Update(obj) +} + +func (c *serviceAccountController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.ServiceAccounts(namespace).Delete(name, options) +} + +func (c *serviceAccountController) Get(namespace, name string, options metav1.GetOptions) (*v1.ServiceAccount, error) { + return c.clientGetter.ServiceAccounts(namespace).Get(name, options) +} + +func (c *serviceAccountController) List(namespace string, opts metav1.ListOptions) (*v1.ServiceAccountList, error) { + return c.clientGetter.ServiceAccounts(namespace).List(opts) +} + +func (c *serviceAccountController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.ServiceAccounts(namespace).Watch(opts) +} + +func (c *serviceAccountController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ServiceAccount, err error) { + return c.clientGetter.ServiceAccounts(namespace).Patch(name, pt, data, subresources...) +} + +type serviceAccountCache struct { + lister listers.ServiceAccountLister + indexer cache.Indexer +} + +func (c *serviceAccountCache) Get(namespace, name string) (*v1.ServiceAccount, error) { + return c.lister.ServiceAccounts(namespace).Get(name) +} + +func (c *serviceAccountCache) List(namespace string, selector labels.Selector) ([]*v1.ServiceAccount, error) { + return c.lister.ServiceAccounts(namespace).List(selector) +} + +func (c *serviceAccountCache) AddIndexer(indexName string, indexer ServiceAccountIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.ServiceAccount)) + }, + })) +} + +func (c *serviceAccountCache) GetByIndex(indexName, key string) (result []*v1.ServiceAccount, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.ServiceAccount)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/factory.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/factory.go new file mode 100644 index 0000000000..6080c5fd67 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package rbac + +import ( + "context" + "time" + + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + informers "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) Rbac() Interface { + return New(c.controllerManager, c.informerFactory.Rbac(), c.clientset) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/interface.go new file mode 100644 index 0000000000..572969acfb --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package rbac + +import ( + v1 "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1" + "github.com/rancher/wrangler/pkg/generic" + informers "k8s.io/client-go/informers/rbac" + clientset "k8s.io/client-go/kubernetes" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.RbacV1(), g.informers.V1()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrole.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrole.go new file mode 100644 index 0000000000..11e3849f24 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrole.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/rbac/v1" + clientset "k8s.io/client-go/kubernetes/typed/rbac/v1" + listers "k8s.io/client-go/listers/rbac/v1" + "k8s.io/client-go/tools/cache" +) + +type ClusterRoleHandler func(string, *v1.ClusterRole) (*v1.ClusterRole, error) + +type ClusterRoleController interface { + ClusterRoleClient + + OnChange(ctx context.Context, name string, sync ClusterRoleHandler) + OnRemove(ctx context.Context, name string, sync ClusterRoleHandler) + Enqueue(name string) + + Cache() ClusterRoleCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ClusterRoleClient interface { + Create(*v1.ClusterRole) (*v1.ClusterRole, error) + Update(*v1.ClusterRole) (*v1.ClusterRole, error) + + Delete(name string, options *metav1.DeleteOptions) error + Get(name string, options metav1.GetOptions) (*v1.ClusterRole, error) + List(opts metav1.ListOptions) (*v1.ClusterRoleList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterRole, err error) +} + +type ClusterRoleCache interface { + Get(name string) (*v1.ClusterRole, error) + List(selector labels.Selector) ([]*v1.ClusterRole, error) + + AddIndexer(indexName string, indexer ClusterRoleIndexer) + GetByIndex(indexName, key string) ([]*v1.ClusterRole, error) +} + +type ClusterRoleIndexer func(obj *v1.ClusterRole) ([]string, error) + +type clusterRoleController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ClusterRolesGetter + informer informers.ClusterRoleInformer + gvk schema.GroupVersionKind +} + +func NewClusterRoleController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ClusterRolesGetter, informer informers.ClusterRoleInformer) ClusterRoleController { + return &clusterRoleController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromClusterRoleHandlerToHandler(sync ClusterRoleHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.ClusterRole + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.ClusterRole)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *clusterRoleController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.ClusterRole)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateClusterRoleOnChange(updater generic.Updater, handler ClusterRoleHandler) ClusterRoleHandler { + return func(key string, obj *v1.ClusterRole) (*v1.ClusterRole, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.ClusterRole) + } + } + + return copyObj, err + } +} + +func (c *clusterRoleController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *clusterRoleController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *clusterRoleController) OnChange(ctx context.Context, name string, sync ClusterRoleHandler) { + c.AddGenericHandler(ctx, name, FromClusterRoleHandlerToHandler(sync)) +} + +func (c *clusterRoleController) OnRemove(ctx context.Context, name string, sync ClusterRoleHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromClusterRoleHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *clusterRoleController) Enqueue(name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), "", name) +} + +func (c *clusterRoleController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *clusterRoleController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *clusterRoleController) Cache() ClusterRoleCache { + return &clusterRoleCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *clusterRoleController) Create(obj *v1.ClusterRole) (*v1.ClusterRole, error) { + return c.clientGetter.ClusterRoles().Create(obj) +} + +func (c *clusterRoleController) Update(obj *v1.ClusterRole) (*v1.ClusterRole, error) { + return c.clientGetter.ClusterRoles().Update(obj) +} + +func (c *clusterRoleController) Delete(name string, options *metav1.DeleteOptions) error { + return c.clientGetter.ClusterRoles().Delete(name, options) +} + +func (c *clusterRoleController) Get(name string, options metav1.GetOptions) (*v1.ClusterRole, error) { + return c.clientGetter.ClusterRoles().Get(name, options) +} + +func (c *clusterRoleController) List(opts metav1.ListOptions) (*v1.ClusterRoleList, error) { + return c.clientGetter.ClusterRoles().List(opts) +} + +func (c *clusterRoleController) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.ClusterRoles().Watch(opts) +} + +func (c *clusterRoleController) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterRole, err error) { + return c.clientGetter.ClusterRoles().Patch(name, pt, data, subresources...) +} + +type clusterRoleCache struct { + lister listers.ClusterRoleLister + indexer cache.Indexer +} + +func (c *clusterRoleCache) Get(name string) (*v1.ClusterRole, error) { + return c.lister.Get(name) +} + +func (c *clusterRoleCache) List(selector labels.Selector) ([]*v1.ClusterRole, error) { + return c.lister.List(selector) +} + +func (c *clusterRoleCache) AddIndexer(indexName string, indexer ClusterRoleIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.ClusterRole)) + }, + })) +} + +func (c *clusterRoleCache) GetByIndex(indexName, key string) (result []*v1.ClusterRole, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.ClusterRole)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrolebinding.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrolebinding.go new file mode 100644 index 0000000000..3f9ea4f5fa --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/clusterrolebinding.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/rbac/v1" + clientset "k8s.io/client-go/kubernetes/typed/rbac/v1" + listers "k8s.io/client-go/listers/rbac/v1" + "k8s.io/client-go/tools/cache" +) + +type ClusterRoleBindingHandler func(string, *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) + +type ClusterRoleBindingController interface { + ClusterRoleBindingClient + + OnChange(ctx context.Context, name string, sync ClusterRoleBindingHandler) + OnRemove(ctx context.Context, name string, sync ClusterRoleBindingHandler) + Enqueue(name string) + + Cache() ClusterRoleBindingCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ClusterRoleBindingClient interface { + Create(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) + Update(*v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) + + Delete(name string, options *metav1.DeleteOptions) error + Get(name string, options metav1.GetOptions) (*v1.ClusterRoleBinding, error) + List(opts metav1.ListOptions) (*v1.ClusterRoleBindingList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterRoleBinding, err error) +} + +type ClusterRoleBindingCache interface { + Get(name string) (*v1.ClusterRoleBinding, error) + List(selector labels.Selector) ([]*v1.ClusterRoleBinding, error) + + AddIndexer(indexName string, indexer ClusterRoleBindingIndexer) + GetByIndex(indexName, key string) ([]*v1.ClusterRoleBinding, error) +} + +type ClusterRoleBindingIndexer func(obj *v1.ClusterRoleBinding) ([]string, error) + +type clusterRoleBindingController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ClusterRoleBindingsGetter + informer informers.ClusterRoleBindingInformer + gvk schema.GroupVersionKind +} + +func NewClusterRoleBindingController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ClusterRoleBindingsGetter, informer informers.ClusterRoleBindingInformer) ClusterRoleBindingController { + return &clusterRoleBindingController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromClusterRoleBindingHandlerToHandler(sync ClusterRoleBindingHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.ClusterRoleBinding + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.ClusterRoleBinding)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *clusterRoleBindingController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.ClusterRoleBinding)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateClusterRoleBindingOnChange(updater generic.Updater, handler ClusterRoleBindingHandler) ClusterRoleBindingHandler { + return func(key string, obj *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.ClusterRoleBinding) + } + } + + return copyObj, err + } +} + +func (c *clusterRoleBindingController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *clusterRoleBindingController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *clusterRoleBindingController) OnChange(ctx context.Context, name string, sync ClusterRoleBindingHandler) { + c.AddGenericHandler(ctx, name, FromClusterRoleBindingHandlerToHandler(sync)) +} + +func (c *clusterRoleBindingController) OnRemove(ctx context.Context, name string, sync ClusterRoleBindingHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromClusterRoleBindingHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *clusterRoleBindingController) Enqueue(name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), "", name) +} + +func (c *clusterRoleBindingController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *clusterRoleBindingController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *clusterRoleBindingController) Cache() ClusterRoleBindingCache { + return &clusterRoleBindingCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *clusterRoleBindingController) Create(obj *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { + return c.clientGetter.ClusterRoleBindings().Create(obj) +} + +func (c *clusterRoleBindingController) Update(obj *v1.ClusterRoleBinding) (*v1.ClusterRoleBinding, error) { + return c.clientGetter.ClusterRoleBindings().Update(obj) +} + +func (c *clusterRoleBindingController) Delete(name string, options *metav1.DeleteOptions) error { + return c.clientGetter.ClusterRoleBindings().Delete(name, options) +} + +func (c *clusterRoleBindingController) Get(name string, options metav1.GetOptions) (*v1.ClusterRoleBinding, error) { + return c.clientGetter.ClusterRoleBindings().Get(name, options) +} + +func (c *clusterRoleBindingController) List(opts metav1.ListOptions) (*v1.ClusterRoleBindingList, error) { + return c.clientGetter.ClusterRoleBindings().List(opts) +} + +func (c *clusterRoleBindingController) Watch(opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.ClusterRoleBindings().Watch(opts) +} + +func (c *clusterRoleBindingController) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ClusterRoleBinding, err error) { + return c.clientGetter.ClusterRoleBindings().Patch(name, pt, data, subresources...) +} + +type clusterRoleBindingCache struct { + lister listers.ClusterRoleBindingLister + indexer cache.Indexer +} + +func (c *clusterRoleBindingCache) Get(name string) (*v1.ClusterRoleBinding, error) { + return c.lister.Get(name) +} + +func (c *clusterRoleBindingCache) List(selector labels.Selector) ([]*v1.ClusterRoleBinding, error) { + return c.lister.List(selector) +} + +func (c *clusterRoleBindingCache) AddIndexer(indexName string, indexer ClusterRoleBindingIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.ClusterRoleBinding)) + }, + })) +} + +func (c *clusterRoleBindingCache) GetByIndex(indexName, key string) (result []*v1.ClusterRoleBinding, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.ClusterRoleBinding)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/interface.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/interface.go new file mode 100644 index 0000000000..8c62786369 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/interface.go @@ -0,0 +1,61 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/rbac/v1" + informers "k8s.io/client-go/informers/rbac/v1" + clientset "k8s.io/client-go/kubernetes/typed/rbac/v1" +) + +type Interface interface { + ClusterRole() ClusterRoleController + ClusterRoleBinding() ClusterRoleBindingController + Role() RoleController + RoleBinding() RoleBindingController +} + +func New(controllerManager *generic.ControllerManager, client clientset.RbacV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.RbacV1Interface +} + +func (c *version) ClusterRole() ClusterRoleController { + return NewClusterRoleController(v1.SchemeGroupVersion.WithKind("ClusterRole"), c.controllerManager, c.client, c.informers.ClusterRoles()) +} +func (c *version) ClusterRoleBinding() ClusterRoleBindingController { + return NewClusterRoleBindingController(v1.SchemeGroupVersion.WithKind("ClusterRoleBinding"), c.controllerManager, c.client, c.informers.ClusterRoleBindings()) +} +func (c *version) Role() RoleController { + return NewRoleController(v1.SchemeGroupVersion.WithKind("Role"), c.controllerManager, c.client, c.informers.Roles()) +} +func (c *version) RoleBinding() RoleBindingController { + return NewRoleBindingController(v1.SchemeGroupVersion.WithKind("RoleBinding"), c.controllerManager, c.client, c.informers.RoleBindings()) +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/role.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/role.go new file mode 100644 index 0000000000..849fb54420 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/role.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/rbac/v1" + clientset "k8s.io/client-go/kubernetes/typed/rbac/v1" + listers "k8s.io/client-go/listers/rbac/v1" + "k8s.io/client-go/tools/cache" +) + +type RoleHandler func(string, *v1.Role) (*v1.Role, error) + +type RoleController interface { + RoleClient + + OnChange(ctx context.Context, name string, sync RoleHandler) + OnRemove(ctx context.Context, name string, sync RoleHandler) + Enqueue(namespace, name string) + + Cache() RoleCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type RoleClient interface { + Create(*v1.Role) (*v1.Role, error) + Update(*v1.Role) (*v1.Role, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Role, error) + List(namespace string, opts metav1.ListOptions) (*v1.RoleList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Role, err error) +} + +type RoleCache interface { + Get(namespace, name string) (*v1.Role, error) + List(namespace string, selector labels.Selector) ([]*v1.Role, error) + + AddIndexer(indexName string, indexer RoleIndexer) + GetByIndex(indexName, key string) ([]*v1.Role, error) +} + +type RoleIndexer func(obj *v1.Role) ([]string, error) + +type roleController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.RolesGetter + informer informers.RoleInformer + gvk schema.GroupVersionKind +} + +func NewRoleController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.RolesGetter, informer informers.RoleInformer) RoleController { + return &roleController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromRoleHandlerToHandler(sync RoleHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Role + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Role)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *roleController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Role)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateRoleOnChange(updater generic.Updater, handler RoleHandler) RoleHandler { + return func(key string, obj *v1.Role) (*v1.Role, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Role) + } + } + + return copyObj, err + } +} + +func (c *roleController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *roleController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *roleController) OnChange(ctx context.Context, name string, sync RoleHandler) { + c.AddGenericHandler(ctx, name, FromRoleHandlerToHandler(sync)) +} + +func (c *roleController) OnRemove(ctx context.Context, name string, sync RoleHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromRoleHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *roleController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *roleController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *roleController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *roleController) Cache() RoleCache { + return &roleCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *roleController) Create(obj *v1.Role) (*v1.Role, error) { + return c.clientGetter.Roles(obj.Namespace).Create(obj) +} + +func (c *roleController) Update(obj *v1.Role) (*v1.Role, error) { + return c.clientGetter.Roles(obj.Namespace).Update(obj) +} + +func (c *roleController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Roles(namespace).Delete(name, options) +} + +func (c *roleController) Get(namespace, name string, options metav1.GetOptions) (*v1.Role, error) { + return c.clientGetter.Roles(namespace).Get(name, options) +} + +func (c *roleController) List(namespace string, opts metav1.ListOptions) (*v1.RoleList, error) { + return c.clientGetter.Roles(namespace).List(opts) +} + +func (c *roleController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Roles(namespace).Watch(opts) +} + +func (c *roleController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Role, err error) { + return c.clientGetter.Roles(namespace).Patch(name, pt, data, subresources...) +} + +type roleCache struct { + lister listers.RoleLister + indexer cache.Indexer +} + +func (c *roleCache) Get(namespace, name string) (*v1.Role, error) { + return c.lister.Roles(namespace).Get(name) +} + +func (c *roleCache) List(namespace string, selector labels.Selector) ([]*v1.Role, error) { + return c.lister.Roles(namespace).List(selector) +} + +func (c *roleCache) AddIndexer(indexName string, indexer RoleIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Role)) + }, + })) +} + +func (c *roleCache) GetByIndex(indexName, key string) (result []*v1.Role, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Role)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/rolebinding.go b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/rolebinding.go new file mode 100644 index 0000000000..9bfddb5218 --- /dev/null +++ b/vendor/github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1/rolebinding.go @@ -0,0 +1,238 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + v1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + informers "k8s.io/client-go/informers/rbac/v1" + clientset "k8s.io/client-go/kubernetes/typed/rbac/v1" + listers "k8s.io/client-go/listers/rbac/v1" + "k8s.io/client-go/tools/cache" +) + +type RoleBindingHandler func(string, *v1.RoleBinding) (*v1.RoleBinding, error) + +type RoleBindingController interface { + RoleBindingClient + + OnChange(ctx context.Context, name string, sync RoleBindingHandler) + OnRemove(ctx context.Context, name string, sync RoleBindingHandler) + Enqueue(namespace, name string) + + Cache() RoleBindingCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type RoleBindingClient interface { + Create(*v1.RoleBinding) (*v1.RoleBinding, error) + Update(*v1.RoleBinding) (*v1.RoleBinding, error) + + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.RoleBinding, error) + List(namespace string, opts metav1.ListOptions) (*v1.RoleBindingList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.RoleBinding, err error) +} + +type RoleBindingCache interface { + Get(namespace, name string) (*v1.RoleBinding, error) + List(namespace string, selector labels.Selector) ([]*v1.RoleBinding, error) + + AddIndexer(indexName string, indexer RoleBindingIndexer) + GetByIndex(indexName, key string) ([]*v1.RoleBinding, error) +} + +type RoleBindingIndexer func(obj *v1.RoleBinding) ([]string, error) + +type roleBindingController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.RoleBindingsGetter + informer informers.RoleBindingInformer + gvk schema.GroupVersionKind +} + +func NewRoleBindingController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.RoleBindingsGetter, informer informers.RoleBindingInformer) RoleBindingController { + return &roleBindingController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromRoleBindingHandlerToHandler(sync RoleBindingHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.RoleBinding + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.RoleBinding)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *roleBindingController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.RoleBinding)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateRoleBindingOnChange(updater generic.Updater, handler RoleBindingHandler) RoleBindingHandler { + return func(key string, obj *v1.RoleBinding) (*v1.RoleBinding, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.RoleBinding) + } + } + + return copyObj, err + } +} + +func (c *roleBindingController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *roleBindingController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *roleBindingController) OnChange(ctx context.Context, name string, sync RoleBindingHandler) { + c.AddGenericHandler(ctx, name, FromRoleBindingHandlerToHandler(sync)) +} + +func (c *roleBindingController) OnRemove(ctx context.Context, name string, sync RoleBindingHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromRoleBindingHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *roleBindingController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *roleBindingController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *roleBindingController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *roleBindingController) Cache() RoleBindingCache { + return &roleBindingCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *roleBindingController) Create(obj *v1.RoleBinding) (*v1.RoleBinding, error) { + return c.clientGetter.RoleBindings(obj.Namespace).Create(obj) +} + +func (c *roleBindingController) Update(obj *v1.RoleBinding) (*v1.RoleBinding, error) { + return c.clientGetter.RoleBindings(obj.Namespace).Update(obj) +} + +func (c *roleBindingController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.RoleBindings(namespace).Delete(name, options) +} + +func (c *roleBindingController) Get(namespace, name string, options metav1.GetOptions) (*v1.RoleBinding, error) { + return c.clientGetter.RoleBindings(namespace).Get(name, options) +} + +func (c *roleBindingController) List(namespace string, opts metav1.ListOptions) (*v1.RoleBindingList, error) { + return c.clientGetter.RoleBindings(namespace).List(opts) +} + +func (c *roleBindingController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.RoleBindings(namespace).Watch(opts) +} + +func (c *roleBindingController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.RoleBinding, err error) { + return c.clientGetter.RoleBindings(namespace).Patch(name, pt, data, subresources...) +} + +type roleBindingCache struct { + lister listers.RoleBindingLister + indexer cache.Indexer +} + +func (c *roleBindingCache) Get(namespace, name string) (*v1.RoleBinding, error) { + return c.lister.RoleBindings(namespace).Get(name) +} + +func (c *roleBindingCache) List(namespace string, selector labels.Selector) ([]*v1.RoleBinding, error) { + return c.lister.RoleBindings(namespace).List(selector) +} + +func (c *roleBindingCache) AddIndexer(indexName string, indexer RoleBindingIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.RoleBinding)) + }, + })) +} + +func (c *roleBindingCache) GetByIndex(indexName, key string) (result []*v1.RoleBinding, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.RoleBinding)) + } + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler/LICENSE b/vendor/github.com/rancher/wrangler/LICENSE new file mode 100644 index 0000000000..e454a52586 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/LICENSE @@ -0,0 +1,178 @@ + + 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 + diff --git a/vendor/github.com/rancher/wrangler/README.md b/vendor/github.com/rancher/wrangler/README.md new file mode 100644 index 0000000000..19be2eabdc --- /dev/null +++ b/vendor/github.com/rancher/wrangler/README.md @@ -0,0 +1,77 @@ +Wrangler [In Development - Does Not Work] +-------- +Framework for wrapping clients, informers, listers into a simple +usable controller pattern that promotes some good practices. + +More documentation to follow but if you want to see what it +looks like to write a controller with this framework refer to +[main.go](https://github.com/rancher/wrangler/blob/master/sample/main.go) and [controller.go](https://github.com/rancher/wrangler/blob/master/sample/controller.go) in + the [sample](https://github.com/rancher/wrangler/blob/master/sample). + +Sample Project +------ +The sample project does the same things as the standard Kubernetes [sample controller](https://github.com/kubernetes/sample-controller) but +just using this framework and patterns. + +To use the sample clone this project to a proper GOPATH and then + +```bash +cd $GOPATH/src/github.com/rancher/wrangler/sample +go generate +go build . +./sample +``` + +How it works +------------ + +Most people writing controllers are a bit lost when they go to write a controller as they +find that there is nothing in Kubernetes that is like `type Controller interface` where you +can just do `NewController`. Instead a controller is really just a pattern of how you use +the generated clientsets, informers, and listers combined with some custom event handlers and +a workqueue. + +Wrangler providers a code generator that will generate the clientset, informers, listers and +additionally generate a controller per type. The interface to the +controller looks as follows + +To use the controller all one needs to do is register simple OnChange handlers. Also in the +interface is access to the client and caches in a simple flat API. refer to +[main.go](https://github.com/rancher/wrangler/blob/master/sample/main.go) and [controller.go](https://github.com/rancher/wrangler/blob/master/sample/controller.go) in + the [sample project](https://github.com/rancher/wrangler/blob/master/sample) for more complete usage. + +```golang +type FooHandler func(string, *v1alpha1.Foo) (*v1alpha1.Foo, error) + +type FooController interface { + Create(*v1alpha1.Foo) (*v1alpha1.Foo, error) + Update(*v1alpha1.Foo) (*v1alpha1.Foo, error) + UpdateStatus(*v1alpha1.Foo) (*v1alpha1.Foo, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + DeleteCollection(namespace string, options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1alpha1.Foo, error) + List(namespace string, opts metav1.ListOptions) (*v1alpha1.FooList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Foo, err error) + + Cache() FooControllerCache + + OnChange(ctx context.Context, name string, sync FooHandler) + OnRemove(ctx context.Context, name string, sync FooHandler) + Enqueue(namespace, name string) + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind +} + +type FooControllerCache interface { + Get(namespace, name string) (*v1alpha1.Foo, error) + List(namespace string, selector labels.Selector) ([]*v1alpha1.Foo, error) + + AddIndexer(indexName string, indexer FooIndexer) + GetByIndex(indexName, key string) ([]*v1alpha1.Foo, error) +} + +type FooIndexer func(obj *v1alpha1.Foo) ([]string, error) + +``` diff --git a/vendor/github.com/rancher/wrangler/go.mod b/vendor/github.com/rancher/wrangler/go.mod new file mode 100644 index 0000000000..36bd20841e --- /dev/null +++ b/vendor/github.com/rancher/wrangler/go.mod @@ -0,0 +1,38 @@ +module github.com/rancher/wrangler + +go 1.12 + +replace github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 + +require ( + github.com/evanphx/json-patch v4.2.0+incompatible // indirect + github.com/ghodss/yaml v1.0.0 + github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect + github.com/golang/protobuf v1.3.1 // indirect + github.com/google/gofuzz v1.0.0 // indirect + github.com/googleapis/gnostic v0.2.0 // indirect + github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/imdario/mergo v0.3.7 // indirect + github.com/json-iterator/go v1.1.6 // indirect + github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pkg/errors v0.8.1 + github.com/sirupsen/logrus v1.4.1 + golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a // indirect + golang.org/x/sync v0.0.0-20190423024810-112230192c58 + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect + golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.2.2 // indirect + k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b + k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 + k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d + k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible + k8s.io/code-generator v0.0.0-20190311093542-50b561225d70 + k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a + k8s.io/klog v0.3.0 + k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 // indirect + k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 // indirect + sigs.k8s.io/yaml v1.1.0 // indirect +) diff --git a/vendor/github.com/rancher/wrangler/go.sum b/vendor/github.com/rancher/wrangler/go.sum new file mode 100644 index 0000000000..c59683411d --- /dev/null +++ b/vendor/github.com/rancher/wrangler/go.sum @@ -0,0 +1,316 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v0.0.0-20180117170138-065b426bd416/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550 h1:mV9jbLoSW/8m4VK16ZkHTozJa8sesK5u5kTMFysTYac= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.17.2/go.mod h1:QO936ZXeisByFmZEO1IS1Dqhtf4QV1sYYFtIq6Ld86Q= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.0.0-20141017032234-72f9bd7c4e0c/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 h1:Xsxh7fX3+2wAUJtPy8g2lZh0cYuyifqhBL0vxCIYojs= +github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na5h73XkbuEf2AP9fbgrIGqqxVzFhYD6U= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cobra v0.0.0-20180319062004-c439c4fa0937/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff h1:VARhShG49tiji6mdRNp7JTNDtJ0FhuprF93GBQ37xGU= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190318221613-d196dffd7c2b h1:ZWpVMTsK0ey5WJCu+vVdfMldWq7/ezaOcjnKWIHWVkE= +golang.org/x/net v0.0.0-20190318221613-d196dffd7c2b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190411180116-681f9ce8ac52 h1:9RlW/mHPSeoxtqVWkJ7ZugoTFX8WFZRzmCep/niCbtU= +golang.org/x/tools v0.0.0-20190411180116-681f9ce8ac52/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190509153222-73554e0f7805 h1:1ufBXAsTpUhSmmPXEEs5PrGQSfnBhsjAd2SmVhp9xrY= +golang.org/x/tools v0.0.0-20190509153222-73554e0f7805/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190503110853-61630f889b3c h1:y1nbvZVlOyUa+p4RVXqQj+s6W+FjZZNVkgG5pvYpFhU= +k8s.io/api v0.0.0-20190503110853-61630f889b3c/go.mod h1:42M1T54fVvXj2R/yqB+v9ksH4xI41q6XU/NUlo3hyjk= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 h1:q1Qvjzs/iEdXF6A1a8H3AKVFDzJNcJn3nXMs6R6qFtA= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= +k8s.io/apiextensions-apiserver v0.0.0-20190509064156-0d7f274f68cb h1:H1lmk1bj+eBMoV5ZrjjiNteOZbyNW83ky9lBj/VXFv4= +k8s.io/apiextensions-apiserver v0.0.0-20190509064156-0d7f274f68cb/go.mod h1:kPauayyBRLaL36ujVyx3zHiX/ZryjlOlo/eY1I7HN4Q= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/apimachinery v0.0.0-20190502092502-a44ef629a3c9/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw= +k8s.io/apimachinery v0.0.0-20190508063446-a3da69d3723c/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw= +k8s.io/apimachinery v0.0.0-20190509063443-7d8f8feb49c5 h1:fEvp/a2P/A7mOT2jK8Kznm3XNOvKVXU2FDDdaPDcMrs= +k8s.io/apimachinery v0.0.0-20190509063443-7d8f8feb49c5/go.mod h1:5CBnzrKYGHzv9ZsSKmQ8wHt4XI4/TUBPDwYM9FlZMyw= +k8s.io/apiserver v0.0.0-20190509063909-3b296809833b/go.mod h1:2LexhkMnSuvwNmYzmjMUU8aroaFpFkLKcv/DeZaEpjs= +k8s.io/client-go v0.0.0-20190508063711-1babf78c8b32/go.mod h1:xF+vJeNvjoNfv1P1p3aElmg8C1YDMDUsrCtcMbYbzn0= +k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= +k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70 h1:lgPp615xLHxN84RBd+viA/oHzJfI0miFYFH4T9wpPQ4= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d h1:QY1FeareEgkYrWnF2D2XxZFlF0k5Ir4uE8YjD1kHi94= +k8s.io/code-generator v0.0.0-20190419212335-ff26e7842f9d/go.mod h1:rVrFWfTVftGH7bb972nWC6N4QkJ4LU7FOXu8GH2UkJo= +k8s.io/component-base v0.0.0-20190509023737-8de8845fb642/go.mod h1:1OvmLN55oW7tYZ/2zSCSxOfOICjo9Tm2eyiKy+Fk7hw= +k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a h1:QoHVuRquf80YZ+/bovwxoMO3Q/A3nt3yTgS0/0nejuk= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.2.0 h1:0ElL0OHzF3N+OhoJTL0uca20SxtYt4X4+bzHeqrB83c= +k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 h1:TRb4wNWoBVrH9plmkp2q86FIDppkbrEXdXlxU3a3BMI= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190401085232-94e1e7b7574c h1:kJCzg2vGCzah5icgkKR7O1Dzn0NA2iGlym27sb0ZfGE= +k8s.io/kube-openapi v0.0.0-20190401085232-94e1e7b7574c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 h1:IrnrEIp9du1SngrzGC1fdYEdos7Il6I6EVxwFQHJwCg= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= +k8s.io/utils v0.0.0-20190221042446-c2654d5206da h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn3b/WPHqD5mBvP4= +k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 h1:8r+l4bNWjRlsFYlQJnKJ2p7s1YQPj4XyXiJVqDHRx7c= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +sigs.k8s.io/structured-merge-diff v0.0.0-20190302045857-e85c7b244fd2/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/apply.go b/vendor/github.com/rancher/wrangler/pkg/apply/apply.go new file mode 100644 index 0000000000..c346d14488 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/apply/apply.go @@ -0,0 +1,170 @@ +package apply + +import ( + "fmt" + "sync" + + "github.com/rancher/wrangler/pkg/apply/injectors" + "github.com/rancher/wrangler/pkg/objectset" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/tools/cache" +) + +const ( + defaultNamespace = "default" +) + +type Patcher func(namespace, name string, pt types.PatchType, data []byte) (runtime.Object, error) + +type ClientFactory func(gvk schema.GroupVersionKind) (dynamic.NamespaceableResourceInterface, error) + +type InformerGetter interface { + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind +} + +type Apply interface { + Apply(set *objectset.ObjectSet) error + ApplyObjects(objs ...runtime.Object) error + WithCacheTypes(igs ...InformerGetter) Apply + WithSetID(id string) Apply + WithOwner(obj runtime.Object) Apply + WithInjector(injs ...injectors.ConfigInjector) Apply + WithInjectorName(injs ...string) Apply + WithPatcher(gvk schema.GroupVersionKind, patchers Patcher) Apply + WithStrictCaching() Apply + WithDefaultNamespace(ns string) Apply + WithRateLimiting(ratelimitingQps float32) Apply + WithNoDelete() Apply +} + +func New(discovery discovery.DiscoveryInterface, cf ClientFactory, igs ...InformerGetter) Apply { + a := &apply{ + clients: &clients{ + clientFactory: cf, + discovery: discovery, + namespaced: map[schema.GroupVersionKind]bool{}, + clients: map[schema.GroupVersionKind]dynamic.NamespaceableResourceInterface{}, + }, + informers: map[schema.GroupVersionKind]cache.SharedIndexInformer{}, + } + + for _, ig := range igs { + a.informers[ig.GroupVersionKind()] = ig.Informer() + } + + return a +} + +type apply struct { + clients *clients + informers map[schema.GroupVersionKind]cache.SharedIndexInformer +} + +type clients struct { + sync.Mutex + + clientFactory ClientFactory + discovery discovery.DiscoveryInterface + namespaced map[schema.GroupVersionKind]bool + clients map[schema.GroupVersionKind]dynamic.NamespaceableResourceInterface +} + +func (c *clients) IsNamespaced(gvk schema.GroupVersionKind) bool { + c.Lock() + defer c.Unlock() + return c.namespaced[gvk] +} + +func (c *clients) client(gvk schema.GroupVersionKind) (dynamic.NamespaceableResourceInterface, error) { + c.Lock() + defer c.Unlock() + + if client, ok := c.clients[gvk]; ok { + return client, nil + } + + resources, err := c.discovery.ServerResourcesForGroupVersion(gvk.GroupVersion().String()) + if err != nil { + return nil, err + } + + for _, resource := range resources.APIResources { + if resource.Kind != gvk.Kind { + continue + } + + client, err := c.clientFactory(gvk) + if err != nil { + return nil, err + } + + c.namespaced[gvk] = resource.Namespaced + c.clients[gvk] = client + return client, nil + } + + return nil, fmt.Errorf("failed to discover client for %s", gvk) +} + +func (a *apply) newDesiredSet() desiredSet { + return desiredSet{ + a: a, + defaultNamespace: defaultNamespace, + ratelimitingQps: 1, + } +} + +func (a *apply) Apply(set *objectset.ObjectSet) error { + return a.newDesiredSet().Apply(set) +} + +func (a *apply) ApplyObjects(objs ...runtime.Object) error { + os := objectset.NewObjectSet() + os.Add(objs...) + return a.newDesiredSet().Apply(os) +} + +func (a *apply) WithSetID(id string) Apply { + return a.newDesiredSet().WithSetID(id) +} + +func (a *apply) WithOwner(obj runtime.Object) Apply { + return a.newDesiredSet().WithOwner(obj) +} + +func (a *apply) WithInjector(injs ...injectors.ConfigInjector) Apply { + return a.newDesiredSet().WithInjector(injs...) +} + +func (a *apply) WithInjectorName(injs ...string) Apply { + return a.newDesiredSet().WithInjectorName(injs...) +} + +func (a *apply) WithCacheTypes(igs ...InformerGetter) Apply { + return a.newDesiredSet().WithCacheTypes(igs...) +} + +func (a *apply) WithPatcher(gvk schema.GroupVersionKind, patcher Patcher) Apply { + return a.newDesiredSet().WithPatcher(gvk, patcher) +} + +func (a *apply) WithStrictCaching() Apply { + return a.newDesiredSet().WithStrictCaching() +} + +func (a *apply) WithDefaultNamespace(ns string) Apply { + return a.newDesiredSet().WithDefaultNamespace(ns) +} + +func (a *apply) WithRateLimiting(ratelimitingQps float32) Apply { + return a.newDesiredSet().WithRateLimiting(ratelimitingQps) +} + +func (a *apply) WithNoDelete() Apply { + return a.newDesiredSet().WithNoDelete() +} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/client_factory.go b/vendor/github.com/rancher/wrangler/pkg/apply/client_factory.go new file mode 100644 index 0000000000..5facc0f379 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/apply/client_factory.go @@ -0,0 +1,22 @@ +package apply + +import ( + "strings" + + "github.com/rancher/wrangler/pkg/name" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" +) + +func NewClientFactory(config *rest.Config) ClientFactory { + return func(gvk schema.GroupVersionKind) (dynamic.NamespaceableResourceInterface, error) { + client, err := dynamic.NewForConfig(config) + if err != nil { + return nil, err + } + + gvr := gvk.GroupVersion().WithResource(name.GuessPluralName(strings.ToLower(gvk.Kind))) + return client.Resource(gvr), nil + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go new file mode 100644 index 0000000000..d29bae380d --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset.go @@ -0,0 +1,115 @@ +package apply + +import ( + "github.com/rancher/wrangler/pkg/apply/injectors" + "github.com/rancher/wrangler/pkg/merr" + "github.com/rancher/wrangler/pkg/objectset" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +type desiredSet struct { + a *apply + defaultNamespace string + strictCaching bool + pruneTypes map[schema.GroupVersionKind]cache.SharedIndexInformer + patchers map[schema.GroupVersionKind]Patcher + remove bool + noDelete bool + setID string + objs *objectset.ObjectSet + codeVersion string + owner runtime.Object + injectors []injectors.ConfigInjector + ratelimitingQps float32 + injectorNames []string + errs []error +} + +func (o *desiredSet) err(err error) error { + o.errs = append(o.errs, err) + return o.Err() +} + +func (o desiredSet) Err() error { + return merr.NewErrors(append(o.errs, o.objs.Err())...) +} + +func (o desiredSet) Apply(set *objectset.ObjectSet) error { + if set == nil { + set = objectset.NewObjectSet() + } + o.objs = set + return o.apply() +} + +func (o desiredSet) ApplyObjects(objs ...runtime.Object) error { + os := objectset.NewObjectSet() + os.Add(objs...) + return o.Apply(os) +} + +func (o desiredSet) WithSetID(id string) Apply { + o.setID = id + return o +} + +func (o desiredSet) WithOwner(obj runtime.Object) Apply { + o.owner = obj + return o +} + +func (o desiredSet) WithInjector(injs ...injectors.ConfigInjector) Apply { + o.injectors = append(o.injectors, injs...) + return o +} + +func (o desiredSet) WithInjectorName(injs ...string) Apply { + o.injectorNames = append(o.injectorNames, injs...) + return o +} + +func (o desiredSet) WithCacheTypes(igs ...InformerGetter) Apply { + pruneTypes := map[schema.GroupVersionKind]cache.SharedIndexInformer{} + for k, v := range o.pruneTypes { + pruneTypes[k] = v + } + + for _, ig := range igs { + pruneTypes[ig.GroupVersionKind()] = ig.Informer() + } + + o.pruneTypes = pruneTypes + return o +} + +func (o desiredSet) WithPatcher(gvk schema.GroupVersionKind, patcher Patcher) Apply { + patchers := map[schema.GroupVersionKind]Patcher{} + for k, v := range o.patchers { + patchers[k] = v + } + patchers[gvk] = patcher + o.patchers = patchers + return o +} + +func (o desiredSet) WithStrictCaching() Apply { + o.strictCaching = true + return o +} + +func (o desiredSet) WithDefaultNamespace(ns string) Apply { + o.defaultNamespace = ns + return o +} + +func (o desiredSet) WithRateLimiting(ratelimitingQps float32) Apply { + o.ratelimitingQps = ratelimitingQps + return o +} + +func (o desiredSet) WithNoDelete() Apply { + o.noDelete = true + return o +} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_apply.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go similarity index 59% rename from vendor/github.com/rancher/norman/pkg/objectset/desiredset_apply.go rename to vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go index 5dd01ff280..c211bc65b7 100644 --- a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_apply.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_apply.go @@ -1,13 +1,14 @@ -package objectset +package apply import ( "crypto/sha1" "encoding/hex" "fmt" - "sort" "sync" "github.com/pkg/errors" + "github.com/rancher/wrangler/pkg/apply/injectors" + "github.com/rancher/wrangler/pkg/objectset" errors2 "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,25 +38,29 @@ var ( rlsLock sync.Mutex ) -func (o *DesiredSet) getRateLimit(inputID string) flowcontrol.RateLimiter { +func (o *desiredSet) getRateLimit(labelHash string) flowcontrol.RateLimiter { var rl flowcontrol.RateLimiter rlsLock.Lock() defer rlsLock.Unlock() if o.remove { - delete(rls, inputID) + delete(rls, labelHash) } else { - rl = rls[inputID] + rl = rls[labelHash] if rl == nil { - rl = flowcontrol.NewTokenBucketRateLimiter(4.0/60.0, 10) - rls[inputID] = rl + rl = flowcontrol.NewTokenBucketRateLimiter(o.ratelimitingQps, 10) + rls[labelHash] = rl } } return rl } -func (o *DesiredSet) Apply() error { +func (o *desiredSet) apply() error { + if o.objs == nil || o.objs.Len() == 0 { + o.remove = true + } + if err := o.Err(); err != nil { return err } @@ -70,8 +75,6 @@ func (o *DesiredSet) Apply() error { return errors2.NewConflict(schema.GroupResource{}, o.setID, errors.New("delaying object set")) } - inputID := o.inputID(labelSet[LabelHash]) - objList, err := o.injectLabelsAndAnnotations(labelSet, annotationSet) if err != nil { return o.err(err) @@ -90,81 +93,21 @@ func (o *DesiredSet) Apply() error { return o.err(err) } - for _, gvk := range o.gvkOrder() { - o.process(inputID, debugID, labels.NewSelector().Add(*req), gvk, objs[gvk]) + for _, gvk := range o.objs.GVKOrder(o.knownGVK()...) { + o.process(debugID, labels.NewSelector().Add(*req), gvk, objs[gvk]) } return o.Err() } -func (o *DesiredSet) gvkOrder() []schema.GroupVersionKind { - seen := map[schema.GroupVersionKind]bool{} - var gvkOrder []schema.GroupVersionKind - - for _, obj := range o.objs.order { - if seen[obj.GetObjectKind().GroupVersionKind()] { - continue - } - seen[obj.GetObjectKind().GroupVersionKind()] = true - gvkOrder = append(gvkOrder, obj.GetObjectKind().GroupVersionKind()) +func (o *desiredSet) knownGVK() (ret []schema.GroupVersionKind) { + for k := range o.pruneTypes { + ret = append(ret, k) } - - var rest []schema.GroupVersionKind - - for gvk := range o.clients { - if seen[gvk] { - continue - } - - seen[gvk] = true - rest = append(rest, gvk) - } - - sort.Slice(rest, func(i, j int) bool { - return rest[i].String() < rest[j].String() - }) - - return append(gvkOrder, rest...) + return } -func (o *DesiredSet) inputID(labelHash string) string { - sort.Slice(o.objs.inputs, func(i, j int) bool { - left, lErr := meta.Accessor(o.objs.inputs[i]) - right, rErr := meta.Accessor(o.objs.inputs[j]) - if lErr != nil || rErr != nil { - return true - } - - lKey := o.objs.inputs[i].GetObjectKind().GroupVersionKind().String() + "/" + newObjectKey(left).String() - rKey := o.objs.inputs[j].GetObjectKind().GroupVersionKind().String() + "/" + newObjectKey(right).String() - return lKey < rKey - }) - - dig := sha1.New() - dig.Write([]byte(o.codeVersion)) - dig.Write([]byte(labelHash)) - - inputs := o.objs.inputs - if o.owner != nil { - inputs = append([]runtime.Object{o.owner}, o.objs.inputs...) - } - - for _, obj := range inputs { - metadata, err := meta.Accessor(obj) - if err != nil { - dig.Write([]byte(obj.GetObjectKind().GroupVersionKind().String())) - continue - } - - key := newObjectKey(metadata) - dig.Write([]byte(key.String())) - dig.Write([]byte(metadata.GetResourceVersion())) - } - - return hex.EncodeToString(dig.Sum(nil)) -} - -func (o *DesiredSet) debugID() string { +func (o *desiredSet) debugID() string { if o.owner == nil { return o.setID } @@ -173,21 +116,21 @@ func (o *DesiredSet) debugID() string { return o.setID } - return fmt.Sprintf("%s %s", o.setID, objectKey{ - namespace: metadata.GetNamespace(), - name: metadata.GetName(), + return fmt.Sprintf("%s %s", o.setID, objectset.ObjectKey{ + Namespace: metadata.GetNamespace(), + Name: metadata.GetName(), }) } -func (o *DesiredSet) collect(objList []runtime.Object) objectCollection { - result := objectCollection{} +func (o *desiredSet) collect(objList []runtime.Object) objectset.ObjectByGVK { + result := objectset.ObjectByGVK{} for _, obj := range objList { - result.add(obj) + result.Add(obj) } return result } -func (o *DesiredSet) runInjectors(objList []runtime.Object) ([]runtime.Object, error) { +func (o *desiredSet) runInjectors(objList []runtime.Object) ([]runtime.Object, error) { var err error for _, inj := range o.injectors { @@ -201,10 +144,22 @@ func (o *DesiredSet) runInjectors(objList []runtime.Object) ([]runtime.Object, e } } + for _, name := range o.injectorNames { + inj := injectors.Get(name) + if inj == nil { + continue + } + + objList, err = inj(objList) + if err != nil { + return nil, err + } + } + return objList, nil } -func (o *DesiredSet) getLabelsAndAnnotations() (map[string]string, map[string]string, error) { +func (o *desiredSet) getLabelsAndAnnotations() (map[string]string, map[string]string, error) { annotations := map[string]string{ LabelID: o.setID, } @@ -226,10 +181,10 @@ func (o *DesiredSet) getLabelsAndAnnotations() (map[string]string, map[string]st return labels, annotations, nil } -func (o *DesiredSet) injectLabelsAndAnnotations(labels, annotations map[string]string) ([]runtime.Object, error) { +func (o *desiredSet) injectLabelsAndAnnotations(labels, annotations map[string]string) ([]runtime.Object, error) { var result []runtime.Object - for _, objMap := range o.objs.objects { + for _, objMap := range o.objs.ObjectsByGVK() { for key, obj := range objMap { obj = obj.DeepCopyObject() meta, err := meta.Accessor(obj) @@ -252,7 +207,6 @@ func setAnnotations(meta metav1.Object, annotations map[string]string) { if objAnn == nil { objAnn = map[string]string{} } - delete(objAnn, LabelInputID) delete(objAnn, LabelApplied) for k, v := range annotations { objAnn[k] = v diff --git a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_compare.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go similarity index 78% rename from vendor/github.com/rancher/norman/pkg/objectset/desiredset_compare.go rename to vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go index de5082dda2..0dca721fcc 100644 --- a/vendor/github.com/rancher/norman/pkg/objectset/desiredset_compare.go +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_compare.go @@ -1,4 +1,4 @@ -package objectset +package apply import ( "bytes" @@ -8,11 +8,9 @@ import ( "sync" "github.com/pkg/errors" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/types/convert" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/meta" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "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" @@ -20,12 +18,12 @@ import ( "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/jsonmergepatch" "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes/scheme" ) const ( LabelApplied = "objectset.rio.cattle.io/applied" - LabelInputID = "objectset.rio.cattle.io/inputid" ) var ( @@ -38,7 +36,7 @@ type patchCacheEntry struct { lookup strategicpatch.LookupPatchMeta } -func prepareObjectForCreate(inputID string, obj runtime.Object) (runtime.Object, error) { +func prepareObjectForCreate(obj runtime.Object) (runtime.Object, error) { serialized, err := json.Marshal(obj) if err != nil { return nil, err @@ -54,20 +52,19 @@ func prepareObjectForCreate(inputID string, obj runtime.Object) (runtime.Object, annotations = map[string]string{} } - annotations[LabelInputID] = inputID annotations[LabelApplied] = appliedToAnnotation(serialized) meta.SetAnnotations(annotations) return obj, nil } -func originalAndModifiedForInputID(inputID string, oldMetadata v1.Object, newObject runtime.Object) ([]byte, []byte, error) { - original, err := getOriginal(inputID, oldMetadata) +func originalAndModified(oldMetadata v1.Object, newObject runtime.Object) ([]byte, []byte, error) { + original, err := getOriginal(oldMetadata) if err != nil { return nil, nil, err } - newObject, err = prepareObjectForCreate(inputID, newObject) + newObject, err = prepareObjectForCreate(newObject) if err != nil { return nil, nil, err } @@ -77,27 +74,26 @@ func originalAndModifiedForInputID(inputID string, oldMetadata v1.Object, newObj return original, modified, err } -func onlyKeys(data map[string]interface{}, keys ...string) bool { - for i, key := range keys { - if len(data) > 1 { - return false - } else if len(data) == 0 { +func emptyMaps(data map[string]interface{}, keys ...string) bool { + for _, key := range append(keys, "__invalid_key__") { + if len(data) == 0 { + // map is empty so all children are empty too return true + } else if len(data) > 1 { + // map has more than one key so not empty + return false } value, ok := data[key] if !ok { + // map has one key but not what we are expecting so not considered empty return false } - if i == len(keys)-1 { - return true - } - - data = convert.ToMapInterface(value) + data = toMapInterface(value) } - return false + return true } func sanitizePatch(patch []byte) ([]byte, error) { @@ -122,7 +118,7 @@ func sanitizePatch(patch []byte) ([]byte, error) { mod = true } - if onlyKeys(data, "metadata", "annotations", LabelInputID) { + if emptyMaps(data, "metadata", "annotations") { return []byte("{}"), nil } @@ -133,15 +129,13 @@ func sanitizePatch(patch []byte) ([]byte, error) { return json.Marshal(data) } -func applyPatch(patcher Patcher, client objectclient.GenericClient, debugID, inputID string, oldObject, newObject runtime.Object) (bool, error) { - gvk := client.GroupVersionKind() - +func applyPatch(gvk schema.GroupVersionKind, patcher Patcher, debugID string, oldObject, newObject runtime.Object) (bool, error) { oldMetadata, err := meta.Accessor(oldObject) if err != nil { return false, err } - original, modified, err := originalAndModifiedForInputID(inputID, oldMetadata, newObject) + original, modified, err := originalAndModified(oldMetadata, newObject) if err != nil { return false, err } @@ -173,19 +167,18 @@ func applyPatch(patcher Patcher, client objectclient.GenericClient, debugID, inp patch, original, modified, current) logrus.Debugf("DesiredSet - Updated %s %s/%s for %s -- %s %s", gvk, oldMetadata.GetNamespace(), oldMetadata.GetName(), debugID, patchType, patch) - _, err = patcher(oldMetadata.GetName(), oldObject, patchType, patch) + _, err = patcher(oldMetadata.GetNamespace(), oldMetadata.GetName(), patchType, patch) return true, err } -func (o *DesiredSet) compareObjects(patcher Patcher, client objectclient.GenericClient, debugID, inputID string, oldObject, newObject runtime.Object, force bool) error { +func (o *desiredSet) compareObjects(gvk schema.GroupVersionKind, patcher Patcher, client dynamic.NamespaceableResourceInterface, debugID string, oldObject, newObject runtime.Object, force bool) error { oldMetadata, err := meta.Accessor(oldObject) if err != nil { return err } - gvk := client.GroupVersionKind() - if ran, err := applyPatch(patcher, client, debugID, inputID, oldObject, newObject); err != nil { + if ran, err := applyPatch(gvk, patcher, debugID, oldObject, newObject); err != nil { return err } else if !ran { logrus.Debugf("DesiredSet - No change(2) %s %s/%s for %s", gvk, oldMetadata.GetNamespace(), oldMetadata.GetName(), debugID) @@ -200,7 +193,7 @@ func removeCreationTimestamp(data map[string]interface{}) bool { return false } - data = convert.ToMapInterface(metadata) + data = toMapInterface(metadata) if _, ok := data["creationTimestamp"]; ok { delete(data, "creationTimestamp") return true @@ -209,7 +202,7 @@ func removeCreationTimestamp(data map[string]interface{}) bool { return false } -func getOriginal(inputID string, obj v1.Object) ([]byte, error) { +func getOriginal(obj v1.Object) ([]byte, error) { original := appliedFromAnnotation(obj.GetAnnotations()[LabelApplied]) if len(original) == 0 { return []byte("{}"), nil @@ -223,7 +216,7 @@ func getOriginal(inputID string, obj v1.Object) ([]byte, error) { removeCreationTimestamp(mapObj.Object) - objCopy, err := prepareObjectForCreate(inputID, mapObj) + objCopy, err := prepareObjectForCreate(mapObj) if err != nil { return nil, err } @@ -330,3 +323,8 @@ func getPatchStyle(gvk schema.GroupVersionKind) (types.PatchType, strategicpatch return patchType, lookupPatchMeta, nil } + +func toMapInterface(obj interface{}) map[string]interface{} { + v, _ := obj.(map[string]interface{}) + return v +} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go new file mode 100644 index 0000000000..fe91a4a566 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_crud.go @@ -0,0 +1,66 @@ +package apply + +import ( + "bytes" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/json" + "k8s.io/client-go/dynamic" +) + +var ( + deletePolicy = v1.DeletePropagationBackground +) + +func (o *desiredSet) toUnstructured(obj runtime.Object) (*unstructured.Unstructured, error) { + unstruct, ok := obj.(*unstructured.Unstructured) + if ok { + return unstruct, nil + } + + buf := &bytes.Buffer{} + if err := json.NewEncoder(buf).Encode(obj); err != nil { + return nil, err + } + + unstruct = &unstructured.Unstructured{ + Object: map[string]interface{}{}, + } + + return unstruct, json.Unmarshal(buf.Bytes(), &unstruct.Object) +} + +func (o *desiredSet) create(nsed bool, namespace string, client dynamic.NamespaceableResourceInterface, obj runtime.Object) (runtime.Object, error) { + unstr, err := o.toUnstructured(obj) + if err != nil { + return nil, err + } + + if nsed { + return client.Namespace(namespace).Create(unstr, v1.CreateOptions{}) + } + return client.Create(unstr, v1.CreateOptions{}) +} + +func (o *desiredSet) get(nsed bool, namespace, name string, client dynamic.NamespaceableResourceInterface) (runtime.Object, error) { + if nsed { + return client.Namespace(namespace).Get(name, v1.GetOptions{}) + } + return client.Get(name, v1.GetOptions{}) +} + +func (o *desiredSet) delete(nsed bool, namespace, name string, client dynamic.NamespaceableResourceInterface) error { + if o.noDelete { + return nil + } + opts := &v1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + } + if nsed { + return client.Namespace(namespace).Delete(name, opts) + } + + return client.Delete(name, opts) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go new file mode 100644 index 0000000000..20206ed790 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/apply/desiredset_process.go @@ -0,0 +1,238 @@ +package apply + +import ( + "fmt" + "sort" + + "github.com/pkg/errors" + "github.com/rancher/wrangler/pkg/merr" + "github.com/rancher/wrangler/pkg/objectset" + "github.com/sirupsen/logrus" + errors2 "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + types2 "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/tools/cache" +) + +var ( + ErrReplace = errors.New("replace object with changes") + ReplaceOnChange = func(name string, o runtime.Object, patchType types2.PatchType, data []byte, subresources ...string) (runtime.Object, error) { + return nil, ErrReplace + } +) + +func (o *desiredSet) getControllerAndClient(debugID string, gvk schema.GroupVersionKind) (cache.SharedIndexInformer, dynamic.NamespaceableResourceInterface, error) { + informer, ok := o.pruneTypes[gvk] + if !ok { + informer = o.a.informers[gvk] + } + if informer == nil && o.strictCaching { + return nil, nil, fmt.Errorf("failed to find informer for %s for %s", gvk, debugID) + } + + client, err := o.a.clients.client(gvk) + if err != nil { + return nil, nil, err + } + + return informer, client, nil +} + +func (o *desiredSet) adjustNamespace(gvk schema.GroupVersionKind, objs map[objectset.ObjectKey]runtime.Object) error { + for k, v := range objs { + if k.Namespace != "" { + continue + } + + v = v.DeepCopyObject() + meta, err := meta.Accessor(v) + if err != nil { + return err + } + + meta.SetNamespace(o.defaultNamespace) + + delete(objs, k) + k.Namespace = o.defaultNamespace + objs[k] = v + } + + return nil +} + +func (o *desiredSet) createPatcher(client dynamic.NamespaceableResourceInterface) Patcher { + return func(namespace, name string, pt types2.PatchType, data []byte) (object runtime.Object, e error) { + if namespace != "" { + return client.Namespace(namespace).Patch(name, pt, data, v1.PatchOptions{}) + } + return client.Patch(name, pt, data, v1.PatchOptions{}) + } +} + +func (o *desiredSet) process(debugID string, set labels.Selector, gvk schema.GroupVersionKind, objs map[objectset.ObjectKey]runtime.Object) { + controller, client, err := o.getControllerAndClient(debugID, gvk) + if err != nil { + o.err(err) + return + } + + nsed := o.a.clients.IsNamespaced(gvk) + + if nsed { + if err := o.adjustNamespace(gvk, objs); err != nil { + o.err(err) + return + } + } + + patcher, ok := o.patchers[gvk] + if !ok { + patcher = o.createPatcher(client) + } + + existing, err := list(controller, client, set) + if err != nil { + o.err(fmt.Errorf("failed to list %s for %s", gvk, debugID)) + return + } + + toCreate, toDelete, toUpdate := compareSets(existing, objs) + + createF := func(k objectset.ObjectKey) { + obj := objs[k] + obj, err := prepareObjectForCreate(obj) + if err != nil { + o.err(errors.Wrapf(err, "failed to prepare create %s %s for %s", k, gvk, debugID)) + return + } + + _, err = o.create(nsed, k.Namespace, client, obj) + if errors2.IsAlreadyExists(err) { + // Taking over an object that wasn't previously managed by us + existingObj, err := o.get(nsed, k.Namespace, k.Name, client) + if err == nil { + toUpdate = append(toUpdate, k) + existing[k] = existingObj + return + } + } + if err != nil { + o.err(errors.Wrapf(err, "failed to create %s %s for %s", k, gvk, debugID)) + return + } + logrus.Debugf("DesiredSet - Created %s %s for %s", gvk, k, debugID) + } + + deleteF := func(k objectset.ObjectKey) { + if err := o.delete(nsed, k.Namespace, k.Name, client); err != nil { + o.err(errors.Wrapf(err, "failed to delete %s %s for %s", k, gvk, debugID)) + return + } + logrus.Debugf("DesiredSet - Delete %s %s for %s", gvk, k, debugID) + } + + updateF := func(k objectset.ObjectKey) { + err := o.compareObjects(gvk, patcher, client, debugID, existing[k], objs[k], len(toCreate) > 0 || len(toDelete) > 0) + if err == ErrReplace { + deleteF(k) + o.err(fmt.Errorf("DesiredSet - Replace Wait %s %s for %s", gvk, k, debugID)) + } else if err != nil { + o.err(errors.Wrapf(err, "failed to update %s %s for %s", k, gvk, debugID)) + } + } + + for _, k := range toCreate { + createF(k) + } + + for _, k := range toUpdate { + updateF(k) + } + + for _, k := range toDelete { + deleteF(k) + } +} + +func compareSets(existingSet, newSet map[objectset.ObjectKey]runtime.Object) (toCreate, toDelete, toUpdate []objectset.ObjectKey) { + for k := range newSet { + if _, ok := existingSet[k]; ok { + toUpdate = append(toUpdate, k) + } else { + toCreate = append(toCreate, k) + } + } + + for k := range existingSet { + if _, ok := newSet[k]; !ok { + toDelete = append(toDelete, k) + } + } + + sortObjectKeys(toCreate) + sortObjectKeys(toDelete) + sortObjectKeys(toUpdate) + + return +} + +func sortObjectKeys(keys []objectset.ObjectKey) { + sort.Slice(keys, func(i, j int) bool { + return keys[i].String() < keys[j].String() + }) +} + +func addObjectToMap(objs map[objectset.ObjectKey]runtime.Object, obj interface{}) error { + metadata, err := meta.Accessor(obj) + if err != nil { + return err + } + + objs[objectset.ObjectKey{ + Namespace: metadata.GetNamespace(), + Name: metadata.GetName(), + }] = obj.(runtime.Object) + + return nil +} + +func list(informer cache.SharedIndexInformer, client dynamic.NamespaceableResourceInterface, selector labels.Selector) (map[objectset.ObjectKey]runtime.Object, error) { + var ( + errs []error + objs = map[objectset.ObjectKey]runtime.Object{} + ) + + if informer == nil { + list, err := client.List(v1.ListOptions{ + LabelSelector: selector.String(), + }) + if err != nil { + return nil, err + } + + for _, obj := range list.Items { + copy := obj + if err := addObjectToMap(objs, ©); err != nil { + errs = append(errs, err) + } + } + + return objs, merr.NewErrors(errs...) + } + + err := cache.ListAllByNamespace(informer.GetIndexer(), "", selector, func(obj interface{}) { + if err := addObjectToMap(objs, obj); err != nil { + errs = append(errs, err) + } + }) + if err != nil { + errs = append(errs, err) + } + + return objs, merr.NewErrors(errs...) +} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/injectors/registry.go b/vendor/github.com/rancher/wrangler/pkg/apply/injectors/registry.go similarity index 100% rename from vendor/github.com/rancher/norman/pkg/objectset/injectors/registry.go rename to vendor/github.com/rancher/wrangler/pkg/apply/injectors/registry.go diff --git a/vendor/github.com/rancher/norman/generator/cleanup/cleanup.go b/vendor/github.com/rancher/wrangler/pkg/cleanup/cleanup.go similarity index 100% rename from vendor/github.com/rancher/norman/generator/cleanup/cleanup.go rename to vendor/github.com/rancher/wrangler/pkg/cleanup/cleanup.go diff --git a/vendor/github.com/rancher/norman/condition/condition.go b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go similarity index 55% rename from vendor/github.com/rancher/norman/condition/condition.go rename to vendor/github.com/rancher/wrangler/pkg/condition/condition.go index 49dafb10d4..dbf9471554 100644 --- a/vendor/github.com/rancher/norman/condition/condition.go +++ b/vendor/github.com/rancher/wrangler/pkg/condition/condition.go @@ -2,21 +2,59 @@ package condition import ( "reflect" - "regexp" "time" "github.com/pkg/errors" - "github.com/rancher/norman/controller" - "github.com/rancher/norman/objectclient" - "k8s.io/api/core/v1" - err2 "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ) type Cond string -var temfileRegexp = regexp.MustCompile("/tmp/[-_a-zA-Z0-9]+") +func (c Cond) GetStatus(obj runtime.Object) string { + return getStatus(obj, string(c)) +} + +func (c Cond) SetError(obj runtime.Object, reason string, err error) { + if err == nil { + c.True(obj) + c.Message(obj, "") + c.Reason(obj, reason) + return + } + if reason == "" { + reason = "Error" + } + c.False(obj) + c.Message(obj, err.Error()) + c.Reason(obj, reason) +} + +func (c Cond) MatchesError(obj runtime.Object, reason string, err error) bool { + if err == nil { + return c.IsTrue(obj) && + c.GetMessage(obj) == "" && + c.GetReason(obj) == reason + } + if reason == "" { + reason = "Error" + } + return c.IsFalse(obj) && + c.GetMessage(obj) == err.Error() && + c.GetReason(obj) == reason +} + +func (c Cond) SetStatus(obj runtime.Object, status string) { + setStatus(obj, string(c), status) +} + +func (c Cond) SetStatusBool(obj runtime.Object, val bool) { + if val { + setStatus(obj, string(c), "True") + } else { + setStatus(obj, string(c), "False") + } +} func (c Cond) True(obj runtime.Object) { setStatus(obj, string(c), "True") @@ -26,14 +64,6 @@ func (c Cond) IsTrue(obj runtime.Object) bool { return getStatus(obj, string(c)) == "True" } -func (c Cond) LastUpdated(obj runtime.Object, ts string) { - setTS(obj, string(c), ts) -} - -func (c Cond) GetLastUpdated(obj runtime.Object) string { - return getTS(obj, string(c)) -} - func (c Cond) False(obj runtime.Object) { setStatus(obj, string(c), "False") } @@ -42,18 +72,22 @@ func (c Cond) IsFalse(obj runtime.Object) bool { return getStatus(obj, string(c)) == "False" } -func (c Cond) GetStatus(obj runtime.Object) string { - return getStatus(obj, string(c)) -} - -func (c Cond) SetStatus(obj runtime.Object, status string) { - setStatus(obj, string(c), status) -} - func (c Cond) Unknown(obj runtime.Object) { setStatus(obj, string(c), "Unknown") } +func (c Cond) IsUnknown(obj runtime.Object) bool { + return getStatus(obj, string(c)) == "Unknown" +} + +func (c Cond) LastUpdated(obj runtime.Object, ts string) { + setTS(obj, string(c), ts) +} + +func (c Cond) GetLastUpdated(obj runtime.Object) string { + return getTS(obj, string(c)) +} + func (c Cond) CreateUnknownIfNotExists(obj runtime.Object) { condSlice := getValue(obj, "Status", "Conditions") cond := findCond(condSlice, string(c)) @@ -62,15 +96,19 @@ func (c Cond) CreateUnknownIfNotExists(obj runtime.Object) { } } -func (c Cond) IsUnknown(obj runtime.Object) bool { - return getStatus(obj, string(c)) == "Unknown" -} - func (c Cond) Reason(obj runtime.Object, reason string) { cond := findOrCreateCond(obj, string(c)) getFieldValue(cond, "Reason").SetString(reason) } +func (c Cond) GetReason(obj runtime.Object) string { + cond := findOrNotCreateCond(obj, string(c)) + if cond == nil { + return "" + } + return getFieldValue(*cond, "Reason").String() +} + func (c Cond) SetMessageIfBlank(obj runtime.Object, message string) { if c.GetMessage(obj) == "" { c.Message(obj, message) @@ -90,148 +128,49 @@ func (c Cond) GetMessage(obj runtime.Object) string { return getFieldValue(*cond, "Message").String() } -func (c Cond) ReasonAndMessageFromError(obj runtime.Object, err error) { - if err2.IsConflict(err) { - return - } - cond := findOrCreateCond(obj, string(c)) - setValue(cond, "Message", err.Error()) - switch ce := err.(type) { - case *conditionError: - setValue(cond, "Reason", ce.reason) - case *controller.ForgetError: - if ce.Reason != "" { - setValue(cond, "Reason", ce.Reason) - } else { - setValue(cond, "Reason", "Error") - } - default: - setValue(cond, "Reason", "Error") - } -} - -func (c Cond) GetReason(obj runtime.Object) string { - cond := findOrNotCreateCond(obj, string(c)) - if cond == nil { - return "" - } - return getFieldValue(*cond, "Reason").String() -} - -func (c Cond) Once(obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) { +func (c Cond) Once(obj runtime.Object, f func() (runtime.Object, error)) error { if c.IsFalse(obj) { - return obj, &controller.ForgetError{ - Err: errors.New(c.GetReason(obj)), - } + return errors.New(c.GetReason(obj)) } return c.DoUntilTrue(obj, f) } -func (c Cond) DoUntilTrue(obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) { +func (c Cond) DoUntilTrue(obj runtime.Object, f func() (runtime.Object, error)) error { if c.IsTrue(obj) { - return obj, nil + return nil } - return c.do(obj, f) + return c.Do(f) } -func (c Cond) Do(obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) { - return c.do(obj, f) +func messageAndReason(err error) (string, string) { + if err == nil { + return "", "" + } + + switch ce := err.(type) { + case *conditionError: + return err.Error(), ce.reason + default: + return err.Error(), "Error" + } } -type ObjectClientGetter interface { - ObjectClient() *objectclient.ObjectClient -} +func (c Cond) Do(f func() (runtime.Object, error)) error { + obj, err := f() -func (c Cond) Track(obj runtime.Object, client ObjectClientGetter, f func() (runtime.Object, error)) (runtime.Object, error) { - obj = obj.DeepCopyObject() - retObj, changed, err := c.do2(false, obj, f) - if !changed { - return retObj, err + if apierrors.IsConflict(err) { + // Don't update condition state on conflicts + return err } - c.SetStatus(retObj, c.GetStatus(obj)) - c.LastUpdated(retObj, c.GetLastUpdated(obj)) - c.Reason(retObj, c.GetReason(obj)) - c.Message(retObj, c.GetMessage(obj)) + message, reason := messageAndReason(err) + c.SetStatusBool(obj, err == nil) + c.Message(obj, message) + c.Reason(obj, reason) - if obj, ok := retObj.(metav1.Object); ok { - updated, uerr := client.ObjectClient().Update(obj.GetName(), retObj) - if uerr == nil { - return updated, err - } - } - - return retObj, err -} - -func (c Cond) do(obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) { - obj, _, err := c.do2(true, obj, f) - return obj, err -} - -func (c Cond) do2(setReturned bool, obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, bool, error) { - status := c.GetStatus(obj) - ts := c.GetLastUpdated(obj) - reason := c.GetReason(obj) - message := c.GetMessage(obj) - - checkObj := obj - retObj, err := c.doInternal(setReturned, obj, f) - if setReturned { - checkObj = retObj - } - - // This is to prevent non stop flapping of states and update - if status == c.GetStatus(checkObj) && - reason == c.GetReason(checkObj) { - if message != c.GetMessage(checkObj) { - replaced := temfileRegexp.ReplaceAllString(c.GetMessage(checkObj), "file_path_redacted") - c.Message(checkObj, replaced) - } - if message == c.GetMessage(checkObj) { - c.LastUpdated(checkObj, ts) - } - } - - changed := status != c.GetStatus(checkObj) || - ts != c.GetLastUpdated(checkObj) || - reason != c.GetReason(checkObj) || - message != c.GetMessage(checkObj) - - return retObj, changed, err -} - -func (c Cond) doInternal(setReturned bool, obj runtime.Object, f func() (runtime.Object, error)) (runtime.Object, error) { - if !c.IsFalse(obj) { - c.Unknown(obj) - } - - setObject := obj - newObj, err := f() - if newObj != nil && !reflect.ValueOf(newObj).IsNil() { - obj = newObj - if setReturned { - setObject = obj - } - } - - if err != nil { - if _, ok := err.(*controller.ForgetError); ok { - if c.GetMessage(setObject) == "" { - c.ReasonAndMessageFromError(setObject, err) - } - return obj, err - } - c.False(setObject) - c.ReasonAndMessageFromError(setObject, err) - return obj, err - } - c.True(setObject) - c.Reason(setObject, "") - c.Message(setObject, "") - return obj, nil + return err } func touchTS(value reflect.Value) { @@ -345,18 +284,3 @@ type conditionError struct { func (e *conditionError) Error() string { return e.message } - -type GenericCondition struct { - // Type of cluster condition. - Type string `json:"type"` - // Status of the condition, one of True, False, Unknown. - Status v1.ConditionStatus `json:"status"` - // The last time this condition was updated. - LastUpdateTime string `json:"lastUpdateTime,omitempty"` - // Last time the condition transitioned from one status to another. - LastTransitionTime string `json:"lastTransitionTime,omitempty"` - // The reason for the condition's last transition. - Reason string `json:"reason,omitempty"` - // Human-readable message indicating details about last transition - Message string `json:"message,omitempty"` -} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/OWNERS b/vendor/github.com/rancher/wrangler/pkg/controller-gen/OWNERS new file mode 100644 index 0000000000..62866d0b19 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- lavalamp +- wojtek-t +- caesarxuchao +reviewers: +- lavalamp +- wojtek-t +- caesarxuchao diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/README.md b/vendor/github.com/rancher/wrangler/pkg/controller-gen/README.md new file mode 100644 index 0000000000..092a61151c --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/README.md @@ -0,0 +1,4 @@ +See [generating-clientset.md](https://git.k8s.io/community/contributors/devel/sig-api-machinery/generating-clientset.md) + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/staging/src/k8s.io/code-generator/client-gen/README.md?pixel)]() diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/args.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/args.go new file mode 100644 index 0000000000..1fe796a871 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/args.go @@ -0,0 +1,28 @@ +package args + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/types" +) + +type CustomArgs struct { + Package string + TypesByGroup map[schema.GroupVersion][]*types.Name + Options Options + OutputBase string +} + +type Options struct { + OutputPackage string + Groups map[string]Group + Boilerplate string +} + +type Group struct { + Types []interface{} + GenerateTypes bool + PackageName string + ClientSetPackage string + ListersPackage string + InformersPackage string +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/groupversion.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/groupversion.go new file mode 100644 index 0000000000..becf16f929 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/args/groupversion.go @@ -0,0 +1,60 @@ +package args + +import ( + "reflect" + "strings" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/code-generator/cmd/client-gen/path" + "k8s.io/gengo/types" +) + +const ( + needsComment = ` + // +genclient + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + ` + objectComment = "+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object" +) + +func ObjectsToGroupVersion(group string, objs []interface{}, ret map[schema.GroupVersion][]*types.Name) { + for _, obj := range objs { + version, t := toVersionType(obj) + gv := schema.GroupVersion{ + Group: group, + Version: version, + } + ret[gv] = append(ret[gv], t) + } +} + +func toVersionType(obj interface{}) (string, *types.Name) { + t := reflect.TypeOf(obj) + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + pkg := path.Vendorless(t.PkgPath()) + parts := strings.Split(pkg, "/") + return parts[len(parts)-1], &types.Name{ + Package: pkg, + Name: t.Name(), + } +} + +func CheckType(passedType *types.Type) { + tags := util.MustParseClientGenTags(passedType.SecondClosestCommentLines) + if !tags.GenerateClient { + panic("Type " + passedType.String() + " is missing comment " + needsComment) + } + found := false + for _, line := range passedType.SecondClosestCommentLines { + if strings.Contains(line, objectComment) { + found = true + } + } + if !found { + panic("Type " + passedType.String() + " is missing comment " + objectComment) + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/client_generator.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/client_generator.go new file mode 100644 index 0000000000..231bf15521 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/client_generator.go @@ -0,0 +1,243 @@ +/* +Copyright 2015 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 generators has the generators for the client-gen utility. +package generators + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "regexp" + "strings" + + "github.com/matryer/moq/pkg/moq" + "github.com/pkg/errors" + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "golang.org/x/tools/imports" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/types" +) + +var ( + underscoreRegexp = regexp.MustCompile(`([a-z])([A-Z])`) + goImportOpts = &imports.Options{ + TabWidth: 8, + TabIndent: true, + Comments: true, + Fragment: true, + } +) + +type ClientGenerator struct { + Fakes map[string][]string +} + +func NewClientGenerator() *ClientGenerator { + return &ClientGenerator{ + Fakes: make(map[string][]string), + } +} + +// Packages makes the client package definition. +func (cg *ClientGenerator) Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + customArgs := arguments.CustomArgs.(*args2.CustomArgs) + generateTypesGroups := map[string]bool{} + + for groupName, group := range customArgs.Options.Groups { + if group.GenerateTypes { + generateTypesGroups[groupName] = true + } + } + + var ( + packageList []generator.Package + groups = map[string]bool{} + ) + + for gv, types := range customArgs.TypesByGroup { + if !groups[gv.Group] { + packageList = append(packageList, cg.groupPackage(gv.Group, arguments, customArgs)) + if generateTypesGroups[gv.Group] { + packageList = append(packageList, cg.typesGroupPackage(types[0], gv, arguments, customArgs)) + } + } + groups[gv.Group] = true + packageList = append(packageList, cg.groupVersionPackage(gv, arguments, customArgs)) + + if generateTypesGroups[gv.Group] { + packageList = append(packageList, cg.typesGroupVersionPackage(types[0], gv, arguments, customArgs)) + packageList = append(packageList, cg.typesGroupVersionDocPackage(types[0], gv, arguments, customArgs)) + } + } + + return generator.Packages(packageList) +} + +func (cg *ClientGenerator) typesGroupPackage(name *types.Name, gv schema.GroupVersion, generatorArgs *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Package { + packagePath := strings.TrimRight(name.Package, "/"+gv.Version) + return Package(generatorArgs, packagePath, func(context *generator.Context) []generator.Generator { + return []generator.Generator{ + RegisterGroupGo(gv.Group, generatorArgs, customArgs), + } + }) +} + +func (cg *ClientGenerator) typesGroupVersionDocPackage(name *types.Name, gv schema.GroupVersion, generatorArgs *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Package { + packagePath := name.Package + p := Package(generatorArgs, packagePath, func(context *generator.Context) []generator.Generator { + return []generator.Generator{ + generator.DefaultGen{ + OptionalName: "doc", + }, + RegisterGroupVersionGo(gv, generatorArgs, customArgs), + ListTypesGo(gv, generatorArgs, customArgs), + } + }) + + p.(*generator.DefaultPackage).HeaderText = append(p.(*generator.DefaultPackage).HeaderText, []byte(fmt.Sprintf(` + +// +k8s:deepcopy-gen=package +// +groupName=%s +`, gv.Group))...) + + return p +} + +func (cg *ClientGenerator) typesGroupVersionPackage(name *types.Name, gv schema.GroupVersion, generatorArgs *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Package { + packagePath := name.Package + return Package(generatorArgs, packagePath, func(context *generator.Context) []generator.Generator { + return []generator.Generator{ + RegisterGroupVersionGo(gv, generatorArgs, customArgs), + ListTypesGo(gv, generatorArgs, customArgs), + } + }) +} + +func (cg *ClientGenerator) groupPackage(group string, generatorArgs *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Package { + packagePath := filepath.Join(customArgs.Package, "controllers", groupPackageName(group, "")) + return Package(generatorArgs, packagePath, func(context *generator.Context) []generator.Generator { + return []generator.Generator{ + FactoryGo(group, generatorArgs, customArgs), + GroupInterfaceGo(group, generatorArgs, customArgs), + } + }) +} + +func (cg *ClientGenerator) groupVersionPackage(gv schema.GroupVersion, generatorArgs *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Package { + packagePath := filepath.Join(customArgs.Package, "controllers", groupPackageName(gv.Group, ""), gv.Version) + + return Package(generatorArgs, packagePath, func(context *generator.Context) []generator.Generator { + generators := []generator.Generator{ + GroupVersionInterfaceGo(gv, generatorArgs, customArgs), + } + + for _, t := range customArgs.TypesByGroup[gv] { + generators = append(generators, TypeGo(gv, t, generatorArgs, customArgs)) + cg.Fakes[packagePath] = append(cg.Fakes[packagePath], t.Name) + } + + return generators + }) +} + +func removePackage(pkg string) string { + pkgSplit := strings.Split(pkg, string(os.PathSeparator)) + return strings.Join(pkgSplit[3:], string(os.PathSeparator)) +} + +func (cg *ClientGenerator) GenerateMocks() error { + base := args.DefaultSourceTree() + + for packagePath, resources := range cg.Fakes { + if base == "./" { + packagePath = removePackage(packagePath) + } + genPath := path.Join(base, packagePath) + + // Clean the fakes dir + err := cleanMockDir(genPath) + if err != nil { + return err + } + + m, err := moq.New(genPath, "fakes") + if err != nil { + return err + } + + for _, resource := range resources { + var out bytes.Buffer + + interfaces := []string{ + resource + "Controller", + resource + "Client", + resource + "Cache", + } + + err = m.Mock(&out, interfaces...) + if err != nil { + return err + } + + filePath := path.Join(genPath, "fakes", "zz_generated_"+addUnderscore(resource)+"_mock.go") + + // format imports - moq only uses gofmt which does not do imports + res, err := imports.Process(filePath, out.Bytes(), goImportOpts) + if err != nil { + return err + } + + // create the file + err = ioutil.WriteFile(filePath, res, 0644) + if err != nil { + return err + } + } + } + return nil +} + +func addUnderscore(input string) string { + return strings.ToLower(underscoreRegexp.ReplaceAllString(input, `${1}_${2}`)) +} + +func cleanMockDir(dir string) error { + dir = path.Join(dir, "fakes") + files, err := ioutil.ReadDir(dir) + if err != nil { + // if the directory doesn't exist there is nothing to do + if !os.IsNotExist(err) { + return err + } + return nil + } + + for _, file := range files { + if strings.HasSuffix(file.Name(), "_mock.go") || strings.HasSuffix(file.Name(), "_mock_test.go") { + if err := os.Remove(path.Join(dir, file.Name())); err != nil { + return errors.Wrapf(err, "failed to delete %s", path.Join(dir, file.Name())) + } + } + } + + return nil +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/factory_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/factory_go.go new file mode 100644 index 0000000000..22a2c664c8 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/factory_go.go @@ -0,0 +1,132 @@ +package generators + +import ( + "fmt" + "io" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" +) + +func FactoryGo(group string, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return &factory{ + group: group, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "factory", + OptionalBody: []byte(factoryBody), + }, + } +} + +type factory struct { + generator.DefaultGen + + group string + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *factory) Imports(*generator.Context) []string { + group := f.customArgs.Options.Groups[f.group] + + return []string{ + "context", + "time", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/client-go/rest", + GenericPackage, + fmt.Sprintf("clientset \"%s\"", group.ClientSetPackage), + fmt.Sprintf("informers \"%s\"", group.InformersPackage), + } +} + +func (f *factory) Init(c *generator.Context, w io.Writer) error { + if err := f.DefaultGen.Init(c, w); err != nil { + return err + } + + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + m := map[string]interface{}{ + "groupName": upperLowercase(f.group), + } + + sw.Do("func (c *Factory) {{.groupName}}() Interface {\n", m) + sw.Do(" return New(c.controllerManager, c.informerFactory.{{.groupName}}(), c.clientset)\n", m) + sw.Do("}\n", m) + + return sw.Error() +} + +var factoryBody = ` +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_interface_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_interface_go.go new file mode 100644 index 0000000000..77d4120afa --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_interface_go.go @@ -0,0 +1,106 @@ +package generators + +import ( + "fmt" + "io" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" +) + +func GroupInterfaceGo(group string, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return &interfaceGo{ + group: group, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "interface", + OptionalBody: []byte(interfaceBody), + }, + } +} + +type interfaceGo struct { + generator.DefaultGen + + group string + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *interfaceGo) Imports(*generator.Context) []string { + group := f.customArgs.Options.Groups[f.group] + + packages := []string{ + GenericPackage, + fmt.Sprintf("clientset \"%s\"", group.ClientSetPackage), + fmt.Sprintf("informers \"%s/%s\"", group.InformersPackage, groupPackageName(f.group, group.PackageName)), + } + + for gv := range f.customArgs.TypesByGroup { + if gv.Group != f.group { + continue + } + + packages = append(packages, fmt.Sprintf("%s \"%s/controllers/%s/%s\"", gv.Version, f.customArgs.Package, groupPackageName(gv.Group, ""), gv.Version)) + } + + return packages +} + +func (f *interfaceGo) Init(c *generator.Context, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + sw.Do("type Interface interface {\n", nil) + for gv := range f.customArgs.TypesByGroup { + if gv.Group != f.group { + continue + } + + sw.Do("{{.upperVersion}}() {{.version}}.Interface\n", map[string]interface{}{ + "upperVersion": namer.IC(gv.Version), + "version": gv.Version, + }) + } + sw.Do("}\n", nil) + + if err := f.DefaultGen.Init(c, w); err != nil { + return err + } + + for gv := range f.customArgs.TypesByGroup { + if gv.Group != f.group { + continue + } + + m := map[string]interface{}{ + "upperGroup": upperLowercase(f.group), + "upperVersion": namer.IC(gv.Version), + "version": gv.Version, + } + sw.Do("\nfunc (g *group) {{.upperVersion}}() {{.version}}.Interface {\n", m) + sw.Do("return {{.version}}.New(g.controllerManager, g.client.{{.upperGroup}}{{.upperVersion}}(), g.informers.{{.upperVersion}}())\n", m) + sw.Do("}\n", m) + } + + return sw.Error() +} + +var interfaceBody = ` +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_version_interface_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_version_interface_go.go new file mode 100644 index 0000000000..379e8d580a --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/group_version_interface_go.go @@ -0,0 +1,115 @@ +package generators + +import ( + "fmt" + "io" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +func GroupVersionInterfaceGo(gv schema.GroupVersion, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return &groupInterfaceGo{ + gv: gv, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "interface", + }, + } +} + +type groupInterfaceGo struct { + generator.DefaultGen + + gv schema.GroupVersion + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *groupInterfaceGo) Imports(*generator.Context) []string { + firstType := f.customArgs.TypesByGroup[f.gv][0] + group := f.customArgs.Options.Groups[f.gv.Group] + + packages := []string{ + GenericPackage, + fmt.Sprintf("%s \"%s\"", f.gv.Version, firstType.Package), + fmt.Sprintf("clientset \"%s/typed/%s/%s\"", group.ClientSetPackage, groupPackageName(f.gv.Group, group.PackageName), f.gv.Version), + fmt.Sprintf("informers \"%s/%s/%s\"", group.InformersPackage, groupPackageName(f.gv.Group, group.PackageName), f.gv.Version), + } + + return packages +} + +var ( + pluralExceptions = map[string]string{ + "Endpoints": "Endpoints", + } + plural = namer.NewPublicPluralNamer(pluralExceptions) +) + +func (f *groupInterfaceGo) Init(c *generator.Context, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} + + var types []*types.Type + for _, name := range f.customArgs.TypesByGroup[f.gv] { + types = append(types, c.Universe.Type(*name)) + } + types = orderer.OrderTypes(types) + + sw.Do("type Interface interface {\n", nil) + for _, t := range types { + m := map[string]interface{}{ + "type": t.Name.Name, + } + sw.Do("{{.type}}() {{.type}}Controller\n", m) + } + sw.Do("}\n", nil) + + m := map[string]interface{}{ + "version": f.gv.Version, + "versionUpper": namer.IC(f.gv.Version), + "groupUpper": upperLowercase(f.gv.Group), + } + sw.Do(groupInterfaceBody, m) + + for _, t := range types { + m := map[string]interface{}{ + "type": t.Name.Name, + "plural": plural.Name(t), + "version": f.gv.Version, + "versionUpper": namer.IC(f.gv.Version), + "groupUpper": upperLowercase(f.gv.Group), + } + + sw.Do("func (c *version) {{.type}}() {{.type}}Controller {\n", m) + sw.Do("return New{{.type}}Controller({{.version}}.SchemeGroupVersion.WithKind(\"{{.type}}\"), c.controllerManager, c.client, c.informers.{{.plural}}())\n", m) + sw.Do("}\n", m) + } + + return sw.Error() +} + +var groupInterfaceBody = ` +func New(controllerManager *generic.ControllerManager, client clientset.{{.groupUpper}}{{.versionUpper}}Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.{{.groupUpper}}{{.versionUpper}}Interface +} + +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/list_type_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/list_type_go.go new file mode 100644 index 0000000000..4968d04ca9 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/list_type_go.go @@ -0,0 +1,70 @@ +package generators + +import ( + "io" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" +) + +func ListTypesGo(gv schema.GroupVersion, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return &listTypesGo{ + gv: gv, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "zz_generated_list_types", + }, + } +} + +type listTypesGo struct { + generator.DefaultGen + + gv schema.GroupVersion + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *listTypesGo) Imports(*generator.Context) []string { + packages := []string{ + "metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"", + } + + return packages +} + +func (f *listTypesGo) Init(c *generator.Context, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + for _, t := range f.customArgs.TypesByGroup[f.gv] { + m := map[string]interface{}{ + "type": t.Name, + } + args2.CheckType(c.Universe.Type(*t)) + sw.Do(string(listTypesBody), m) + } + + return sw.Error() +} + +var listTypesBody = ` +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// {{.type}}List is a list of {{.type}} resources +type {{.type}}List struct { + metav1.TypeMeta ` + "`" + `json:",inline"` + "`" + ` + metav1.ListMeta ` + "`" + `json:"metadata"` + "`" + ` + + Items []{{.type}} ` + "`" + `json:"items"` + "`" + ` +} + +func New{{.type}}(namespace, name string, obj {{.type}}) *{{.type}} { + obj.APIVersion, obj.Kind = SchemeGroupVersion.WithKind("{{.type}}").ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/pkg.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/pkg.go new file mode 100644 index 0000000000..316a8facd5 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/pkg.go @@ -0,0 +1,22 @@ +package generators + +import ( + "strings" + + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" +) + +func Package(arguments *args.GeneratorArgs, name string, generators func(context *generator.Context) []generator.Generator) generator.Package { + boilerplate, err := arguments.LoadGoBoilerplate() + runtime.Must(err) + + parts := strings.Split(name, "/") + return &generator.DefaultPackage{ + PackageName: groupPath(parts[len(parts)-1]), + PackagePath: name, + HeaderText: boilerplate, + GeneratorFunc: generators, + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_go.go new file mode 100644 index 0000000000..89165fa35f --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_go.go @@ -0,0 +1,34 @@ +package generators + +import ( + "fmt" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" +) + +func RegisterGroupGo(group string, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return ®isterGroupGo{ + group: group, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "zz_generated_register", + }, + } +} + +type registerGroupGo struct { + generator.DefaultGen + + group string + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *registerGroupGo) PackageConsts(*generator.Context) []string { + return []string{ + fmt.Sprintf("GroupName = \"%s\"", f.group), + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_version_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_version_go.go new file mode 100644 index 0000000000..623959b3f0 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/register_group_version_go.go @@ -0,0 +1,110 @@ +package generators + +import ( + "fmt" + "io" + "strings" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +func RegisterGroupVersionGo(gv schema.GroupVersion, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return ®isterGroupVersionGo{ + gv: gv, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: "zz_generated_register", + }, + } +} + +type registerGroupVersionGo struct { + generator.DefaultGen + + gv schema.GroupVersion + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *registerGroupVersionGo) Imports(*generator.Context) []string { + firstType := f.customArgs.TypesByGroup[f.gv][0] + typeGroupPath := strings.TrimSuffix(firstType.Package, "/"+f.gv.Version) + + packages := []string{ + "metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/runtime/schema", + fmt.Sprintf("%s \"%s\"", groupPath(f.gv.Group), typeGroupPath), + } + + return packages +} + +func (f *registerGroupVersionGo) Init(c *generator.Context, w io.Writer) error { + var ( + types []*types.Type + orderer = namer.Orderer{Namer: namer.NewPrivateNamer(0)} + sw = generator.NewSnippetWriter(w, c, "{{", "}}") + ) + + for _, name := range f.customArgs.TypesByGroup[f.gv] { + types = append(types, c.Universe.Type(*name)) + } + types = orderer.OrderTypes(types) + + m := map[string]interface{}{ + "version": f.gv.Version, + "groupPath": groupPath(f.gv.Group), + } + sw.Do(registerGroupVersionBody, m) + + for _, t := range types { + m := map[string]interface{}{ + "type": t.Name.Name, + } + + sw.Do("&{{.type}}{},\n", m) + sw.Do("&{{.type}}List{},\n", m) + } + + sw.Do(registerGroupVersionBodyEnd, nil) + + return sw.Error() +} + +var registerGroupVersionBody = ` +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: {{.groupPath}}.GroupName, Version: "{{.version}}"} + +// Kind takes an unqualified kind and returns back 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 = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, +` + +var registerGroupVersionBodyEnd = ` + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go new file mode 100644 index 0000000000..d1d26da1e5 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go @@ -0,0 +1,298 @@ +package generators + +import ( + "fmt" + "io" + "strings" + + args2 "github.com/rancher/wrangler/pkg/controller-gen/args" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/code-generator/cmd/client-gen/generators/util" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +func TypeGo(gv schema.GroupVersion, name *types.Name, args *args.GeneratorArgs, customArgs *args2.CustomArgs) generator.Generator { + return &typeGo{ + name: name, + gv: gv, + args: args, + customArgs: customArgs, + DefaultGen: generator.DefaultGen{ + OptionalName: strings.ToLower(name.Name), + }, + } +} + +type typeGo struct { + generator.DefaultGen + + name *types.Name + gv schema.GroupVersion + args *args.GeneratorArgs + customArgs *args2.CustomArgs +} + +func (f *typeGo) Imports(*generator.Context) []string { + group := f.customArgs.Options.Groups[f.gv.Group] + + packages := []string{ + "metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"", + "k8s.io/apimachinery/pkg/labels", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/apimachinery/pkg/types", + "utilruntime \"k8s.io/apimachinery/pkg/util/runtime\"", + "k8s.io/apimachinery/pkg/watch", + "k8s.io/client-go/tools/cache", + fmt.Sprintf("%s \"%s\"", f.gv.Version, f.name.Package), + GenericPackage, + fmt.Sprintf("clientset \"%s/typed/%s/%s\"", group.ClientSetPackage, groupPackageName(f.gv.Group, group.PackageName), f.gv.Version), + fmt.Sprintf("informers \"%s/%s/%s\"", group.InformersPackage, groupPackageName(f.gv.Group, group.PackageName), f.gv.Version), + fmt.Sprintf("listers \"%s/%s/%s\"", group.ListersPackage, groupPackageName(f.gv.Group, group.PackageName), f.gv.Version), + } + + return packages +} + +func (f *typeGo) Init(c *generator.Context, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + if err := f.DefaultGen.Init(c, w); err != nil { + return err + } + + t := c.Universe.Type(*f.name) + m := map[string]interface{}{ + "type": f.name.Name, + "lowerName": namer.IL(f.name.Name), + "plural": plural.Name(t), + "version": f.gv.Version, + "namespaced": !util.MustParseClientGenTags(t.SecondClosestCommentLines).NonNamespaced, + "hasStatus": hasStatus(t), + } + + sw.Do(string(typeBody), m) + return sw.Error() +} + +func hasStatus(t *types.Type) bool { + for _, m := range t.Members { + if m.Name == "Status" { + return true + } + } + return false +} + +var typeBody = ` +type {{.type}}Handler func(string, *{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) + +type {{.type}}Controller interface { + {{.type}}Client + + OnChange(ctx context.Context, name string, sync {{.type}}Handler) + OnRemove(ctx context.Context, name string, sync {{.type}}Handler) + Enqueue({{ if .namespaced}}namespace, {{end}}name string) + + Cache() {{.type}}Cache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type {{.type}}Client interface { + Create(*{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) + Update(*{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) +{{ if .hasStatus -}} + UpdateStatus(*{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) +{{- end }} + Delete({{ if .namespaced}}namespace, {{end}}name string, options *metav1.DeleteOptions) error + Get({{ if .namespaced}}namespace, {{end}}name string, options metav1.GetOptions) (*{{.version}}.{{.type}}, error) + List({{ if .namespaced}}namespace string, {{end}}opts metav1.ListOptions) (*{{.version}}.{{.type}}List, error) + Watch({{ if .namespaced}}namespace string, {{end}}opts metav1.ListOptions) (watch.Interface, error) + Patch({{ if .namespaced}}namespace, {{end}}name string, pt types.PatchType, data []byte, subresources ...string) (result *{{.version}}.{{.type}}, err error) +} + +type {{.type}}Cache interface { + Get({{ if .namespaced}}namespace, {{end}}name string) (*{{.version}}.{{.type}}, error) + List({{ if .namespaced}}namespace string, {{end}}selector labels.Selector) ([]*{{.version}}.{{.type}}, error) + + AddIndexer(indexName string, indexer {{.type}}Indexer) + GetByIndex(indexName, key string) ([]*{{.version}}.{{.type}}, error) +} + +type {{.type}}Indexer func(obj *{{.version}}.{{.type}}) ([]string, error) + +type {{.lowerName}}Controller struct { + controllerManager *generic.ControllerManager + clientGetter clientset.{{.plural}}Getter + informer informers.{{.type}}Informer + gvk schema.GroupVersionKind +} + +func New{{.type}}Controller(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.{{.plural}}Getter, informer informers.{{.type}}Informer) {{.type}}Controller { + return &{{.lowerName}}Controller{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func From{{.type}}HandlerToHandler(sync {{.type}}Handler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *{{.version}}.{{.type}} + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*{{.version}}.{{.type}})) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *{{.lowerName}}Controller) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*{{.version}}.{{.type}})) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func Update{{.type}}OnChange(updater generic.Updater, handler {{.type}}Handler) {{.type}}Handler { + return func(key string, obj *{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*{{.version}}.{{.type}}) + } + } + + return copyObj, err + } +} + +func (c *{{.lowerName}}Controller) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *{{.lowerName}}Controller) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *{{.lowerName}}Controller) OnChange(ctx context.Context, name string, sync {{.type}}Handler) { + c.AddGenericHandler(ctx, name, From{{.type}}HandlerToHandler(sync)) +} + +func (c *{{.lowerName}}Controller) OnRemove(ctx context.Context, name string, sync {{.type}}Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), From{{.type}}HandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *{{.lowerName}}Controller) Enqueue({{ if .namespaced}}namespace, {{end}}name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), {{ if .namespaced }}namespace, {{else}}"", {{end}}name) +} + +func (c *{{.lowerName}}Controller) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *{{.lowerName}}Controller) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *{{.lowerName}}Controller) Cache() {{.type}}Cache { + return &{{.lowerName}}Cache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *{{.lowerName}}Controller) Create(obj *{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}obj.Namespace{{end}}).Create(obj) +} + +func (c *{{.lowerName}}Controller) Update(obj *{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}obj.Namespace{{end}}).Update(obj) +} + +{{ if .hasStatus -}} +func (c *{{.lowerName}}Controller) UpdateStatus(obj *{{.version}}.{{.type}}) (*{{.version}}.{{.type}}, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}obj.Namespace{{end}}).UpdateStatus(obj) +} +{{- end }} + +func (c *{{.lowerName}}Controller) Delete({{ if .namespaced}}namespace, {{end}}name string, options *metav1.DeleteOptions) error { + return c.clientGetter.{{.plural}}({{ if .namespaced}}namespace{{end}}).Delete(name, options) +} + +func (c *{{.lowerName}}Controller) Get({{ if .namespaced}}namespace, {{end}}name string, options metav1.GetOptions) (*{{.version}}.{{.type}}, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}namespace{{end}}).Get(name, options) +} + +func (c *{{.lowerName}}Controller) List({{ if .namespaced}}namespace string, {{end}}opts metav1.ListOptions) (*{{.version}}.{{.type}}List, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}namespace{{end}}).List(opts) +} + +func (c *{{.lowerName}}Controller) Watch({{ if .namespaced}}namespace string, {{end}}opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}namespace{{end}}).Watch(opts) +} + +func (c *{{.lowerName}}Controller) Patch({{ if .namespaced}}namespace, {{end}}name string, pt types.PatchType, data []byte, subresources ...string) (result *{{.version}}.{{.type}}, err error) { + return c.clientGetter.{{.plural}}({{ if .namespaced}}namespace{{end}}).Patch(name, pt, data, subresources...) +} + +type {{.lowerName}}Cache struct { + lister listers.{{.type}}Lister + indexer cache.Indexer +} + +func (c *{{.lowerName}}Cache) Get({{ if .namespaced}}namespace, {{end}}name string) (*{{.version}}.{{.type}}, error) { + return c.lister.{{ if .namespaced}}{{.plural}}(namespace).{{end}}Get(name) +} + +func (c *{{.lowerName}}Cache) List({{ if .namespaced}}namespace string, {{end}}selector labels.Selector) ([]*{{.version}}.{{.type}}, error) { + return c.lister.{{ if .namespaced}}{{.plural}}(namespace).{{end}}List(selector) +} + +func (c *{{.lowerName}}Cache) AddIndexer(indexName string, indexer {{.type}}Indexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*{{.version}}.{{.type}})) + }, + })) +} + +func (c *{{.lowerName}}Cache) GetByIndex(indexName, key string) (result []*{{.version}}.{{.type}}, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*{{.version}}.{{.type}})) + } + return result, nil +} +` diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/util.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/util.go new file mode 100644 index 0000000000..939414e505 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/util.go @@ -0,0 +1,30 @@ +package generators + +import ( + "strings" + + "k8s.io/gengo/namer" +) + +const ( + GenericPackage = "github.com/rancher/wrangler/pkg/generic" +) + +func groupPath(group string) string { + g := strings.Replace(strings.Split(group, ".")[0], "-", "", -1) + return groupPackageName(g, "") +} + +func groupPackageName(group, groupPackageName string) string { + if groupPackageName != "" { + return groupPackageName + } + if group == "" { + return "core" + } + return group +} + +func upperLowercase(name string) string { + return namer.IC(strings.ToLower(groupPath(name))) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go new file mode 100644 index 0000000000..3b96553a95 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/main.go @@ -0,0 +1,299 @@ +package controllergen + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/sirupsen/logrus" + + cgargs "github.com/rancher/wrangler/pkg/controller-gen/args" + "github.com/rancher/wrangler/pkg/controller-gen/generators" + "k8s.io/apimachinery/pkg/runtime/schema" + csargs "k8s.io/code-generator/cmd/client-gen/args" + clientgenerators "k8s.io/code-generator/cmd/client-gen/generators" + cs "k8s.io/code-generator/cmd/client-gen/generators" + types2 "k8s.io/code-generator/cmd/client-gen/types" + dpargs "k8s.io/code-generator/cmd/deepcopy-gen/args" + infargs "k8s.io/code-generator/cmd/informer-gen/args" + inf "k8s.io/code-generator/cmd/informer-gen/generators" + lsargs "k8s.io/code-generator/cmd/lister-gen/args" + ls "k8s.io/code-generator/cmd/lister-gen/generators" + "k8s.io/gengo/args" + dp "k8s.io/gengo/examples/deepcopy-gen/generators" + "k8s.io/gengo/types" +) + +func Run(opts cgargs.Options) { + customArgs := &cgargs.CustomArgs{ + Options: opts, + TypesByGroup: map[schema.GroupVersion][]*types.Name{}, + Package: opts.OutputPackage, + } + + genericArgs := args.Default().WithoutDefaultFlagParsing() + genericArgs.CustomArgs = customArgs + genericArgs.GoHeaderFilePath = opts.Boilerplate + genericArgs.InputDirs = parseTypes(customArgs) + + if genericArgs.OutputBase == "./" { //go modules + tempDir, err := ioutil.TempDir("", "") + if err != nil { + return + } + + genericArgs.OutputBase = tempDir + defer os.RemoveAll(tempDir) + } + customArgs.OutputBase = genericArgs.OutputBase + + clientGen := generators.NewClientGenerator() + + if err := genericArgs.Execute( + clientgenerators.NameSystems(), + clientgenerators.DefaultNameSystem(), + clientGen.Packages, + ); err != nil { + logrus.Fatalf("Error: %v", err) + } + + groups := map[string]bool{} + for groupName, group := range customArgs.Options.Groups { + if group.GenerateTypes { + groups[groupName] = true + } + } + + if len(groups) == 0 { + if err := copyGoPathToModules(customArgs); err != nil { + logrus.Fatalf("go modules copy failed: %v", err) + } + + if err := clientGen.GenerateMocks(); err != nil { + logrus.Errorf("mocks failed: %v", err) + return + } + + return + } + + if err := copyGoPathToModules(customArgs); err != nil { + logrus.Fatalf("go modules copy failed: %v", err) + } + + if err := generateDeepcopy(groups, customArgs); err != nil { + logrus.Fatalf("deepcopy failed: %v", err) + } + + if err := generateClientset(groups, customArgs); err != nil { + logrus.Fatalf("clientset failed: %v", err) + } + + if err := generateListers(groups, customArgs); err != nil { + logrus.Fatalf("listers failed: %v", err) + } + + if err := generateInformers(groups, customArgs); err != nil { + logrus.Fatalf("informers failed: %v", err) + } + + if err := copyGoPathToModules(customArgs); err != nil { + logrus.Fatalf("go modules copy failed: %v", err) + } + + if err := clientGen.GenerateMocks(); err != nil { + logrus.Errorf("mocks failed: %v", err) + return + } +} + +func sourcePackagePath(customArgs *cgargs.CustomArgs, pkgName string) string { + pkgSplit := strings.Split(pkgName, string(os.PathSeparator)) + pkg := filepath.Join(customArgs.OutputBase, strings.Join(pkgSplit[:3], string(os.PathSeparator))) + return pkg +} + +//until k8s code-gen supports gopath +func copyGoPathToModules(customArgs *cgargs.CustomArgs) error { + + pathsToCopy := map[string]bool{} + for _, types := range customArgs.TypesByGroup { + for _, names := range types { + pkg := sourcePackagePath(customArgs, names.Package) + pathsToCopy[pkg] = true + } + } + + pkg := sourcePackagePath(customArgs, customArgs.Package) + pathsToCopy[pkg] = true + + for pkg, _ := range pathsToCopy { + if _, err := os.Stat(pkg); os.IsNotExist(err) { + continue + } + + return filepath.Walk(pkg, func(path string, info os.FileInfo, err error) error { + newPath := strings.Replace(path, pkg, ".", 1) + if _, err := os.Stat(newPath); os.IsNotExist(err) { + if info.IsDir() { + return os.Mkdir(newPath, info.Mode()) + } + + return copyFile(path, newPath) + } + + return err + }) + } + + return nil +} + +func copyFile(src, dst string) error { + var err error + var srcfd *os.File + var dstfd *os.File + var srcinfo os.FileInfo + + if srcfd, err = os.Open(src); err != nil { + return err + } + defer srcfd.Close() + + if dstfd, err = os.Create(dst); err != nil { + return err + } + defer dstfd.Close() + + if _, err = io.Copy(dstfd, srcfd); err != nil { + return err + } + if srcinfo, err = os.Stat(src); err != nil { + return err + } + return os.Chmod(dst, srcinfo.Mode()) +} + +func generateDeepcopy(groups map[string]bool, customArgs *cgargs.CustomArgs) error { + deepCopyCustomArgs := &dpargs.CustomArgs{} + + args := args.Default().WithoutDefaultFlagParsing() + args.CustomArgs = deepCopyCustomArgs + args.OutputBase = customArgs.OutputBase + args.OutputFileBaseName = "zz_generated_deepcopy" + args.GoHeaderFilePath = customArgs.Options.Boilerplate + + for gv, names := range customArgs.TypesByGroup { + if !groups[gv.Group] { + continue + } + args.InputDirs = append(args.InputDirs, names[0].Package) + deepCopyCustomArgs.BoundingDirs = append(deepCopyCustomArgs.BoundingDirs, names[0].Package) + } + + return args.Execute(dp.NameSystems(), + dp.DefaultNameSystem(), + dp.Packages) +} + +func generateClientset(groups map[string]bool, customArgs *cgargs.CustomArgs) error { + args, clientSetArgs := csargs.NewDefaults() + clientSetArgs.ClientsetName = "versioned" + args.OutputBase = customArgs.OutputBase + args.OutputPackagePath = filepath.Join(customArgs.Package, "clientset") + args.GoHeaderFilePath = customArgs.Options.Boilerplate + + var order []schema.GroupVersion + + for gv := range customArgs.TypesByGroup { + if !groups[gv.Group] { + continue + } + order = append(order, gv) + } + sort.Slice(order, func(i, j int) bool { + return order[i].Group < order[j].Group + }) + + for _, gv := range order { + names := customArgs.TypesByGroup[gv] + args.InputDirs = append(args.InputDirs, names[0].Package) + clientSetArgs.Groups = append(clientSetArgs.Groups, types2.GroupVersions{ + PackageName: gv.Group, + Group: types2.Group(gv.Group), + Versions: []types2.PackageVersion{ + { + Version: types2.Version(gv.Version), + Package: names[0].Package, + }, + }, + }) + } + + return args.Execute(cs.NameSystems(), + cs.DefaultNameSystem(), + cs.Packages) +} + +func generateInformers(groups map[string]bool, customArgs *cgargs.CustomArgs) error { + args, clientSetArgs := infargs.NewDefaults() + clientSetArgs.VersionedClientSetPackage = filepath.Join(customArgs.Package, "clientset/versioned") + clientSetArgs.ListersPackage = filepath.Join(customArgs.Package, "listers") + args.OutputBase = customArgs.OutputBase + args.OutputPackagePath = filepath.Join(customArgs.Package, "informers") + args.GoHeaderFilePath = customArgs.Options.Boilerplate + + for gv, names := range customArgs.TypesByGroup { + if !groups[gv.Group] { + continue + } + args.InputDirs = append(args.InputDirs, names[0].Package) + } + + return args.Execute(inf.NameSystems(), + inf.DefaultNameSystem(), + inf.Packages) +} + +func generateListers(groups map[string]bool, customArgs *cgargs.CustomArgs) error { + args, _ := lsargs.NewDefaults() + args.OutputBase = customArgs.OutputBase + args.OutputPackagePath = filepath.Join(customArgs.Package, "listers") + args.GoHeaderFilePath = customArgs.Options.Boilerplate + + for gv, names := range customArgs.TypesByGroup { + if !groups[gv.Group] { + continue + } + args.InputDirs = append(args.InputDirs, names[0].Package) + } + + return args.Execute(ls.NameSystems(), + ls.DefaultNameSystem(), + ls.Packages) +} + +func parseTypes(customArgs *cgargs.CustomArgs) []string { + for groupName, group := range customArgs.Options.Groups { + if group.GenerateTypes { + group.InformersPackage = filepath.Join(customArgs.Package, "informers/externalversions") + group.ClientSetPackage = filepath.Join(customArgs.Package, "clientset/versioned") + group.ListersPackage = filepath.Join(customArgs.Package, "listers") + customArgs.Options.Groups[groupName] = group + } + } + + for groupName, group := range customArgs.Options.Groups { + cgargs.ObjectsToGroupVersion(groupName, group.Types, customArgs.TypesByGroup) + } + + var inputDirs []string + for _, names := range customArgs.TypesByGroup { + inputDirs = append(inputDirs, names[0].Package) + } + + return inputDirs +} diff --git a/vendor/github.com/rancher/wrangler/pkg/crd/init.go b/vendor/github.com/rancher/wrangler/pkg/crd/init.go new file mode 100644 index 0000000000..6de27f7825 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/crd/init.go @@ -0,0 +1,253 @@ +package crd + +import ( + "context" + "strings" + "sync" + "time" + + "github.com/rancher/wrangler/pkg/kv" + "github.com/rancher/wrangler/pkg/name" + "github.com/sirupsen/logrus" + apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/rest" +) + +type Factory struct { + wg sync.WaitGroup + err error + CRDClient clientset.Interface +} + +type CRD struct { + GVK schema.GroupVersionKind + PluralName string + NonNamespace bool +} + +func (c CRD) ToCustomResourceDefinition() apiext.CustomResourceDefinition { + plural := c.PluralName + if plural == "" { + plural = strings.ToLower(name.GuessPluralName(c.GVK.Kind)) + } + + name := strings.ToLower(plural + "." + c.GVK.Group) + + crd := apiext.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: apiext.CustomResourceDefinitionSpec{ + Group: c.GVK.Group, + Version: c.GVK.Version, + Versions: []apiext.CustomResourceDefinitionVersion{ + { + Name: c.GVK.Version, + Storage: true, + Served: true, + }, + }, + Names: apiext.CustomResourceDefinitionNames{ + Plural: plural, + Kind: c.GVK.Kind, + }, + }, + } + + if c.NonNamespace { + crd.Spec.Scope = apiext.ClusterScoped + } else { + crd.Spec.Scope = apiext.NamespaceScoped + } + + return crd +} + +func NamespacedType(name string) CRD { + kindGroup, version := kv.Split(name, "/") + kind, group := kv.Split(kindGroup, ".") + + return FromGV(schema.GroupVersion{ + Group: group, + Version: version, + }, kind) +} + +func NamespacedTypes(names ...string) (ret []CRD) { + for _, name := range names { + ret = append(ret, NamespacedType(name)) + } + return +} + +func NonNamespacedType(name string) CRD { + crd := NamespacedType(name) + crd.NonNamespace = true + return crd +} + +func NonNamespacedTypes(names ...string) (ret []CRD) { + for _, name := range names { + ret = append(ret, NonNamespacedType(name)) + } + return +} + +func FromGV(gv schema.GroupVersion, kind string) CRD { + return CRD{ + GVK: gv.WithKind(kind), + } +} + +func NewFactoryFromClientGetter(client clientset.Interface) *Factory { + return &Factory{ + CRDClient: client, + } +} + +func NewFactoryFromClient(config *rest.Config) (*Factory, error) { + f, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + return &Factory{ + CRDClient: f, + }, nil +} + +func (f *Factory) BatchWait() error { + f.wg.Wait() + return f.err +} + +func (f *Factory) BatchCreateCRDs(ctx context.Context, crds ...CRD) { + f.wg.Add(1) + go func() { + defer f.wg.Done() + if _, err := f.CreateCRDs(ctx, crds...); err != nil && f.err == nil { + f.err = err + } + }() +} + +func (f *Factory) CreateCRDs(ctx context.Context, crds ...CRD) (map[schema.GroupVersionKind]*apiext.CustomResourceDefinition, error) { + if len(crds) == 0 { + return nil, nil + } + + crdStatus := map[schema.GroupVersionKind]*apiext.CustomResourceDefinition{} + + ready, err := f.getReadyCRDs() + if err != nil { + return nil, err + } + + for _, crdDef := range crds { + crd, err := f.createCRD(crdDef, ready) + if err != nil { + return nil, err + } + crdStatus[crdDef.GVK] = crd + } + + ready, err = f.getReadyCRDs() + if err != nil { + return nil, err + } + + for gvk, crd := range crdStatus { + if readyCrd, ok := ready[crd.Name]; ok { + crdStatus[gvk] = readyCrd + } else { + if err := f.waitCRD(ctx, crd.Name, gvk, crdStatus); err != nil { + return nil, err + } + } + } + + return crdStatus, nil +} + +func (f *Factory) waitCRD(ctx context.Context, crdName string, gvk schema.GroupVersionKind, crdStatus map[schema.GroupVersionKind]*apiext.CustomResourceDefinition) error { + logrus.Infof("Waiting for CRD %s to become available", crdName) + defer logrus.Infof("Done waiting for CRD %s to become available", crdName) + + first := true + return wait.Poll(500*time.Millisecond, 60*time.Second, func() (bool, error) { + if !first { + logrus.Infof("Waiting for CRD %s to become available", crdName) + } + first = false + + crd, err := f.CRDClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crdName, metav1.GetOptions{}) + if err != nil { + return false, err + } + + for _, cond := range crd.Status.Conditions { + switch cond.Type { + case apiext.Established: + if cond.Status == apiext.ConditionTrue { + crdStatus[gvk] = crd + return true, err + } + case apiext.NamesAccepted: + if cond.Status == apiext.ConditionFalse { + logrus.Infof("Name conflict on %s: %v\n", crdName, cond.Reason) + } + } + } + + return false, ctx.Err() + }) +} + +func (f *Factory) createCRD(crdDef CRD, ready map[string]*apiext.CustomResourceDefinition) (*apiext.CustomResourceDefinition, error) { + plural := crdDef.PluralName + if plural == "" { + plural = strings.ToLower(name.GuessPluralName(crdDef.GVK.Kind)) + } + + crd := crdDef.ToCustomResourceDefinition() + + existing, ok := ready[crd.Name] + if ok { + if !equality.Semantic.DeepEqual(crd.Spec.Versions, existing.Spec.Versions) { + existing.Spec = crd.Spec + logrus.Infof("Updating CRD %s", crd.Name) + return f.CRDClient.ApiextensionsV1beta1().CustomResourceDefinitions().Update(existing) + } + return existing, nil + } + + logrus.Infof("Creating CRD %s", crd.Name) + return f.CRDClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(&crd) +} + +func (f *Factory) getReadyCRDs() (map[string]*apiext.CustomResourceDefinition, error) { + list, err := f.CRDClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + + result := map[string]*apiext.CustomResourceDefinition{} + + for i, crd := range list.Items { + for _, cond := range crd.Status.Conditions { + switch cond.Type { + case apiext.Established: + if cond.Status == apiext.ConditionTrue { + result[crd.Name] = &list.Items[i] + } + } + } + } + + return result, nil +} diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/change.go b/vendor/github.com/rancher/wrangler/pkg/generic/change.go new file mode 100644 index 0000000000..3baef41166 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/generic/change.go @@ -0,0 +1,40 @@ +package generic + +import ( + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" +) + +func UpdateOnChange(updater Updater, handler Handler) Handler { + return func(key string, obj runtime.Object) (runtime.Object, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopyObject() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + + oldMeta, ignoreErr := meta.Accessor(obj) + if ignoreErr != nil { + return copyObj, err + } + + newMeta, ignoreErr := meta.Accessor(copyObj) + if ignoreErr != nil { + return copyObj, err + } + + if oldMeta.GetResourceVersion() == newMeta.GetResourceVersion() && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj + } + } + + return copyObj, err + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/controller.go b/vendor/github.com/rancher/wrangler/pkg/generic/controller.go new file mode 100644 index 0000000000..565c31370b --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/generic/controller.go @@ -0,0 +1,194 @@ +/* +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 generic + +import ( + "fmt" + "strings" + "time" + + "github.com/sirupsen/logrus" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" +) + +type Handler func(key string, obj runtime.Object) (runtime.Object, error) + +// Controller is the controller implementation for Foo resources +type Controller struct { + name string + workqueue workqueue.RateLimitingInterface + informer cache.SharedIndexInformer + handler Handler +} + +type generationKey struct { + generation int + key string +} + +// NewController returns a new sample controller +func NewController(name string, informer cache.SharedIndexInformer, workqueue workqueue.RateLimitingInterface, handler Handler) *Controller { + controller := &Controller{ + name: name, + handler: handler, + informer: informer, + workqueue: workqueue, + } + + logrus.Info("Setting up event handlers") + informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: controller.handleObject, + UpdateFunc: func(old, new interface{}) { + newMeta, err := meta.Accessor(new) + utilruntime.Must(err) + oldMeta, err := meta.Accessor(old) + utilruntime.Must(err) + if newMeta.GetResourceVersion() == oldMeta.GetResourceVersion() { + return + } + controller.handleObject(new) + }, + DeleteFunc: controller.handleObject, + }) + + return controller +} + +func (c *Controller) run(threadiness int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.workqueue.ShutDown() + + // Start the informer factories to begin populating the informer caches + logrus.Infof("Starting %s controller", c.name) + + // Launch two workers to process Foo resources + for i := 0; i < threadiness; i++ { + go wait.Until(c.runWorker, time.Second, stopCh) + } + + <-stopCh + logrus.Infof("Shutting down %s workers", c.name) +} + +func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) error { + if ok := cache.WaitForCacheSync(stopCh, c.informer.HasSynced); !ok { + c.workqueue.ShutDown() + return fmt.Errorf("failed to wait for caches to sync") + } + + go c.run(threadiness, stopCh) + return nil +} + +func (c *Controller) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *Controller) processNextWorkItem() bool { + obj, shutdown := c.workqueue.Get() + + if shutdown { + return false + } + + if err := c.processSingleItem(obj); err != nil { + if !strings.Contains(err.Error(), "please apply your changes to the latest version and try again") { + utilruntime.HandleError(err) + } + return true + } + + return true +} + +func (c *Controller) processSingleItem(obj interface{}) error { + var ( + key string + ok bool + ) + + defer c.workqueue.Done(obj) + + if key, ok = obj.(string); !ok { + c.workqueue.Forget(obj) + utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj)) + return nil + } + if err := c.syncHandler(key); err != nil { + c.workqueue.AddRateLimited(key) + return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error()) + } + + c.workqueue.Forget(obj) + return nil +} + +func (c *Controller) syncHandler(key string) error { + obj, exists, err := c.informer.GetStore().GetByKey(key) + if err != nil { + return err + } + if !exists { + _, err := c.handler(key, nil) + return err + } + + _, err = c.handler(key, obj.(runtime.Object)) + return err +} + +func (c *Controller) Enqueue(namespace, name string) { + if namespace == "" { + c.workqueue.AddRateLimited(name) + } else { + c.workqueue.AddRateLimited(namespace + "/" + name) + } +} + +func (c *Controller) enqueue(obj interface{}) { + var key string + var err error + if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + utilruntime.HandleError(err) + return + } + c.workqueue.AddRateLimited(key) +} + +func (c *Controller) handleObject(obj interface{}) { + if _, ok := obj.(metav1.Object); !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object, invalid type")) + return + } + _, ok = tombstone.Obj.(metav1.Object) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object tombstone, invalid type")) + return + } + } + c.enqueue(obj) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/controllerfactory.go b/vendor/github.com/rancher/wrangler/pkg/generic/controllerfactory.go new file mode 100644 index 0000000000..ab7cbf905d --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/generic/controllerfactory.go @@ -0,0 +1,124 @@ +package generic + +import ( + "context" + "sync" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" +) + +type ControllerManager struct { + lock sync.Mutex + generation int + started map[schema.GroupVersionKind]bool + controllers map[schema.GroupVersionKind]*Controller + handlers map[schema.GroupVersionKind]*Handlers +} + +func (g *ControllerManager) Start(ctx context.Context, defaultThreadiness int, threadiness map[schema.GroupVersionKind]int) error { + g.lock.Lock() + defer g.lock.Unlock() + + for gvk, controller := range g.controllers { + if g.started[gvk] { + continue + } + + threadiness, ok := threadiness[gvk] + if !ok { + threadiness = defaultThreadiness + } + if err := controller.Run(threadiness, ctx.Done()); err != nil { + return err + } + + if g.started == nil { + g.started = map[schema.GroupVersionKind]bool{} + } + g.started[gvk] = true + } + + return nil +} + +func (g *ControllerManager) Enqueue(gvk schema.GroupVersionKind, informer cache.SharedIndexInformer, namespace, name string) { + _, controller, _ := g.getController(gvk, informer, true) + controller.Enqueue(namespace, name) +} + +func (g *ControllerManager) removeHandler(gvk schema.GroupVersionKind, generation int) { + g.lock.Lock() + defer g.lock.Unlock() + + handlers, ok := g.handlers[gvk] + if !ok { + return + } + + var newHandlers []handlerEntry + for _, h := range handlers.handlers { + if h.generation == generation { + continue + } + newHandlers = append(newHandlers, h) + } + + handlers.handlers = newHandlers +} + +func (g *ControllerManager) getController(gvk schema.GroupVersionKind, informer cache.SharedIndexInformer, lock bool) (*Handlers, *Controller, bool) { + if lock { + g.lock.Lock() + defer g.lock.Unlock() + } + + if controller, ok := g.controllers[gvk]; ok { + return g.handlers[gvk], controller, true + } + + handlers := &Handlers{} + + queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), gvk.String()) + controller := NewController(gvk.String(), informer, queue, handlers.Handle) + + if g.handlers == nil { + g.handlers = map[schema.GroupVersionKind]*Handlers{} + } + + if g.controllers == nil { + g.controllers = map[schema.GroupVersionKind]*Controller{} + } + + g.handlers[gvk] = handlers + g.controllers[gvk] = controller + + return handlers, controller, false +} + +func (g *ControllerManager) AddHandler(ctx context.Context, gvk schema.GroupVersionKind, informer cache.SharedIndexInformer, name string, handler Handler) { + g.lock.Lock() + defer g.lock.Unlock() + + g.generation++ + entry := handlerEntry{ + generation: g.generation, + name: name, + handler: handler, + } + + go func() { + <-ctx.Done() + g.removeHandler(gvk, entry.generation) + }() + + handlers, controller, ok := g.getController(gvk, informer, false) + handlers.handlers = append(handlers.handlers, entry) + + if ok { + for _, key := range controller.informer.GetStore().ListKeys() { + controller.workqueue.Add(key) + } + } +} diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/handlers.go b/vendor/github.com/rancher/wrangler/pkg/generic/handlers.go new file mode 100644 index 0000000000..c592f74e97 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/generic/handlers.go @@ -0,0 +1,72 @@ +package generic + +import ( + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/runtime" +) + +type handlerEntry struct { + generation int + name string + handler Handler +} + +type Handlers struct { + handlers []handlerEntry +} + +func (h *Handlers) Handle(key string, obj runtime.Object) (runtime.Object, error) { + var ( + errs errors + ) + + for _, handler := range h.handlers { + newObj, err := handler.handler(key, obj) + if err != nil { + errs = append(errs, &handlerError{ + HandlerName: handler.name, + Err: err, + }) + } + if newObj != nil { + obj = newObj + } + } + + return obj, errs.ToErr() +} + +type errors []error + +func (e errors) Error() string { + buf := strings.Builder{} + for _, err := range e { + if buf.Len() > 0 { + buf.WriteString(", ") + } + buf.WriteString(err.Error()) + } + return buf.String() +} + +func (e errors) ToErr() error { + switch len(e) { + case 0: + return nil + case 1: + return e[0] + default: + return e + } +} + +type handlerError struct { + HandlerName string + Err error +} + +func (h handlerError) Error() string { + return fmt.Sprintf("handler %s: %v", h.HandlerName, h.Err) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/generic/remove.go b/vendor/github.com/rancher/wrangler/pkg/generic/remove.go new file mode 100644 index 0000000000..4e8204d13d --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/generic/remove.go @@ -0,0 +1,119 @@ +package generic + +import ( + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" +) + +var ( + finalizerKey = "wrangler.cattle.io/" +) + +type Updater func(runtime.Object) (runtime.Object, error) + +type objectLifecycleAdapter struct { + name string + handler Handler + updater Updater +} + +func NewRemoveHandler(name string, updater Updater, handler Handler) Handler { + o := objectLifecycleAdapter{ + name: name, + handler: handler, + updater: updater, + } + return o.sync +} + +func (o *objectLifecycleAdapter) sync(key string, obj runtime.Object) (runtime.Object, error) { + if obj == nil { + return nil, nil + } + + metadata, err := meta.Accessor(obj) + if err != nil { + return obj, err + } + + if metadata.GetDeletionTimestamp() == nil { + return o.addFinalizer(obj) + } + + if !o.hasFinalizer(obj) { + return obj, nil + } + + newObj, err := o.handler(key, obj) + if err != nil { + return newObj, err + } + + if newObj != nil { + obj = newObj + } + + return o.removeFinalizer(obj) +} + +func (o *objectLifecycleAdapter) constructFinalizerKey() string { + return finalizerKey + o.name +} + +func (o *objectLifecycleAdapter) hasFinalizer(obj runtime.Object) bool { + metadata, err := meta.Accessor(obj) + if err != nil { + return false + } + + finalizerKey := o.constructFinalizerKey() + finalizers := metadata.GetFinalizers() + for _, finalizer := range finalizers { + if finalizer == finalizerKey { + return true + } + } + + return false +} + +func (o *objectLifecycleAdapter) removeFinalizer(obj runtime.Object) (runtime.Object, error) { + if !o.hasFinalizer(obj) { + return obj, nil + } + + obj = obj.DeepCopyObject() + metadata, err := meta.Accessor(obj) + if err != nil { + return obj, err + } + + finalizerKey := o.constructFinalizerKey() + finalizers := metadata.GetFinalizers() + + var newFinalizers []string + for k, v := range finalizers { + if v != finalizerKey { + continue + } + newFinalizers = append(finalizers[:k], finalizers[k+1:]...) + } + + metadata.SetFinalizers(newFinalizers) + return o.updater(obj) +} + +func (o *objectLifecycleAdapter) addFinalizer(obj runtime.Object) (runtime.Object, error) { + if o.hasFinalizer(obj) { + return obj, nil + } + + obj = obj.DeepCopyObject() + metadata, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + + metadata.SetFinalizers(append(metadata.GetFinalizers(), o.constructFinalizerKey())) + return o.updater(obj) +} \ No newline at end of file diff --git a/vendor/github.com/rancher/norman/pkg/kv/split.go b/vendor/github.com/rancher/wrangler/pkg/kv/split.go similarity index 75% rename from vendor/github.com/rancher/norman/pkg/kv/split.go rename to vendor/github.com/rancher/wrangler/pkg/kv/split.go index 19e7914443..52161a68f8 100644 --- a/vendor/github.com/rancher/norman/pkg/kv/split.go +++ b/vendor/github.com/rancher/wrangler/pkg/kv/split.go @@ -8,8 +8,12 @@ func Split(s, sep string) (string, string) { } func SplitMap(s, sep string) map[string]string { + return SplitMapFromSlice(strings.Split(s, sep)) +} + +func SplitMapFromSlice(parts []string) map[string]string { result := map[string]string{} - for _, part := range strings.Split(s, sep) { + for _, part := range parts { k, v := Split(part, "=") result[k] = v } diff --git a/vendor/github.com/rancher/norman/leader/leader.go b/vendor/github.com/rancher/wrangler/pkg/leader/leader.go similarity index 67% rename from vendor/github.com/rancher/norman/leader/leader.go rename to vendor/github.com/rancher/wrangler/pkg/leader/leader.go index 74e3f7be10..3f2618cf7d 100644 --- a/vendor/github.com/rancher/norman/leader/leader.go +++ b/vendor/github.com/rancher/wrangler/pkg/leader/leader.go @@ -6,16 +6,9 @@ import ( "time" "github.com/sirupsen/logrus" - "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" - v1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" - "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/api/legacyscheme" - - // ensure that core is loaded into legacyschema - _ "k8s.io/kubernetes/pkg/apis/core/install" ) type Callback func(cb context.Context) @@ -38,16 +31,13 @@ func run(ctx context.Context, namespace, name string, client kubernetes.Interfac return err } - recorder := createRecorder(name, client) - rl, err := resourcelock.New(resourcelock.ConfigMapsResourceLock, namespace, name, client.CoreV1(), - nil, + client.CoordinationV1(), resourcelock.ResourceLockConfig{ Identity: id, - EventRecorder: recorder, }) if err != nil { logrus.Fatalf("error creating leader lock for %s: %v", name, err) @@ -75,9 +65,3 @@ func run(ctx context.Context, namespace, name string, client kubernetes.Interfac panic("unreachable") } -func createRecorder(name string, kubeClient kubernetes.Interface) record.EventRecorder { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(logrus.Debugf) - eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) - return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: name}) -} diff --git a/vendor/github.com/rancher/wrangler/pkg/merr/error.go b/vendor/github.com/rancher/wrangler/pkg/merr/error.go new file mode 100644 index 0000000000..df57b6b409 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/merr/error.go @@ -0,0 +1,38 @@ +package merr + +import "bytes" + + +type Errors []error + +func (e Errors) Err() error { + return NewErrors(e...) +} + +func (e Errors) Error() string { + buf := bytes.NewBuffer(nil) + for _, err := range e { + if buf.Len() > 0 { + buf.WriteString(", ") + } + buf.WriteString(err.Error()) + } + + return buf.String() +} + +func NewErrors(inErrors ...error) error { + var errors []error + for _, err := range inErrors { + if err != nil { + errors = append(errors, err) + } + } + + if len(errors) == 0 { + return nil + } else if len(errors) == 1 { + return errors[0] + } + return Errors(errors) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/name/name.go b/vendor/github.com/rancher/wrangler/pkg/name/name.go new file mode 100644 index 0000000000..c75507044c --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/name/name.go @@ -0,0 +1,59 @@ +package name + +import ( + "crypto/md5" + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" +) + +func GuessPluralName(name string) string { + if name == "" { + return name + } + + if strings.EqualFold(name, "Endpoints") { + return name + } + + if suffix(name, "s") || suffix(name, "ch") || suffix(name, "x") || suffix(name, "sh") { + return name + "es" + } + + if suffix(name, "f") || suffix(name, "fe") { + return name + "ves" + } + + if suffix(name, "y") && len(name) > 2 && !strings.ContainsAny(name[len(name)-2:len(name)-1], "[aeiou]") { + return name[0:len(name)-1] + "ies" + } + + return name + "s" +} + +func suffix(str, end string) bool { + return strings.HasSuffix(str, end) +} + +func Limit(s string, count int) string { + if len(s) < count { + return s + } + return fmt.Sprintf("%s-%s", s[:count-6], Hex(s, 5)) +} + +func Hex(s string, length int) string { + h := md5.Sum([]byte(s)) + d := hex.EncodeToString(h[:]) + return d[:length] +} + +func SafeConcatName(name ...string) string { + fullPath := strings.Join(name, "-") + if len(fullPath) > 63 { + digest := sha256.Sum256([]byte(fullPath)) + return fullPath[0:57] + "-" + hex.EncodeToString(digest[0:])[0:5] + } + return fullPath +} diff --git a/vendor/github.com/rancher/norman/pkg/objectset/objectset.go b/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go similarity index 53% rename from vendor/github.com/rancher/norman/pkg/objectset/objectset.go rename to vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go index 741caa91c9..7e3c9b0031 100644 --- a/vendor/github.com/rancher/norman/pkg/objectset/objectset.go +++ b/vendor/github.com/rancher/wrangler/pkg/objectset/objectset.go @@ -3,36 +3,37 @@ package objectset import ( "fmt" "reflect" + "sort" - "github.com/rancher/norman/types" + "github.com/rancher/wrangler/pkg/merr" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) -type objectKey struct { - name string - namespace string +type ObjectKey struct { + Name string + Namespace string } -func newObjectKey(obj v1.Object) objectKey { - return objectKey{ - namespace: obj.GetNamespace(), - name: obj.GetName(), +func NewObjectKey(obj v1.Object) ObjectKey { + return ObjectKey{ + Namespace: obj.GetNamespace(), + Name: obj.GetName(), } } -func (o objectKey) String() string { - if o.namespace == "" { - return o.name +func (o ObjectKey) String() string { + if o.Namespace == "" { + return o.Name } - return fmt.Sprintf("%s/%s", o.namespace, o.name) + return fmt.Sprintf("%s/%s", o.Namespace, o.Name) } -type objectCollection map[schema.GroupVersionKind]map[objectKey]runtime.Object +type ObjectByGVK map[schema.GroupVersionKind]map[ObjectKey]runtime.Object -func (o objectCollection) add(obj runtime.Object) error { +func (o ObjectByGVK) Add(obj runtime.Object) error { metadata, err := meta.Accessor(obj) if err != nil { return err @@ -40,13 +41,13 @@ func (o objectCollection) add(obj runtime.Object) error { objs := o[obj.GetObjectKind().GroupVersionKind()] if objs == nil { - objs = map[objectKey]runtime.Object{} + objs = map[ObjectKey]runtime.Object{} o[obj.GetObjectKind().GroupVersionKind()] = objs } - objs[objectKey{ - namespace: metadata.GetNamespace(), - name: metadata.GetName(), + objs[ObjectKey{ + Namespace: metadata.GetNamespace(), + Name: metadata.GetName(), }] = obj return nil @@ -54,7 +55,7 @@ func (o objectCollection) add(obj runtime.Object) error { type ObjectSet struct { errs []error - objects objectCollection + objects ObjectByGVK nsed map[schema.GroupVersionKind]bool inputs []runtime.Object order []runtime.Object @@ -63,10 +64,18 @@ type ObjectSet struct { func NewObjectSet() *ObjectSet { return &ObjectSet{ nsed: map[schema.GroupVersionKind]bool{}, - objects: objectCollection{}, + objects: ObjectByGVK{}, } } +func (o *ObjectSet) Inputs() []runtime.Object { + return o.inputs +} + +func (o *ObjectSet) ObjectsByGVK() ObjectByGVK { + return o.objects +} + func (o *ObjectSet) AddInput(objs ...runtime.Object) *ObjectSet { for _, obj := range objs { if obj == nil || reflect.ValueOf(obj).IsNil() { @@ -111,7 +120,7 @@ func (o *ObjectSet) add(obj runtime.Object) { } o.nsed[gvk] = namespace != "" - if err := o.objects.add(obj); err != nil { + if err := o.objects.Add(obj); err != nil { o.err(fmt.Errorf("failed to get metadata for %s", gvk)) return } @@ -129,5 +138,39 @@ func (o *ObjectSet) AddErr(err error) { } func (o *ObjectSet) Err() error { - return types.NewErrors(o.errs...) + return merr.NewErrors(o.errs...) +} + +func (o *ObjectSet) Len() int { + return len(o.objects) +} + +func (o *ObjectSet) GVKOrder(known ...schema.GroupVersionKind) []schema.GroupVersionKind { + seen := map[schema.GroupVersionKind]bool{} + var gvkOrder []schema.GroupVersionKind + + for _, obj := range o.order { + if seen[obj.GetObjectKind().GroupVersionKind()] { + continue + } + seen[obj.GetObjectKind().GroupVersionKind()] = true + gvkOrder = append(gvkOrder, obj.GetObjectKind().GroupVersionKind()) + } + + var rest []schema.GroupVersionKind + + for _, gvk := range known { + if seen[gvk] { + continue + } + + seen[gvk] = true + rest = append(rest, gvk) + } + + sort.Slice(rest, func(i, j int) bool { + return rest[i].String() < rest[j].String() + }) + + return append(gvkOrder, rest...) } diff --git a/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go b/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go new file mode 100644 index 0000000000..befdf7dd8d --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go @@ -0,0 +1,63 @@ +package relatedresource + +import ( + "context" + + "github.com/rancher/wrangler/pkg/generic" + "github.com/rancher/wrangler/pkg/kv" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/cache" +) + +type Key struct { + Namespace string + Name string +} + +func NewKey(namespace, name string) Key { + return Key{ + Namespace: namespace, + Name: name, + } +} + +type ControllerWrapper interface { + Informer() cache.SharedIndexInformer + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) +} + +type Enqueuer interface { + Enqueue(namespace, name string) +} + +type Resolver func(namespace, name string, obj runtime.Object) ([]Key, error) + +func Watch(ctx context.Context, name string, resolve Resolver, enq Enqueuer, watching ...ControllerWrapper) { + for _, c := range watching { + watch(ctx, name, enq, resolve, c) + } +} + +func watch(ctx context.Context, name string, enq Enqueuer, resolve Resolver, controller ControllerWrapper) { + controller.AddGenericHandler(ctx, name, func(key string, obj runtime.Object) (runtime.Object, error) { + ns, name := kv.Split(key, "/") + + ro, ok := obj.(runtime.Object) + if !ok { + ro = nil + } + + keys, err := resolve(ns, name, ro) + if err != nil { + return nil, err + } + + for _, key := range keys { + if key.Name != "" { + enq.Enqueue(key.Namespace, key.Name) + } + } + + return nil, nil + }) +} diff --git a/vendor/github.com/rancher/norman/pkg/resolvehome/home.go b/vendor/github.com/rancher/wrangler/pkg/resolvehome/main.go similarity index 51% rename from vendor/github.com/rancher/norman/pkg/resolvehome/home.go rename to vendor/github.com/rancher/wrangler/pkg/resolvehome/main.go index cc96d6a44c..10694a31bf 100644 --- a/vendor/github.com/rancher/norman/pkg/resolvehome/home.go +++ b/vendor/github.com/rancher/wrangler/pkg/resolvehome/main.go @@ -1,11 +1,9 @@ package resolvehome import ( - "os" - "os/user" - "strings" - "github.com/pkg/errors" + "os" + "strings" ) var ( @@ -15,7 +13,7 @@ var ( func Resolve(s string) (string, error) { for _, home := range homes { if strings.Contains(s, home) { - homeDir, err := getHomeDir() + homeDir, err := os.UserHomeDir() if err != nil { return "", errors.Wrap(err, "determining current user") } @@ -24,21 +22,4 @@ func Resolve(s string) (string, error) { } return s, nil -} - -func getHomeDir() (string, error) { - home := os.Getenv("HOME") - if home != "" { - return home, nil - } - - if os.Getuid() == 0 { - return "/root", nil - } - - u, err := user.Current() - if err != nil { - return "", errors.Wrap(err, "determining current user, try set HOME and USER env vars") - } - return u.HomeDir, nil -} +} \ No newline at end of file diff --git a/vendor/github.com/rancher/wrangler/pkg/signals/signal.go b/vendor/github.com/rancher/wrangler/pkg/signals/signal.go new file mode 100644 index 0000000000..801877ede4 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/signals/signal.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 signals + +import ( + "context" + "os" + "os/signal" +) + +var onlyOneSignalHandler = make(chan struct{}) + +// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned +// which is closed on one of these signals. If a second signal is caught, the program +// is terminated with exit code 1. +func SetupSignalHandler(parent context.Context) context.Context { + close(onlyOneSignalHandler) // panics when called twice + ctx, cancel := context.WithCancel(parent) + + c := make(chan os.Signal, 2) + signal.Notify(c, shutdownSignals...) + go func() { + <-c + cancel() + <-c + os.Exit(1) // second signal. Exit directly. + }() + + return ctx +} diff --git a/vendor/github.com/rancher/wrangler/pkg/signals/signal_posix.go b/vendor/github.com/rancher/wrangler/pkg/signals/signal_posix.go new file mode 100644 index 0000000000..9bdb4e7418 --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/signals/signal_posix.go @@ -0,0 +1,26 @@ +// +build !windows + +/* +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 signals + +import ( + "os" + "syscall" +) + +var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} diff --git a/vendor/k8s.io/kubernetes/pkg/util/maps/doc.go b/vendor/github.com/rancher/wrangler/pkg/signals/signal_windows.go similarity index 81% rename from vendor/k8s.io/kubernetes/pkg/util/maps/doc.go rename to vendor/github.com/rancher/wrangler/pkg/signals/signal_windows.go index 2e121b943c..4907d573fe 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/maps/doc.go +++ b/vendor/github.com/rancher/wrangler/pkg/signals/signal_windows.go @@ -1,5 +1,5 @@ /* -Copyright 2016 The Kubernetes Authors. +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. @@ -14,5 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package maps has common methods for dealing with common map types. -package maps +package signals + +import ( + "os" +) + +var shutdownSignals = []os.Signal{os.Interrupt} diff --git a/vendor/github.com/rancher/norman/types/slice/contains.go b/vendor/github.com/rancher/wrangler/pkg/slice/contains.go similarity index 100% rename from vendor/github.com/rancher/norman/types/slice/contains.go rename to vendor/github.com/rancher/wrangler/pkg/slice/contains.go diff --git a/vendor/github.com/rancher/norman/controller/starter.go b/vendor/github.com/rancher/wrangler/pkg/start/all.go similarity index 87% rename from vendor/github.com/rancher/norman/controller/starter.go rename to vendor/github.com/rancher/wrangler/pkg/start/all.go index 555197676c..421dacf4b7 100644 --- a/vendor/github.com/rancher/norman/controller/starter.go +++ b/vendor/github.com/rancher/wrangler/pkg/start/all.go @@ -1,4 +1,4 @@ -package controller +package start import ( "context" @@ -11,7 +11,7 @@ type Starter interface { Start(ctx context.Context, threadiness int) error } -func SyncThenStart(ctx context.Context, threadiness int, starters ...Starter) error { +func All(ctx context.Context, threadiness int, starters ...Starter) error { if err := Sync(ctx, starters...); err != nil { return err } diff --git a/vendor/k8s.io/client-go/discovery/fake/BUILD b/vendor/k8s.io/client-go/discovery/fake/BUILD new file mode 100644 index 0000000000..840aeb37dd --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/fake/BUILD @@ -0,0 +1,46 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["discovery.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/discovery/fake", + importpath = "k8s.io/client-go/discovery/fake", + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/version:go_default_library", + "//staging/src/k8s.io/client-go/pkg/version:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/testing:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["discovery_test.go"], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/version:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", + ], +) diff --git a/vendor/k8s.io/client-go/discovery/fake/discovery.go b/vendor/k8s.io/client-go/discovery/fake/discovery.go new file mode 100644 index 0000000000..335473dd19 --- /dev/null +++ b/vendor/k8s.io/client-go/discovery/fake/discovery.go @@ -0,0 +1,160 @@ +/* +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 fake + +import ( + "fmt" + + "github.com/googleapis/gnostic/OpenAPIv2" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + kubeversion "k8s.io/client-go/pkg/version" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/testing" +) + +// FakeDiscovery implements discovery.DiscoveryInterface and sometimes calls testing.Fake.Invoke with an action, +// but doesn't respect the return value if any. There is a way to fake static values like ServerVersion by using the Faked... fields on the struct. +type FakeDiscovery struct { + *testing.Fake + FakedServerVersion *version.Info +} + +// ServerResourcesForGroupVersion returns the supported resources for a group +// and version. +func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + action := testing.ActionImpl{ + Verb: "get", + Resource: schema.GroupVersionResource{Resource: "resource"}, + } + c.Invokes(action, nil) + for _, resourceList := range c.Resources { + if resourceList.GroupVersion == groupVersion { + return resourceList, nil + } + } + return nil, fmt.Errorf("GroupVersion %q not found", groupVersion) +} + +// ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. +func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { + _, rs, err := c.ServerGroupsAndResources() + return rs, err +} + +// ServerGroupsAndResources returns the supported groups and resources for all groups and versions. +func (c *FakeDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + sgs, err := c.ServerGroups() + if err != nil { + return nil, nil, err + } + resultGroups := []*metav1.APIGroup{} + for i := range sgs.Groups { + resultGroups = append(resultGroups, &sgs.Groups[i]) + } + + action := testing.ActionImpl{ + Verb: "get", + Resource: schema.GroupVersionResource{Resource: "resource"}, + } + c.Invokes(action, nil) + return resultGroups, c.Resources, nil +} + +// ServerPreferredResources returns the supported resources with the version +// preferred by the server. +func (c *FakeDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +// ServerPreferredNamespacedResources returns the supported namespaced resources +// with the version preferred by the server. +func (c *FakeDiscovery) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return nil, nil +} + +// ServerGroups returns the supported groups, with information like supported +// versions and the preferred version. +func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) { + action := testing.ActionImpl{ + Verb: "get", + Resource: schema.GroupVersionResource{Resource: "group"}, + } + c.Invokes(action, nil) + + groups := map[string]*metav1.APIGroup{} + + for _, res := range c.Resources { + gv, err := schema.ParseGroupVersion(res.GroupVersion) + if err != nil { + return nil, err + } + group := groups[gv.Group] + if group == nil { + group = &metav1.APIGroup{ + Name: gv.Group, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: res.GroupVersion, + Version: gv.Version, + }, + } + groups[gv.Group] = group + } + + group.Versions = append(group.Versions, metav1.GroupVersionForDiscovery{ + GroupVersion: res.GroupVersion, + Version: gv.Version, + }) + } + + list := &metav1.APIGroupList{} + for _, apiGroup := range groups { + list.Groups = append(list.Groups, *apiGroup) + } + + return list, nil + +} + +// ServerVersion retrieves and parses the server's version. +func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { + action := testing.ActionImpl{} + action.Verb = "get" + action.Resource = schema.GroupVersionResource{Resource: "version"} + c.Invokes(action, nil) + + if c.FakedServerVersion != nil { + return c.FakedServerVersion, nil + } + + versionInfo := kubeversion.Get() + return &versionInfo, nil +} + +// OpenAPISchema retrieves and parses the swagger API schema the server supports. +func (c *FakeDiscovery) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} + +// RESTClient returns a RESTClient that is used to communicate with API server +// by this client implementation. +func (c *FakeDiscovery) RESTClient() restclient.Interface { + return nil +} diff --git a/vendor/k8s.io/code-generator/BUILD b/vendor/k8s.io/code-generator/BUILD new file mode 100644 index 0000000000..a2aa700a93 --- /dev/null +++ b/vendor/k8s.io/code-generator/BUILD @@ -0,0 +1,29 @@ +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/conversion-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/deepcopy-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/defaulter-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/go-to-protobuf:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/import-boss:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/informer-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/lister-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/register-gen:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/set-gen:all-srcs", + "//staging/src/k8s.io/code-generator/hack:all-srcs", + "//staging/src/k8s.io/code-generator/pkg/namer:all-srcs", + "//staging/src/k8s.io/code-generator/pkg/util:all-srcs", + "//staging/src/k8s.io/code-generator/third_party/forked/golang/reflect:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/CONTRIBUTING.md b/vendor/k8s.io/code-generator/CONTRIBUTING.md new file mode 100644 index 0000000000..76625b7bc9 --- /dev/null +++ b/vendor/k8s.io/code-generator/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing guidelines + +Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. + +This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/code-generator](https://git.k8s.io/kubernetes/staging/src/k8s.io/code-generator) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). + +Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/sig-architecture/staging.md) for more information diff --git a/vendor/k8s.io/code-generator/LICENSE b/vendor/k8s.io/code-generator/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/k8s.io/code-generator/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/code-generator/OWNERS b/vendor/k8s.io/code-generator/OWNERS new file mode 100644 index 0000000000..6f7abe3edb --- /dev/null +++ b/vendor/k8s.io/code-generator/OWNERS @@ -0,0 +1,13 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- lavalamp +- wojtek-t +- sttts +reviewers: +- lavalamp +- wojtek-t +- sttts +labels: +- sig/api-machinery +- area/code-generation diff --git a/vendor/k8s.io/code-generator/README.md b/vendor/k8s.io/code-generator/README.md new file mode 100644 index 0000000000..e03c6bf55e --- /dev/null +++ b/vendor/k8s.io/code-generator/README.md @@ -0,0 +1,24 @@ +# code-generator + +Golang code-generators used to implement [Kubernetes-style API types](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md). + +## Purpose + +These code-generators can be used +- in the context of [CustomResourceDefinition](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) to build native, versioned clients, + informers and other helpers +- in the context of [User-provider API Servers](https://github.com/kubernetes/apiserver) to build conversions between internal and versioned types, defaulters, protobuf codecs, + internal and versioned clients and informers. + +## Resources +- The example [sample controller](https://github.com/kubernetes/sample-controller) shows a code example of a controller that uses the clients, listers and informers generated by this library. +- The article [Kubernetes Deep Dive: Code Generation for CustomResources](https://blog.openshift.com/kubernetes-deep-dive-code-generation-customresources/) gives a step by step instruction on how to use this library. + +## Compatibility + +HEAD of this repo will match HEAD of k8s.io/apiserver, k8s.io/apimachinery, and k8s.io/client-go. + +## Where does it come from? + +`code-generator` is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/code-generator. +Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here. diff --git a/vendor/k8s.io/code-generator/SECURITY_CONTACTS b/vendor/k8s.io/code-generator/SECURITY_CONTACTS new file mode 100644 index 0000000000..70b7cf9a65 --- /dev/null +++ b/vendor/k8s.io/code-generator/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Committee to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/BUILD new file mode 100644 index 0000000000..5df0eb366d --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/BUILD @@ -0,0 +1,46 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", +) + +go_binary( + name = "client-gen", + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen", + importpath = "k8s.io/code-generator/cmd/client-gen", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/args:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/path:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/OWNERS b/vendor/k8s.io/code-generator/cmd/client-gen/OWNERS new file mode 100644 index 0000000000..62866d0b19 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- lavalamp +- wojtek-t +- caesarxuchao +reviewers: +- lavalamp +- wojtek-t +- caesarxuchao diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/README.md b/vendor/k8s.io/code-generator/cmd/client-gen/README.md new file mode 100644 index 0000000000..092a61151c --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/README.md @@ -0,0 +1,4 @@ +See [generating-clientset.md](https://git.k8s.io/community/contributors/devel/sig-api-machinery/generating-clientset.md) + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/staging/src/k8s.io/code-generator/client-gen/README.md?pixel)]() diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/args/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/args/BUILD new file mode 100644 index 0000000000..305f13c38e --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/args/BUILD @@ -0,0 +1,47 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "args.go", + "gvpackages.go", + "gvtype.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/args", + importpath = "k8s.io/code-generator/cmd/client-gen/args", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["gvpackages_test.go"], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + ], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/args/args.go b/vendor/k8s.io/code-generator/cmd/client-gen/args/args.go new file mode 100644 index 0000000000..f45be1bb83 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/args/args.go @@ -0,0 +1,120 @@ +/* +Copyright 2015 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 args + +import ( + "fmt" + "path" + + "github.com/spf13/pflag" + "k8s.io/gengo/args" + + "k8s.io/code-generator/cmd/client-gen/types" + codegenutil "k8s.io/code-generator/pkg/util" +) + +var DefaultInputDirs = []string{} + +// ClientGenArgs is a wrapper for arguments to client-gen. +type CustomArgs struct { + // A sorted list of group versions to generate. For each of them the package path is found + // in GroupVersionToInputPath. + Groups []types.GroupVersions + + // Overrides for which types should be included in the client. + IncludedTypesOverrides map[types.GroupVersion][]string + + // ClientsetName is the name of the clientset to be generated. It's + // populated from command-line arguments. + ClientsetName string + // ClientsetAPIPath is the default API HTTP path for generated clients. + ClientsetAPIPath string + // ClientsetOnly determines if we should generate the clients for groups and + // types along with the clientset. It's populated from command-line + // arguments. + ClientsetOnly bool + // FakeClient determines if client-gen generates the fake clients. + FakeClient bool +} + +func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { + genericArgs := args.Default().WithoutDefaultFlagParsing() + customArgs := &CustomArgs{ + ClientsetName: "internalclientset", + ClientsetAPIPath: "/apis", + ClientsetOnly: false, + FakeClient: true, + } + genericArgs.CustomArgs = customArgs + genericArgs.InputDirs = DefaultInputDirs + + if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 { + genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/clientset") + } + + return genericArgs, customArgs +} + +func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) { + gvsBuilder := NewGroupVersionsBuilder(&ca.Groups) + pflag.Var(NewGVPackagesValue(gvsBuilder, nil), "input", "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\".") + pflag.Var(NewGVTypesValue(&ca.IncludedTypesOverrides, []string{}), "included-types-overrides", "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient will be used for other group versions.") + pflag.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.") + pflag.StringVarP(&ca.ClientsetName, "clientset-name", "n", ca.ClientsetName, "the name of the generated clientset package.") + pflag.StringVarP(&ca.ClientsetAPIPath, "clientset-api-path", "", ca.ClientsetAPIPath, "the value of default API HTTP path, starting with / and without trailing /.") + pflag.BoolVar(&ca.ClientsetOnly, "clientset-only", ca.ClientsetOnly, "when set, client-gen only generates the clientset shell, without generating the individual typed clients") + pflag.BoolVar(&ca.FakeClient, "fake-clientset", ca.FakeClient, "when set, client-gen will generate the fake clientset that can be used in tests") + + // support old flags + fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-package", fs.GetNormalizeFunc())) +} + +func Validate(genericArgs *args.GeneratorArgs) error { + customArgs := genericArgs.CustomArgs.(*CustomArgs) + + if len(genericArgs.OutputPackagePath) == 0 { + return fmt.Errorf("output package cannot be empty") + } + if len(customArgs.ClientsetName) == 0 { + return fmt.Errorf("clientset name cannot be empty") + } + if len(customArgs.ClientsetAPIPath) == 0 { + return fmt.Errorf("clientset API path cannot be empty") + } + + return nil +} + +// GroupVersionPackages returns a map from GroupVersion to the package with the types.go. +func (ca *CustomArgs) GroupVersionPackages() map[types.GroupVersion]string { + res := map[types.GroupVersion]string{} + for _, pkg := range ca.Groups { + for _, v := range pkg.Versions { + res[types.GroupVersion{Group: pkg.Group, Version: v.Version}] = v.Package + } + } + return res +} + +func mapFlagName(from, to string, old func(fs *pflag.FlagSet, name string) pflag.NormalizedName) func(fs *pflag.FlagSet, name string) pflag.NormalizedName { + return func(fs *pflag.FlagSet, name string) pflag.NormalizedName { + if name == from { + name = to + } + return old(fs, name) + } +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go new file mode 100644 index 0000000000..8da71d6f9b --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go @@ -0,0 +1,183 @@ +/* +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 args + +import ( + "bytes" + "encoding/csv" + "flag" + "path" + "sort" + "strings" + + "k8s.io/code-generator/cmd/client-gen/types" +) + +type inputBasePathValue struct { + builder *groupVersionsBuilder +} + +var _ flag.Value = &inputBasePathValue{} + +func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue { + v := &inputBasePathValue{ + builder: builder, + } + v.Set(def) + return v +} + +func (s *inputBasePathValue) Set(val string) error { + s.builder.importBasePath = val + return s.builder.update() +} + +func (s *inputBasePathValue) Type() string { + return "string" +} + +func (s *inputBasePathValue) String() string { + return s.builder.importBasePath +} + +type gvPackagesValue struct { + builder *groupVersionsBuilder + groups []string + changed bool +} + +func NewGVPackagesValue(builder *groupVersionsBuilder, def []string) *gvPackagesValue { + gvp := new(gvPackagesValue) + gvp.builder = builder + if def != nil { + if err := gvp.set(def); err != nil { + panic(err) + } + } + return gvp +} + +var _ flag.Value = &gvPackagesValue{} + +func (s *gvPackagesValue) set(vs []string) error { + if s.changed { + s.groups = append(s.groups, vs...) + } else { + s.groups = append([]string(nil), vs...) + } + + s.builder.groups = s.groups + return s.builder.update() +} + +func (s *gvPackagesValue) Set(val string) error { + vs, err := readAsCSV(val) + if err != nil { + return err + } + if err := s.set(vs); err != nil { + return err + } + s.changed = true + return nil +} + +func (s *gvPackagesValue) Type() string { + return "stringSlice" +} + +func (s *gvPackagesValue) String() string { + str, _ := writeAsCSV(s.groups) + return "[" + str + "]" +} + +type groupVersionsBuilder struct { + value *[]types.GroupVersions + groups []string + importBasePath string +} + +func NewGroupVersionsBuilder(groups *[]types.GroupVersions) *groupVersionsBuilder { + return &groupVersionsBuilder{ + value: groups, + } +} + +func (p *groupVersionsBuilder) update() error { + var seenGroups = make(map[types.Group]*types.GroupVersions) + for _, v := range p.groups { + pth, gvString := parsePathGroupVersion(v) + gv, err := types.ToGroupVersion(gvString) + if err != nil { + return err + } + + versionPkg := types.PackageVersion{Package: path.Join(p.importBasePath, pth, gv.Group.NonEmpty(), gv.Version.String()), Version: gv.Version} + if group, ok := seenGroups[gv.Group]; ok { + seenGroups[gv.Group].Versions = append(group.Versions, versionPkg) + } else { + seenGroups[gv.Group] = &types.GroupVersions{ + PackageName: gv.Group.NonEmpty(), + Group: gv.Group, + Versions: []types.PackageVersion{versionPkg}, + } + } + } + + var groupNames []string + for groupName := range seenGroups { + groupNames = append(groupNames, groupName.String()) + } + sort.Strings(groupNames) + *p.value = []types.GroupVersions{} + for _, groupName := range groupNames { + *p.value = append(*p.value, *seenGroups[types.Group(groupName)]) + } + + return nil +} + +func parsePathGroupVersion(pgvString string) (gvPath string, gvString string) { + subs := strings.Split(pgvString, "/") + length := len(subs) + switch length { + case 0, 1, 2: + return "", pgvString + default: + return strings.Join(subs[:length-2], "/"), strings.Join(subs[length-2:], "/") + } +} + +func readAsCSV(val string) ([]string, error) { + if val == "" { + return []string{}, nil + } + stringReader := strings.NewReader(val) + csvReader := csv.NewReader(stringReader) + return csvReader.Read() +} + +func writeAsCSV(vals []string) (string, error) { + b := &bytes.Buffer{} + w := csv.NewWriter(b) + err := w.Write(vals) + if err != nil { + return "", err + } + w.Flush() + return strings.TrimSuffix(b.String(), "\n"), nil +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go new file mode 100644 index 0000000000..e4e3ccb536 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go @@ -0,0 +1,110 @@ +/* +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 args + +import ( + "flag" + "fmt" + "strings" + + "k8s.io/code-generator/cmd/client-gen/types" +) + +type gvTypeValue struct { + gvToTypes *map[types.GroupVersion][]string + changed bool +} + +func NewGVTypesValue(gvToTypes *map[types.GroupVersion][]string, def []string) *gvTypeValue { + gvt := new(gvTypeValue) + gvt.gvToTypes = gvToTypes + if def != nil { + if err := gvt.set(def); err != nil { + panic(err) + } + } + return gvt +} + +var _ flag.Value = &gvTypeValue{} + +func (s *gvTypeValue) set(vs []string) error { + if !s.changed { + *s.gvToTypes = map[types.GroupVersion][]string{} + } + + for _, input := range vs { + gvString, typeStr, err := parseGroupVersionType(input) + if err != nil { + return err + } + gv, err := types.ToGroupVersion(gvString) + if err != nil { + return err + } + types, ok := (*s.gvToTypes)[gv] + if !ok { + types = []string{} + } + types = append(types, typeStr) + (*s.gvToTypes)[gv] = types + } + + return nil +} + +func (s *gvTypeValue) Set(val string) error { + vs, err := readAsCSV(val) + if err != nil { + return err + } + if err := s.set(vs); err != nil { + return err + } + s.changed = true + return nil +} + +func (s *gvTypeValue) Type() string { + return "stringSlice" +} + +func (s *gvTypeValue) String() string { + strs := make([]string, 0, len(*s.gvToTypes)) + for gv, ts := range *s.gvToTypes { + for _, t := range ts { + strs = append(strs, gv.Group.String()+"/"+gv.Version.String()+"/"+t) + } + } + str, _ := writeAsCSV(strs) + return "[" + str + "]" +} + +func parseGroupVersionType(gvtString string) (gvString string, typeStr string, err error) { + invalidFormatErr := fmt.Errorf("invalid value: %s, should be of the form group/version/type", gvtString) + subs := strings.Split(gvtString, "/") + length := len(subs) + switch length { + case 2: + // gvtString of the form group/type, e.g. api/Service,extensions/ReplicaSet + return subs[0] + "/", subs[1], nil + case 3: + return strings.Join(subs[:length-1], "/"), subs[length-1], nil + default: + return "", "", invalidFormatErr + } +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/generators/BUILD new file mode 100644 index 0000000000..36dcab0604 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/BUILD @@ -0,0 +1,51 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "client_generator.go", + "generator_for_clientset.go", + "generator_for_expansion.go", + "generator_for_group.go", + "generator_for_type.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/generators", + importpath = "k8s.io/code-generator/cmd/client-gen/generators", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/path:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/namer:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/gengo/generator:go_default_library", + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/fake:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go new file mode 100644 index 0000000000..18980744f0 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go @@ -0,0 +1,403 @@ +/* +Copyright 2015 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 generators has the generators for the client-gen utility. +package generators + +import ( + "path/filepath" + "strings" + + clientgenargs "k8s.io/code-generator/cmd/client-gen/args" + "k8s.io/code-generator/cmd/client-gen/generators/fake" + "k8s.io/code-generator/cmd/client-gen/generators/scheme" + "k8s.io/code-generator/cmd/client-gen/generators/util" + "k8s.io/code-generator/cmd/client-gen/path" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + codegennamer "k8s.io/code-generator/pkg/namer" + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/klog" +) + +// NameSystems returns the name system used by the generators in this package. +func NameSystems() namer.NameSystems { + pluralExceptions := map[string]string{ + "Endpoints": "Endpoints", + } + lowercaseNamer := namer.NewAllLowercasePluralNamer(pluralExceptions) + + publicNamer := &ExceptionNamer{ + Exceptions: map[string]string{ + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" + }, + KeyFunc: func(t *types.Type) string { + return t.Name.Package + "." + t.Name.Name + }, + Delegate: namer.NewPublicNamer(0), + } + privateNamer := &ExceptionNamer{ + Exceptions: map[string]string{ + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "eventResource" + }, + KeyFunc: func(t *types.Type) string { + return t.Name.Package + "." + t.Name.Name + }, + Delegate: namer.NewPrivateNamer(0), + } + publicPluralNamer := &ExceptionNamer{ + Exceptions: map[string]string{ + // these exceptions are used to deconflict the generated code + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "EventResource" + }, + KeyFunc: func(t *types.Type) string { + return t.Name.Package + "." + t.Name.Name + }, + Delegate: namer.NewPublicPluralNamer(pluralExceptions), + } + privatePluralNamer := &ExceptionNamer{ + Exceptions: map[string]string{ + // you can put your fully qualified package like + // to generate a name that doesn't conflict with your group. + // "k8s.io/apis/events/v1beta1.Event": "eventResource" + // these exceptions are used to deconflict the generated code + "k8s.io/apis/events/v1beta1.Event": "eventResources", + "k8s.io/kubernetes/pkg/apis/events.Event": "eventResources", + }, + KeyFunc: func(t *types.Type) string { + return t.Name.Package + "." + t.Name.Name + }, + Delegate: namer.NewPrivatePluralNamer(pluralExceptions), + } + + return namer.NameSystems{ + "singularKind": namer.NewPublicNamer(0), + "public": publicNamer, + "private": privateNamer, + "raw": namer.NewRawNamer("", nil), + "publicPlural": publicPluralNamer, + "privatePlural": privatePluralNamer, + "allLowercasePlural": lowercaseNamer, + "resource": codegennamer.NewTagOverrideNamer("resourceName", lowercaseNamer), + } +} + +// ExceptionNamer allows you specify exceptional cases with exact names. This allows you to have control +// for handling various conflicts, like group and resource names for instance. +type ExceptionNamer struct { + Exceptions map[string]string + KeyFunc func(*types.Type) string + + Delegate namer.Namer +} + +// Name provides the requested name for a type. +func (n *ExceptionNamer) Name(t *types.Type) string { + key := n.KeyFunc(t) + if exception, ok := n.Exceptions[key]; ok { + return exception + } + return n.Delegate.Name(t) +} + +// DefaultNameSystem returns the default name system for ordering the types to be +// processed by the generators in this package. +func DefaultNameSystem() string { + return "public" +} + +func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, apiPath string, srcTreePath string, inputPackage string, boilerplate []byte) generator.Package { + groupVersionClientPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty())) + return &generator.DefaultPackage{ + PackageName: strings.ToLower(gv.Version.NonEmpty()), + PackagePath: groupVersionClientPackage, + HeaderText: boilerplate, + PackageDocumentation: []byte( + `// This package has the automatically generated typed clients. +`), + // GeneratorFunc returns a list of generators. Each generator makes a + // single file. + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = []generator.Generator{ + // Always generate a "doc.go" file. + generator.DefaultGen{OptionalName: "doc"}, + } + // Since we want a file per type that we generate a client for, we + // have to provide a function for this. + for _, t := range typeList { + generators = append(generators, &genClientForType{ + DefaultGen: generator.DefaultGen{ + OptionalName: strings.ToLower(c.Namers["private"].Name(t)), + }, + outputPackage: groupVersionClientPackage, + clientsetPackage: clientsetPackage, + group: gv.Group.NonEmpty(), + version: gv.Version.String(), + groupGoName: groupGoName, + typeToMatch: t, + imports: generator.NewImportTracker(), + }) + } + + generators = append(generators, &genGroup{ + DefaultGen: generator.DefaultGen{ + OptionalName: groupPackageName + "_client", + }, + outputPackage: groupVersionClientPackage, + inputPackage: inputPackage, + clientsetPackage: clientsetPackage, + group: gv.Group.NonEmpty(), + version: gv.Version.String(), + groupGoName: groupGoName, + apiPath: apiPath, + types: typeList, + imports: generator.NewImportTracker(), + }) + + expansionFileName := "generated_expansion" + generators = append(generators, &genExpansion{ + groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage), + DefaultGen: generator.DefaultGen{ + OptionalName: expansionFileName, + }, + types: typeList, + }) + + return generators + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + return util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient + }, + } +} + +func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package { + return &generator.DefaultPackage{ + PackageName: customArgs.ClientsetName, + PackagePath: clientsetPackage, + HeaderText: boilerplate, + PackageDocumentation: []byte( + `// This package has the automatically generated clientset. +`), + // GeneratorFunc returns a list of generators. Each generator generates a + // single file. + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = []generator.Generator{ + // Always generate a "doc.go" file. + generator.DefaultGen{OptionalName: "doc"}, + + &genClientset{ + DefaultGen: generator.DefaultGen{ + OptionalName: "clientset", + }, + groups: customArgs.Groups, + groupGoNames: groupGoNames, + clientsetPackage: clientsetPackage, + outputPackage: customArgs.ClientsetName, + imports: generator.NewImportTracker(), + }, + } + return generators + }, + } +} + +func packageForScheme(customArgs *clientgenargs.CustomArgs, clientsetPackage string, srcTreePath string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package { + schemePackage := filepath.Join(clientsetPackage, "scheme") + + // create runtime.Registry for internal client because it has to know about group versions + internalClient := false +NextGroup: + for _, group := range customArgs.Groups { + for _, v := range group.Versions { + if v.String() == "" { + internalClient = true + break NextGroup + } + } + } + + return &generator.DefaultPackage{ + PackageName: "scheme", + PackagePath: schemePackage, + HeaderText: boilerplate, + PackageDocumentation: []byte( + `// This package contains the scheme of the automatically generated clientset. +`), + // GeneratorFunc returns a list of generators. Each generator generates a + // single file. + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = []generator.Generator{ + // Always generate a "doc.go" file. + generator.DefaultGen{OptionalName: "doc"}, + + &scheme.GenScheme{ + DefaultGen: generator.DefaultGen{ + OptionalName: "register", + }, + InputPackages: customArgs.GroupVersionPackages(), + OutputPackage: schemePackage, + OutputPath: filepath.Join(srcTreePath, schemePackage), + Groups: customArgs.Groups, + GroupGoNames: groupGoNames, + ImportTracker: generator.NewImportTracker(), + CreateRegistry: internalClient, + }, + } + return generators + }, + } +} + +// applyGroupOverrides applies group name overrides to each package, if applicable. If there is a +// comment of the form "// +groupName=somegroup" or "// +groupName=somegroup.foo.bar.io", use the +// first field (somegroup) as the name of the group in Go code, e.g. as the func name in a clientset. +// +// If the first field of the groupName is not unique within the clientset, use "// +groupName=unique +func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.CustomArgs) { + // Create a map from "old GV" to "new GV" so we know what changes we need to make. + changes := make(map[clientgentypes.GroupVersion]clientgentypes.GroupVersion) + for gv, inputDir := range customArgs.GroupVersionPackages() { + p := universe.Package(inputDir) + if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil { + newGV := clientgentypes.GroupVersion{ + Group: clientgentypes.Group(override[0]), + Version: gv.Version, + } + changes[gv] = newGV + } + } + + // Modify customArgs.Groups based on the groupName overrides. + newGroups := make([]clientgentypes.GroupVersions, 0, len(customArgs.Groups)) + for _, gvs := range customArgs.Groups { + gv := clientgentypes.GroupVersion{ + Group: gvs.Group, + Version: gvs.Versions[0].Version, // we only need a version, and the first will do + } + if newGV, ok := changes[gv]; ok { + // There's an override, so use it. + newGVS := clientgentypes.GroupVersions{ + PackageName: gvs.PackageName, + Group: newGV.Group, + Versions: gvs.Versions, + } + newGroups = append(newGroups, newGVS) + } else { + // No override. + newGroups = append(newGroups, gvs) + } + } + customArgs.Groups = newGroups +} + +// Packages makes the client package definition. +func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + boilerplate, err := arguments.LoadGoBoilerplate() + if err != nil { + klog.Fatalf("Failed loading boilerplate: %v", err) + } + + customArgs, ok := arguments.CustomArgs.(*clientgenargs.CustomArgs) + if !ok { + klog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.CustomArgs") + } + includedTypesOverrides := customArgs.IncludedTypesOverrides + + applyGroupOverrides(context.Universe, customArgs) + + gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{} + groupGoNames := make(map[clientgentypes.GroupVersion]string) + for gv, inputDir := range customArgs.GroupVersionPackages() { + p := context.Universe.Package(path.Vendorless(inputDir)) + + // If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as + // the Go group identifier in CamelCase. It defaults + groupGoNames[gv] = namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0]) + if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil { + groupGoNames[gv] = namer.IC(override[0]) + } + + // Package are indexed with the vendor prefix stripped + for n, t := range p.Types { + // filter out types which are not included in user specified overrides. + typesOverride, ok := includedTypesOverrides[gv] + if ok { + found := false + for _, typeStr := range typesOverride { + if typeStr == n { + found = true + break + } + } + if !found { + continue + } + } else { + // User has not specified any override for this group version. + // filter out types which dont have genclient. + if tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)); !tags.GenerateClient { + continue + } + } + if _, found := gvToTypes[gv]; !found { + gvToTypes[gv] = []*types.Type{} + } + gvToTypes[gv] = append(gvToTypes[gv], t) + } + } + + var packageList []generator.Package + clientsetPackage := filepath.Join(arguments.OutputPackagePath, customArgs.ClientsetName) + + packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate)) + packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, groupGoNames, boilerplate)) + if customArgs.FakeClient { + packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate)) + } + + // If --clientset-only=true, we don't regenerate the individual typed clients. + if customArgs.ClientsetOnly { + return generator.Packages(packageList) + } + + orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} + gvPackages := customArgs.GroupVersionPackages() + for _, group := range customArgs.Groups { + for _, version := range group.Versions { + gv := clientgentypes.GroupVersion{Group: group.Group, Version: version.Version} + types := gvToTypes[gv] + inputPath := gvPackages[gv] + packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate)) + if customArgs.FakeClient { + packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], inputPath, boilerplate)) + } + } + } + + return generator.Packages(packageList) +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/BUILD new file mode 100644 index 0000000000..4e6e24ed4a --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/BUILD @@ -0,0 +1,41 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "fake_client_generator.go", + "generator_fake_for_clientset.go", + "generator_fake_for_group.go", + "generator_fake_for_type.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake", + importpath = "k8s.io/code-generator/cmd/client-gen/generators/fake", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/scheme:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/path:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//vendor/k8s.io/gengo/generator:go_default_library", + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go new file mode 100644 index 0000000000..4b3854be6e --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go @@ -0,0 +1,130 @@ +/* +Copyright 2015 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 fake + +import ( + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/types" + + clientgenargs "k8s.io/code-generator/cmd/client-gen/args" + scheme "k8s.io/code-generator/cmd/client-gen/generators/scheme" + "k8s.io/code-generator/cmd/client-gen/generators/util" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" +) + +func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, inputPackage string, boilerplate []byte) generator.Package { + outputPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty()), "fake") + // TODO: should make this a function, called by here and in client-generator.go + realClientPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty())) + return &generator.DefaultPackage{ + PackageName: "fake", + PackagePath: outputPackage, + HeaderText: boilerplate, + PackageDocumentation: []byte( + `// Package fake has the automatically generated clients. +`), + // GeneratorFunc returns a list of generators. Each generator makes a + // single file. + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = []generator.Generator{ + // Always generate a "doc.go" file. + generator.DefaultGen{OptionalName: "doc"}, + } + // Since we want a file per type that we generate a client for, we + // have to provide a function for this. + for _, t := range typeList { + generators = append(generators, &genFakeForType{ + DefaultGen: generator.DefaultGen{ + OptionalName: "fake_" + strings.ToLower(c.Namers["private"].Name(t)), + }, + outputPackage: outputPackage, + inputPackage: inputPackage, + group: gv.Group.NonEmpty(), + version: gv.Version.String(), + groupGoName: groupGoName, + typeToMatch: t, + imports: generator.NewImportTracker(), + }) + } + + generators = append(generators, &genFakeForGroup{ + DefaultGen: generator.DefaultGen{ + OptionalName: "fake_" + groupPackageName + "_client", + }, + outputPackage: outputPackage, + realClientPackage: realClientPackage, + group: gv.Group.NonEmpty(), + version: gv.Version.String(), + groupGoName: groupGoName, + types: typeList, + imports: generator.NewImportTracker(), + }) + return generators + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + return util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient + }, + } +} + +func PackageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package { + return &generator.DefaultPackage{ + // TODO: we'll generate fake clientset for different release in the future. + // Package name and path are hard coded for now. + PackageName: "fake", + PackagePath: filepath.Join(clientsetPackage, "fake"), + HeaderText: boilerplate, + PackageDocumentation: []byte( + `// This package has the automatically generated fake clientset. +`), + // GeneratorFunc returns a list of generators. Each generator generates a + // single file. + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = []generator.Generator{ + // Always generate a "doc.go" file. + generator.DefaultGen{OptionalName: "doc"}, + + &genClientset{ + DefaultGen: generator.DefaultGen{ + OptionalName: "clientset_generated", + }, + groups: customArgs.Groups, + groupGoNames: groupGoNames, + fakeClientsetPackage: clientsetPackage, + outputPackage: "fake", + imports: generator.NewImportTracker(), + realClientsetPackage: clientsetPackage, + }, + &scheme.GenScheme{ + DefaultGen: generator.DefaultGen{ + OptionalName: "register", + }, + InputPackages: customArgs.GroupVersionPackages(), + OutputPackage: clientsetPackage, + Groups: customArgs.Groups, + GroupGoNames: groupGoNames, + ImportTracker: generator.NewImportTracker(), + PrivateScheme: true, + }, + } + return generators + }, + } +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go new file mode 100644 index 0000000000..80e4361b77 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go @@ -0,0 +1,169 @@ +/* +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 fake + +import ( + "fmt" + "io" + "path/filepath" + "strings" + + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// genClientset generates a package for a clientset. +type genClientset struct { + generator.DefaultGen + groups []clientgentypes.GroupVersions + groupGoNames map[clientgentypes.GroupVersion]string + fakeClientsetPackage string + outputPackage string + imports namer.ImportTracker + clientsetGenerated bool + // the import path of the generated real clientset. + realClientsetPackage string +} + +var _ generator.Generator = &genClientset{} + +func (g *genClientset) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +// We only want to call GenerateType() once. +func (g *genClientset) Filter(c *generator.Context, t *types.Type) bool { + ret := !g.clientsetGenerated + g.clientsetGenerated = true + return ret +} + +func (g *genClientset) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + for _, group := range g.groups { + for _, version := range group.Versions { + groupClientPackage := filepath.Join(g.fakeClientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty())) + fakeGroupClientPackage := filepath.Join(groupClientPackage, "fake") + + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) + imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.NonEmpty()), groupClientPackage)) + imports = append(imports, fmt.Sprintf("fake%s%s \"%s\"", groupAlias, strings.ToLower(version.NonEmpty()), fakeGroupClientPackage)) + } + } + // the package that has the clientset Interface + imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.realClientsetPackage)) + // imports for the code in commonTemplate + imports = append(imports, + "k8s.io/client-go/testing", + "k8s.io/client-go/discovery", + "fakediscovery \"k8s.io/client-go/discovery/fake\"", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/watch", + ) + + return +} + +func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + // TODO: We actually don't need any type information to generate the clientset, + // perhaps we can adapt the go2ild framework to this kind of usage. + sw := generator.NewSnippetWriter(w, c, "$", "$") + + allGroups := clientgentypes.ToGroupVersionInfo(g.groups, g.groupGoNames) + + sw.Do(common, nil) + sw.Do(checkImpl, nil) + + for _, group := range allGroups { + m := map[string]interface{}{ + "group": group.Group, + "version": group.Version, + "PackageAlias": group.PackageAlias, + "GroupGoName": group.GroupGoName, + "Version": namer.IC(group.Version.String()), + } + + sw.Do(clientsetInterfaceImplTemplate, m) + } + + return sw.Error() +} + +// This part of code is version-independent, unchanging. +var common = ` +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} +` + +var checkImpl = ` +var _ clientset.Interface = &Clientset{} +` + +var clientsetInterfaceImplTemplate = ` +// $.GroupGoName$$.Version$ retrieves the $.GroupGoName$$.Version$Client +func (c *Clientset) $.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface { + return &fake$.PackageAlias$.Fake$.GroupGoName$$.Version${Fake: &c.Fake} +} +` + +var clientsetInterfaceDefaultVersionImpl = ` +// $.GroupGoName$ retrieves the $.GroupGoName$$.Version$Client +func (c *Clientset) $.GroupGoName$() $.PackageAlias$.$.GroupGoName$$.Version$Interface { + return &fake$.PackageAlias$.Fake$.GroupGoName$$.Version${Fake: &c.Fake} +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go new file mode 100644 index 0000000000..8f4d5785ef --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go @@ -0,0 +1,130 @@ +/* +Copyright 2015 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 fake + +import ( + "fmt" + "io" + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" +) + +// genFakeForGroup produces a file for a group client, e.g. ExtensionsClient for the extension group. +type genFakeForGroup struct { + generator.DefaultGen + outputPackage string + realClientPackage string + group string + version string + groupGoName string + // types in this group + types []*types.Type + imports namer.ImportTracker + // If the genGroup has been called. This generator should only execute once. + called bool +} + +var _ generator.Generator = &genFakeForGroup{} + +// We only want to call GenerateType() once per group. +func (g *genFakeForGroup) Filter(c *generator.Context, t *types.Type) bool { + if !g.called { + g.called = true + return true + } + return false +} + +func (g *genFakeForGroup) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *genFakeForGroup) Imports(c *generator.Context) (imports []string) { + imports = g.imports.ImportLines() + if len(g.types) != 0 { + imports = append(imports, fmt.Sprintf("%s \"%s\"", strings.ToLower(filepath.Base(g.realClientPackage)), g.realClientPackage)) + } + return imports +} + +func (g *genFakeForGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + m := map[string]interface{}{ + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "Fake": c.Universe.Type(types.Name{Package: "k8s.io/client-go/testing", Name: "Fake"}), + "RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), + "RESTClient": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClient"}), + } + + sw.Do(groupClientTemplate, m) + for _, t := range g.types { + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + wrapper := map[string]interface{}{ + "type": t, + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "realClientPackage": strings.ToLower(filepath.Base(g.realClientPackage)), + } + if tags.NonNamespaced { + sw.Do(getterImplNonNamespaced, wrapper) + continue + } + sw.Do(getterImplNamespaced, wrapper) + } + sw.Do(getRESTClient, m) + return sw.Error() +} + +var groupClientTemplate = ` +type Fake$.GroupGoName$$.Version$ struct { + *$.Fake|raw$ +} +` + +var getterImplNamespaced = ` +func (c *Fake$.GroupGoName$$.Version$) $.type|publicPlural$(namespace string) $.realClientPackage$.$.type|public$Interface { + return &Fake$.type|publicPlural${c, namespace} +} +` + +var getterImplNonNamespaced = ` +func (c *Fake$.GroupGoName$$.Version$) $.type|publicPlural$() $.realClientPackage$.$.type|public$Interface { + return &Fake$.type|publicPlural${c} +} +` + +var getRESTClient = ` +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *Fake$.GroupGoName$$.Version$) RESTClient() $.RESTClientInterface|raw$ { + var ret *$.RESTClient|raw$ + return ret +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go new file mode 100644 index 0000000000..f5888aef15 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go @@ -0,0 +1,479 @@ +/* +Copyright 2015 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 fake + +import ( + "io" + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + "k8s.io/code-generator/cmd/client-gen/path" +) + +// genFakeForType produces a file for each top-level type. +type genFakeForType struct { + generator.DefaultGen + outputPackage string + group string + version string + groupGoName string + inputPackage string + typeToMatch *types.Type + imports namer.ImportTracker +} + +var _ generator.Generator = &genFakeForType{} + +// Filter ignores all but one type because we're making a single file per type. +func (g *genFakeForType) Filter(c *generator.Context, t *types.Type) bool { return t == g.typeToMatch } + +func (g *genFakeForType) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *genFakeForType) Imports(c *generator.Context) (imports []string) { + return g.imports.ImportLines() +} + +// Ideally, we'd like genStatus to return true if there is a subresource path +// registered for "status" in the API server, but we do not have that +// information, so genStatus returns true if the type has a status field. +func genStatus(t *types.Type) bool { + // Default to true if we have a Status member + hasStatus := false + for _, m := range t.Members { + if m.Name == "Status" { + hasStatus = true + break + } + } + + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + return hasStatus && !tags.NoStatus +} + +// hasObjectMeta returns true if the type has a ObjectMeta field. +func hasObjectMeta(t *types.Type) bool { + for _, m := range t.Members { + if m.Embedded == true && m.Name == "ObjectMeta" { + return true + } + } + return false +} + +// GenerateType makes the body of a file implementing the individual typed client for type t. +func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + pkg := filepath.Base(t.Name.Package) + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + canonicalGroup := g.group + if canonicalGroup == "core" { + canonicalGroup = "" + } + + groupName := g.group + if g.group == "core" { + groupName = "" + } + + // allow user to define a group name that's different from the one parsed from the directory. + p := c.Universe.Package(path.Vendorless(g.inputPackage)) + if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil { + groupName = override[0] + } + + const pkgClientGoTesting = "k8s.io/client-go/testing" + m := map[string]interface{}{ + "type": t, + "inputType": t, + "resultType": t, + "subresourcePath": "", + "package": pkg, + "Package": namer.IC(pkg), + "namespaced": !tags.NonNamespaced, + "Group": namer.IC(g.group), + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "group": canonicalGroup, + "groupName": groupName, + "version": g.version, + "DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}), + "ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}), + "GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}), + "Everything": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/labels", Name: "Everything"}), + "GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersionResource"}), + "GroupVersionKind": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersionKind"}), + "PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}), + "watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}), + + "NewRootListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootListAction"}), + "NewListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListAction"}), + "NewRootGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetAction"}), + "NewGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetAction"}), + "NewRootDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteAction"}), + "NewDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteAction"}), + "NewRootDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteCollectionAction"}), + "NewDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteCollectionAction"}), + "NewRootUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateAction"}), + "NewUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateAction"}), + "NewRootCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateAction"}), + "NewCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateAction"}), + "NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchAction"}), + "NewWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchAction"}), + "NewCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceAction"}), + "NewRootCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceAction"}), + "NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceAction"}), + "NewGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceAction"}), + "NewRootGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceAction"}), + "NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceAction"}), + "NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchAction"}), + "NewPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchAction"}), + "NewRootPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchSubresourceAction"}), + "NewPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchSubresourceAction"}), + "ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "ExtractFromListOptions"}), + } + + if tags.NonNamespaced { + sw.Do(structNonNamespaced, m) + } else { + sw.Do(structNamespaced, m) + } + + if tags.NoVerbs { + return sw.Error() + } + sw.Do(resource, m) + sw.Do(kind, m) + + if tags.HasVerb("get") { + sw.Do(getTemplate, m) + } + if tags.HasVerb("list") { + if hasObjectMeta(t) { + sw.Do(listUsingOptionsTemplate, m) + } else { + sw.Do(listTemplate, m) + } + } + if tags.HasVerb("watch") { + sw.Do(watchTemplate, m) + } + + if tags.HasVerb("create") { + sw.Do(createTemplate, m) + } + if tags.HasVerb("update") { + sw.Do(updateTemplate, m) + } + if tags.HasVerb("updateStatus") && genStatus(t) { + sw.Do(updateStatusTemplate, m) + } + if tags.HasVerb("delete") { + sw.Do(deleteTemplate, m) + } + if tags.HasVerb("deleteCollection") { + sw.Do(deleteCollectionTemplate, m) + } + if tags.HasVerb("patch") { + sw.Do(patchTemplate, m) + } + + // generate extended client methods + for _, e := range tags.Extensions { + inputType := *t + resultType := *t + if len(e.InputTypeOverride) > 0 { + if name, pkg := e.Input(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + inputType = *newType + } else { + inputType.Name.Name = e.InputTypeOverride + } + } + if len(e.ResultTypeOverride) > 0 { + if name, pkg := e.Result(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + resultType = *newType + } else { + resultType.Name.Name = e.ResultTypeOverride + } + } + m["inputType"] = &inputType + m["resultType"] = &resultType + m["subresourcePath"] = e.SubResourcePath + + if e.HasVerb("get") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, getSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, getTemplate), m) + } + } + + if e.HasVerb("list") { + + sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) + } + + // TODO: Figure out schemantic for watching a sub-resource. + if e.HasVerb("watch") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, watchTemplate), m) + } + + if e.HasVerb("create") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, createSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, createTemplate), m) + } + } + + if e.HasVerb("update") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateTemplate), m) + } + } + + // TODO: Figure out schemantic for deleting a sub-resource (what arguments + // are passed, does it need two names? etc. + if e.HasVerb("delete") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, deleteTemplate), m) + } + + if e.HasVerb("patch") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m) + } + } + + return sw.Error() +} + +// adjustTemplate adjust the origin verb template using the expansion name. +// TODO: Make the verbs in templates parametrized so the strings.Replace() is +// not needed. +func adjustTemplate(name, verbType, template string) string { + return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1) +} + +// template for the struct that implements the type's interface +var structNamespaced = ` +// Fake$.type|publicPlural$ implements $.type|public$Interface +type Fake$.type|publicPlural$ struct { + Fake *Fake$.GroupGoName$$.Version$ + ns string +} +` + +// template for the struct that implements the type's interface +var structNonNamespaced = ` +// Fake$.type|publicPlural$ implements $.type|public$Interface +type Fake$.type|publicPlural$ struct { + Fake *Fake$.GroupGoName$$.Version$ +} +` + +var resource = ` +var $.type|allLowercasePlural$Resource = $.GroupVersionResource|raw${Group: "$.groupName$", Version: "$.version$", Resource: "$.type|resource$"} +` + +var kind = ` +var $.type|allLowercasePlural$Kind = $.GroupVersionKind|raw${Group: "$.groupName$", Version: "$.version$", Kind: "$.type|singularKind$"} +` + +var listTemplate = ` +// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors. +func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{}) + $else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.type|raw$List), err +} +` + +var listUsingOptionsTemplate = ` +// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors. +func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{}) + $else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$ + if obj == nil { + return nil, err + } + + label, _, _ := $.ExtractFromListOptions|raw$(opts) + if label == nil { + label = $.Everything|raw$() + } + list := &$.type|raw$List{ListMeta: obj.(*$.type|raw$List).ListMeta} + for _, item := range obj.(*$.type|raw$List).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} +` + +var getTemplate = ` +// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any. +func (c *Fake$.type|publicPlural$) Get(name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewGetAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.resultType|raw${}) + $else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, name), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var getSubresourceTemplate = ` +// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any. +func (c *Fake$.type|publicPlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${}) + $else$Invokes($.NewRootGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var deleteTemplate = ` +// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs. +func (c *Fake$.type|publicPlural$) Delete(name string, options *$.DeleteOptions|raw$) error { + _, err := c.Fake. + $if .namespaced$Invokes($.NewDeleteAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.type|raw${}) + $else$Invokes($.NewRootDeleteAction|raw$($.type|allLowercasePlural$Resource, name), &$.type|raw${})$end$ + return err +} +` + +var deleteCollectionTemplate = ` +// DeleteCollection deletes a collection of objects. +func (c *Fake$.type|publicPlural$) DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error { + $if .namespaced$action := $.NewDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, c.ns, listOptions) + $else$action := $.NewRootDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, listOptions) + $end$ + _, err := c.Fake.Invokes(action, &$.type|raw$List{}) + return err +} +` +var createTemplate = ` +// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *Fake$.type|publicPlural$) Create($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewCreateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${}) + $else$Invokes($.NewRootCreateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var createSubresourceTemplate = ` +// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *Fake$.type|publicPlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$), &$.resultType|raw${}) + $else$Invokes($.NewRootCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var updateTemplate = ` +// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *Fake$.type|publicPlural$) Update($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewUpdateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${}) + $else$Invokes($.NewRootUpdateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var updateSubresourceTemplate = ` +// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *Fake$.type|publicPlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$), &$.inputType|raw${}) + $else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` + +var updateStatusTemplate = ` +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *Fake$.type|publicPlural$) UpdateStatus($.type|private$ *$.type|raw$) (*$.type|raw$, error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "status", c.ns, $.type|private$), &$.type|raw${}) + $else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "status", $.type|private$), &$.type|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.type|raw$), err +} +` + +var watchTemplate = ` +// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$. +func (c *Fake$.type|publicPlural$) Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error) { + return c.Fake. + $if .namespaced$InvokesWatch($.NewWatchAction|raw$($.type|allLowercasePlural$Resource, c.ns, opts)) + $else$InvokesWatch($.NewRootWatchAction|raw$($.type|allLowercasePlural$Resource, opts))$end$ +} +` + +var patchTemplate = ` +// Patch applies the patch and returns the patched $.resultType|private$. +func (c *Fake$.type|publicPlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err error) { + obj, err := c.Fake. + $if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, name, pt, data, subresources... ), &$.resultType|raw${}) + $else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, name, pt, data, subresources...), &$.resultType|raw${})$end$ + if obj == nil { + return nil, err + } + return obj.(*$.resultType|raw$), err +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go new file mode 100644 index 0000000000..a1e67dcbdf --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go @@ -0,0 +1,178 @@ +/* +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 generators + +import ( + "fmt" + "io" + "path/filepath" + "strings" + + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// genClientset generates a package for a clientset. +type genClientset struct { + generator.DefaultGen + groups []clientgentypes.GroupVersions + groupGoNames map[clientgentypes.GroupVersion]string + clientsetPackage string + outputPackage string + imports namer.ImportTracker + clientsetGenerated bool +} + +var _ generator.Generator = &genClientset{} + +func (g *genClientset) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +// We only want to call GenerateType() once. +func (g *genClientset) Filter(c *generator.Context, t *types.Type) bool { + ret := !g.clientsetGenerated + g.clientsetGenerated = true + return ret +} + +func (g *genClientset) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + for _, group := range g.groups { + for _, version := range group.Versions { + typedClientPath := filepath.Join(g.clientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty())) + groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) + imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.NonEmpty()), typedClientPath)) + } + } + return +} + +func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + // TODO: We actually don't need any type information to generate the clientset, + // perhaps we can adapt the go2ild framework to this kind of usage. + sw := generator.NewSnippetWriter(w, c, "$", "$") + + allGroups := clientgentypes.ToGroupVersionInfo(g.groups, g.groupGoNames) + m := map[string]interface{}{ + "allGroups": allGroups, + "Config": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}), + "DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}), + "RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), + "DiscoveryInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/discovery", Name: "DiscoveryInterface"}), + "DiscoveryClient": c.Universe.Type(types.Name{Package: "k8s.io/client-go/discovery", Name: "DiscoveryClient"}), + "NewDiscoveryClientForConfig": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfig"}), + "NewDiscoveryClientForConfigOrDie": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfigOrDie"}), + "NewDiscoveryClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClient"}), + "flowcontrolNewTokenBucketRateLimiter": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/flowcontrol", Name: "NewTokenBucketRateLimiter"}), + } + sw.Do(clientsetInterface, m) + sw.Do(clientsetTemplate, m) + for _, g := range allGroups { + sw.Do(clientsetInterfaceImplTemplate, g) + } + sw.Do(getDiscoveryTemplate, m) + sw.Do(newClientsetForConfigTemplate, m) + sw.Do(newClientsetForConfigOrDieTemplate, m) + sw.Do(newClientsetForRESTClientTemplate, m) + + return sw.Error() +} + +var clientsetInterface = ` +type Interface interface { + Discovery() $.DiscoveryInterface|raw$ + $range .allGroups$$.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface + $end$ +} +` + +var clientsetTemplate = ` +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *$.DiscoveryClient|raw$ + $range .allGroups$$.LowerCaseGroupGoName$$.Version$ *$.PackageAlias$.$.GroupGoName$$.Version$Client + $end$ +} +` + +var clientsetInterfaceImplTemplate = ` +// $.GroupGoName$$.Version$ retrieves the $.GroupGoName$$.Version$Client +func (c *Clientset) $.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface { + return c.$.LowerCaseGroupGoName$$.Version$ +} +` + +var getDiscoveryTemplate = ` +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() $.DiscoveryInterface|raw$ { + if c == nil { + return nil + } + return c.DiscoveryClient +} +` + +var newClientsetForConfigTemplate = ` +// NewForConfig creates a new Clientset for the given config. +func NewForConfig(c *$.Config|raw$) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + configShallowCopy.RateLimiter = $.flowcontrolNewTokenBucketRateLimiter|raw$(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error +$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$, err =$.PackageAlias$.NewForConfig(&configShallowCopy) + if err!=nil { + return nil, err + } +$end$ + cs.DiscoveryClient, err = $.NewDiscoveryClientForConfig|raw$(&configShallowCopy) + if err!=nil { + return nil, err + } + return &cs, nil +} +` + +var newClientsetForConfigOrDieTemplate = ` +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *$.Config|raw$) *Clientset { + var cs Clientset +$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$ =$.PackageAlias$.NewForConfigOrDie(c) +$end$ + cs.DiscoveryClient = $.NewDiscoveryClientForConfigOrDie|raw$(c) + return &cs +} +` + +var newClientsetForRESTClientTemplate = ` +// New creates a new Clientset for the given RESTClient. +func New(c $.RESTClientInterface|raw$) *Clientset { + var cs Clientset +$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$ =$.PackageAlias$.New(c) +$end$ + cs.DiscoveryClient = $.NewDiscoveryClient|raw$(c) + return &cs +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.go new file mode 100644 index 0000000000..f47c079e02 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.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 generators + +import ( + "io" + "os" + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/types" +) + +// genExpansion produces a file for a group client, e.g. ExtensionsClient for the extension group. +type genExpansion struct { + generator.DefaultGen + groupPackagePath string + // types in a group + types []*types.Type +} + +// We only want to call GenerateType() once per group. +func (g *genExpansion) Filter(c *generator.Context, t *types.Type) bool { + return len(g.types) == 0 || t == g.types[0] +} + +func (g *genExpansion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + for _, t := range g.types { + if _, err := os.Stat(filepath.Join(g.groupPackagePath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) { + sw.Do(expansionInterfaceTemplate, t) + } + } + return sw.Error() +} + +var expansionInterfaceTemplate = ` +type $.|public$Expansion interface {} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go new file mode 100644 index 0000000000..fd59715c42 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go @@ -0,0 +1,247 @@ +/* +Copyright 2015 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 generators + +import ( + "io" + "path/filepath" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + "k8s.io/code-generator/cmd/client-gen/path" +) + +// genGroup produces a file for a group client, e.g. ExtensionsClient for the extension group. +type genGroup struct { + generator.DefaultGen + outputPackage string + group string + version string + groupGoName string + apiPath string + // types in this group + types []*types.Type + imports namer.ImportTracker + inputPackage string + clientsetPackage string + // If the genGroup has been called. This generator should only execute once. + called bool +} + +var _ generator.Generator = &genGroup{} + +// We only want to call GenerateType() once per group. +func (g *genGroup) Filter(c *generator.Context, t *types.Type) bool { + if !g.called { + g.called = true + return true + } + return false +} + +func (g *genGroup) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *genGroup) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + imports = append(imports, filepath.Join(g.clientsetPackage, "scheme")) + return +} + +func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + apiPath := func(group string) string { + if group == "core" { + return `"/api"` + } + return `"` + g.apiPath + `"` + } + + groupName := g.group + if g.group == "core" { + groupName = "" + } + // allow user to define a group name that's different from the one parsed from the directory. + p := c.Universe.Package(path.Vendorless(g.inputPackage)) + if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil { + groupName = override[0] + } + + m := map[string]interface{}{ + "group": g.group, + "version": g.version, + "groupName": groupName, + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "types": g.types, + "apiPath": apiPath(g.group), + "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), + "runtimeAPIVersionInternal": c.Universe.Variable(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "APIVersionInternal"}), + "serializerDirectCodecFactory": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "DirectCodecFactory"}), + "restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}), + "restDefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}), + "restRESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), + "restRESTClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientFor"}), + "SchemeGroupVersion": c.Universe.Variable(types.Name{Package: path.Vendorless(g.inputPackage), Name: "SchemeGroupVersion"}), + } + sw.Do(groupInterfaceTemplate, m) + sw.Do(groupClientTemplate, m) + for _, t := range g.types { + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + wrapper := map[string]interface{}{ + "type": t, + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + } + if tags.NonNamespaced { + sw.Do(getterImplNonNamespaced, wrapper) + } else { + sw.Do(getterImplNamespaced, wrapper) + } + } + sw.Do(newClientForConfigTemplate, m) + sw.Do(newClientForConfigOrDieTemplate, m) + sw.Do(newClientForRESTClientTemplate, m) + if g.version == "" { + sw.Do(setInternalVersionClientDefaultsTemplate, m) + } else { + sw.Do(setClientDefaultsTemplate, m) + } + sw.Do(getRESTClient, m) + + return sw.Error() +} + +var groupInterfaceTemplate = ` +type $.GroupGoName$$.Version$Interface interface { + RESTClient() $.restRESTClientInterface|raw$ + $range .types$ $.|publicPlural$Getter + $end$ +} +` + +var groupClientTemplate = ` +// $.GroupGoName$$.Version$Client is used to interact with features provided by the $.groupName$ group. +type $.GroupGoName$$.Version$Client struct { + restClient $.restRESTClientInterface|raw$ +} +` + +var getterImplNamespaced = ` +func (c *$.GroupGoName$$.Version$Client) $.type|publicPlural$(namespace string) $.type|public$Interface { + return new$.type|publicPlural$(c, namespace) +} +` + +var getterImplNonNamespaced = ` +func (c *$.GroupGoName$$.Version$Client) $.type|publicPlural$() $.type|public$Interface { + return new$.type|publicPlural$(c) +} +` + +var newClientForConfigTemplate = ` +// NewForConfig creates a new $.GroupGoName$$.Version$Client for the given config. +func NewForConfig(c *$.restConfig|raw$) (*$.GroupGoName$$.Version$Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := $.restRESTClientFor|raw$(&config) + if err != nil { + return nil, err + } + return &$.GroupGoName$$.Version$Client{client}, nil +} +` + +var newClientForConfigOrDieTemplate = ` +// NewForConfigOrDie creates a new $.GroupGoName$$.Version$Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *$.restConfig|raw$) *$.GroupGoName$$.Version$Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} +` + +var getRESTClient = ` +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *$.GroupGoName$$.Version$Client) RESTClient() $.restRESTClientInterface|raw$ { + if c == nil { + return nil + } + return c.restClient +} +` + +var newClientForRESTClientTemplate = ` +// New creates a new $.GroupGoName$$.Version$Client for the given RESTClient. +func New(c $.restRESTClientInterface|raw$) *$.GroupGoName$$.Version$Client { + return &$.GroupGoName$$.Version$Client{c} +} +` + +var setInternalVersionClientDefaultsTemplate = ` +func setConfigDefaults(config *$.restConfig|raw$) error { + config.APIPath = $.apiPath$ + if config.UserAgent == "" { + config.UserAgent = $.restDefaultKubernetesUserAgent|raw$() + } + if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0].Group { + gv := scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0] + config.GroupVersion = &gv + } + config.NegotiatedSerializer = scheme.Codecs + + if config.QPS == 0 { + config.QPS = 5 + } + if config.Burst == 0 { + config.Burst = 10 + } + + return nil +} +` + +var setClientDefaultsTemplate = ` +func setConfigDefaults(config *$.restConfig|raw$) error { + gv := $.SchemeGroupVersion|raw$ + config.GroupVersion = &gv + config.APIPath = $.apiPath$ + config.NegotiatedSerializer = $.serializerDirectCodecFactory|raw${CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = $.restDefaultKubernetesUserAgent|raw$() + } + + return nil +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go new file mode 100644 index 0000000000..3e8fc7c4c6 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go @@ -0,0 +1,599 @@ +/* +Copyright 2015 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 generators + +import ( + "io" + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" +) + +// genClientForType produces a file for each top-level type. +type genClientForType struct { + generator.DefaultGen + outputPackage string + clientsetPackage string + group string + version string + groupGoName string + typeToMatch *types.Type + imports namer.ImportTracker +} + +var _ generator.Generator = &genClientForType{} + +// Filter ignores all but one type because we're making a single file per type. +func (g *genClientForType) Filter(c *generator.Context, t *types.Type) bool { return t == g.typeToMatch } + +func (g *genClientForType) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *genClientForType) Imports(c *generator.Context) (imports []string) { + return g.imports.ImportLines() +} + +// Ideally, we'd like genStatus to return true if there is a subresource path +// registered for "status" in the API server, but we do not have that +// information, so genStatus returns true if the type has a status field. +func genStatus(t *types.Type) bool { + // Default to true if we have a Status member + hasStatus := false + for _, m := range t.Members { + if m.Name == "Status" { + hasStatus = true + break + } + } + return hasStatus && !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).NoStatus +} + +// GenerateType makes the body of a file implementing the individual typed client for type t. +func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + pkg := filepath.Base(t.Name.Package) + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + type extendedInterfaceMethod struct { + template string + args map[string]interface{} + } + extendedMethods := []extendedInterfaceMethod{} + for _, e := range tags.Extensions { + inputType := *t + resultType := *t + // TODO: Extract this to some helper method as this code is copied into + // 2 other places. + if len(e.InputTypeOverride) > 0 { + if name, pkg := e.Input(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + inputType = *newType + } else { + inputType.Name.Name = e.InputTypeOverride + } + } + if len(e.ResultTypeOverride) > 0 { + if name, pkg := e.Result(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + resultType = *newType + } else { + resultType.Name.Name = e.ResultTypeOverride + } + } + var updatedVerbtemplate string + if _, exists := subresourceDefaultVerbTemplates[e.VerbType]; e.IsSubresource() && exists { + updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(subresourceDefaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(") + } else { + updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(") + } + extendedMethods = append(extendedMethods, extendedInterfaceMethod{ + template: updatedVerbtemplate, + args: map[string]interface{}{ + "type": t, + "inputType": &inputType, + "resultType": &resultType, + "DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}), + "ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}), + "GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}), + "PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}), + }, + }) + } + m := map[string]interface{}{ + "type": t, + "inputType": t, + "resultType": t, + "package": pkg, + "Package": namer.IC(pkg), + "namespaced": !tags.NonNamespaced, + "Group": namer.IC(g.group), + "subresource": false, + "subresourcePath": "", + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}), + "ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}), + "GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}), + "PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}), + "watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}), + "RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), + "schemeParameterCodec": c.Universe.Variable(types.Name{Package: filepath.Join(g.clientsetPackage, "scheme"), Name: "ParameterCodec"}), + } + + sw.Do(getterComment, m) + if tags.NonNamespaced { + sw.Do(getterNonNamespaced, m) + } else { + sw.Do(getterNamespaced, m) + } + + sw.Do(interfaceTemplate1, m) + if !tags.NoVerbs { + if !genStatus(t) { + tags.SkipVerbs = append(tags.SkipVerbs, "updateStatus") + } + interfaceSuffix := "" + if len(extendedMethods) > 0 { + interfaceSuffix = "\n" + } + sw.Do("\n"+generateInterface(tags)+interfaceSuffix, m) + // add extended verbs into interface + for _, v := range extendedMethods { + sw.Do(v.template+interfaceSuffix, v.args) + } + + } + sw.Do(interfaceTemplate4, m) + + if tags.NonNamespaced { + sw.Do(structNonNamespaced, m) + sw.Do(newStructNonNamespaced, m) + } else { + sw.Do(structNamespaced, m) + sw.Do(newStructNamespaced, m) + } + + if tags.NoVerbs { + return sw.Error() + } + + if tags.HasVerb("get") { + sw.Do(getTemplate, m) + } + if tags.HasVerb("list") { + sw.Do(listTemplate, m) + } + if tags.HasVerb("watch") { + sw.Do(watchTemplate, m) + } + + if tags.HasVerb("create") { + sw.Do(createTemplate, m) + } + if tags.HasVerb("update") { + sw.Do(updateTemplate, m) + } + if tags.HasVerb("updateStatus") { + sw.Do(updateStatusTemplate, m) + } + if tags.HasVerb("delete") { + sw.Do(deleteTemplate, m) + } + if tags.HasVerb("deleteCollection") { + sw.Do(deleteCollectionTemplate, m) + } + if tags.HasVerb("patch") { + sw.Do(patchTemplate, m) + } + + // generate expansion methods + for _, e := range tags.Extensions { + inputType := *t + resultType := *t + if len(e.InputTypeOverride) > 0 { + if name, pkg := e.Input(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + inputType = *newType + } else { + inputType.Name.Name = e.InputTypeOverride + } + } + if len(e.ResultTypeOverride) > 0 { + if name, pkg := e.Result(); len(pkg) > 0 { + newType := c.Universe.Type(types.Name{Package: pkg, Name: name}) + resultType = *newType + } else { + resultType.Name.Name = e.ResultTypeOverride + } + } + m["inputType"] = &inputType + m["resultType"] = &resultType + m["subresourcePath"] = e.SubResourcePath + + if e.HasVerb("get") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, getSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, getTemplate), m) + } + } + + if e.HasVerb("list") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, listSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m) + } + } + + // TODO: Figure out schemantic for watching a sub-resource. + if e.HasVerb("watch") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, watchTemplate), m) + } + + if e.HasVerb("create") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, createSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, createTemplate), m) + } + } + + if e.HasVerb("update") { + if e.IsSubresource() { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateSubresourceTemplate), m) + } else { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateTemplate), m) + } + } + + // TODO: Figure out schemantic for deleting a sub-resource (what arguments + // are passed, does it need two names? etc. + if e.HasVerb("delete") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, deleteTemplate), m) + } + + if e.HasVerb("patch") { + sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m) + } + } + + return sw.Error() +} + +// adjustTemplate adjust the origin verb template using the expansion name. +// TODO: Make the verbs in templates parametrized so the strings.Replace() is +// not needed. +func adjustTemplate(name, verbType, template string) string { + return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1) +} + +func generateInterface(tags util.Tags) string { + // need an ordered list here to guarantee order of generated methods. + out := []string{} + for _, m := range util.SupportedVerbs { + if tags.HasVerb(m) { + out = append(out, defaultVerbTemplates[m]) + } + } + return strings.Join(out, "\n") +} + +var subresourceDefaultVerbTemplates = map[string]string{ + "create": `Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (*$.resultType|raw$, error)`, + "list": `List($.type|private$Name string, opts $.ListOptions|raw$) (*$.resultType|raw$List, error)`, + "update": `Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (*$.resultType|raw$, error)`, + "get": `Get($.type|private$Name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`, +} + +var defaultVerbTemplates = map[string]string{ + "create": `Create(*$.inputType|raw$) (*$.resultType|raw$, error)`, + "update": `Update(*$.inputType|raw$) (*$.resultType|raw$, error)`, + "updateStatus": `UpdateStatus(*$.type|raw$) (*$.type|raw$, error)`, + "delete": `Delete(name string, options *$.DeleteOptions|raw$) error`, + "deleteCollection": `DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error`, + "get": `Get(name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`, + "list": `List(opts $.ListOptions|raw$) (*$.resultType|raw$List, error)`, + "watch": `Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error)`, + "patch": `Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err error)`, +} + +// group client will implement this interface. +var getterComment = ` +// $.type|publicPlural$Getter has a method to return a $.type|public$Interface. +// A group's client should implement this interface.` + +var getterNamespaced = ` +type $.type|publicPlural$Getter interface { + $.type|publicPlural$(namespace string) $.type|public$Interface +} +` + +var getterNonNamespaced = ` +type $.type|publicPlural$Getter interface { + $.type|publicPlural$() $.type|public$Interface +} +` + +// this type's interface, typed client will implement this interface. +var interfaceTemplate1 = ` +// $.type|public$Interface has methods to work with $.type|public$ resources. +type $.type|public$Interface interface {` + +var interfaceTemplate4 = ` + $.type|public$Expansion +} +` + +// template for the struct that implements the type's interface +var structNamespaced = ` +// $.type|privatePlural$ implements $.type|public$Interface +type $.type|privatePlural$ struct { + client $.RESTClientInterface|raw$ + ns string +} +` + +// template for the struct that implements the type's interface +var structNonNamespaced = ` +// $.type|privatePlural$ implements $.type|public$Interface +type $.type|privatePlural$ struct { + client $.RESTClientInterface|raw$ +} +` + +var newStructNamespaced = ` +// new$.type|publicPlural$ returns a $.type|publicPlural$ +func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ { + return &$.type|privatePlural${ + client: c.RESTClient(), + ns: namespace, + } +} +` + +var newStructNonNamespaced = ` +// new$.type|publicPlural$ returns a $.type|publicPlural$ +func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ { + return &$.type|privatePlural${ + client: c.RESTClient(), + } +} +` +var listTemplate = ` +// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors. +func (c *$.type|privatePlural$) List(opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil{ + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &$.resultType|raw$List{} + err = c.client.Get(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + VersionedParams(&opts, $.schemeParameterCodec|raw$). + Timeout(timeout). + Do(). + Into(result) + return +} +` + +var listSubresourceTemplate = ` +// List takes $.type|raw$ name, label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors. +func (c *$.type|privatePlural$) List($.type|private$Name string, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil{ + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &$.resultType|raw$List{} + err = c.client.Get(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.type|private$Name). + SubResource("$.subresourcePath$"). + VersionedParams(&opts, $.schemeParameterCodec|raw$). + Timeout(timeout). + Do(). + Into(result) + return +} +` + +var getTemplate = ` +// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any. +func (c *$.type|privatePlural$) Get(name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Get(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name(name). + VersionedParams(&options, $.schemeParameterCodec|raw$). + Do(). + Into(result) + return +} +` + +var getSubresourceTemplate = ` +// Get takes name of the $.type|private$, and returns the corresponding $.resultType|raw$ object, and an error if there is any. +func (c *$.type|privatePlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Get(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.type|private$Name). + SubResource("$.subresourcePath$"). + VersionedParams(&options, $.schemeParameterCodec|raw$). + Do(). + Into(result) + return +} +` + +var deleteTemplate = ` +// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs. +func (c *$.type|privatePlural$) Delete(name string, options *$.DeleteOptions|raw$) error { + return c.client.Delete(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name(name). + Body(options). + Do(). + Error() +} +` + +var deleteCollectionTemplate = ` +// DeleteCollection deletes a collection of objects. +func (c *$.type|privatePlural$) DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil{ + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + VersionedParams(&listOptions, $.schemeParameterCodec|raw$). + Timeout(timeout). + Body(options). + Do(). + Error() +} +` + +var createSubresourceTemplate = ` +// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *$.type|privatePlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Post(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.type|private$Name). + SubResource("$.subresourcePath$"). + Body($.inputType|private$). + Do(). + Into(result) + return +} +` + +var createTemplate = ` +// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *$.type|privatePlural$) Create($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Post(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Body($.inputType|private$). + Do(). + Into(result) + return +} +` + +var updateSubresourceTemplate = ` +// Update takes the top resource name and the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *$.type|privatePlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Put(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.type|private$Name). + SubResource("$.subresourcePath$"). + Body($.inputType|private$). + Do(). + Into(result) + return +} +` + +var updateTemplate = ` +// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any. +func (c *$.type|privatePlural$) Update($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Put(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.inputType|private$.Name). + Body($.inputType|private$). + Do(). + Into(result) + return +} +` + +var updateStatusTemplate = ` +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *$.type|privatePlural$) UpdateStatus($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) { + result = &$.type|raw${} + err = c.client.Put(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + Name($.type|private$.Name). + SubResource("status"). + Body($.type|private$). + Do(). + Into(result) + return +} +` + +var watchTemplate = ` +// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$. +func (c *$.type|privatePlural$) Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil{ + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + VersionedParams(&opts, $.schemeParameterCodec|raw$). + Timeout(timeout). + Watch() +} +` + +var patchTemplate = ` +// Patch applies the patch and returns the patched $.resultType|private$. +func (c *$.type|privatePlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err error) { + result = &$.resultType|raw${} + err = c.client.Patch(pt). + $if .namespaced$Namespace(c.ns).$end$ + Resource("$.type|resource$"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/BUILD new file mode 100644 index 0000000000..77cc51336e --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/BUILD @@ -0,0 +1,33 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["generator_for_scheme.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme", + importpath = "k8s.io/code-generator/cmd/client-gen/generators/scheme", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/path:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//vendor/k8s.io/gengo/generator:go_default_library", + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go new file mode 100644 index 0000000000..a698a28b68 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go @@ -0,0 +1,186 @@ +/* +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 ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "k8s.io/code-generator/cmd/client-gen/path" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs. +type GenScheme struct { + generator.DefaultGen + OutputPackage string + Groups []clientgentypes.GroupVersions + GroupGoNames map[clientgentypes.GroupVersion]string + InputPackages map[clientgentypes.GroupVersion]string + OutputPath string + ImportTracker namer.ImportTracker + PrivateScheme bool + CreateRegistry bool + schemeGenerated bool +} + +func (g *GenScheme) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.OutputPackage, g.ImportTracker), + } +} + +// We only want to call GenerateType() once. +func (g *GenScheme) Filter(c *generator.Context, t *types.Type) bool { + ret := !g.schemeGenerated + g.schemeGenerated = true + return ret +} + +func (g *GenScheme) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.ImportTracker.ImportLines()...) + for _, group := range g.Groups { + for _, version := range group.Versions { + packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}] + groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]) + if g.CreateRegistry { + // import the install package for internal clientsets instead of the type package with register.go + if version.Version != "" { + packagePath = filepath.Dir(packagePath) + } + packagePath = filepath.Join(packagePath, "install") + + imports = append(imports, fmt.Sprintf("%s \"%s\"", groupAlias, path.Vendorless(packagePath))) + break + } else { + imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.Version.NonEmpty()), path.Vendorless(packagePath))) + } + } + } + return +} + +func (g *GenScheme) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + allGroupVersions := clientgentypes.ToGroupVersionInfo(g.Groups, g.GroupGoNames) + allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups, g.GroupGoNames) + + m := map[string]interface{}{ + "allGroupVersions": allGroupVersions, + "allInstallGroups": allInstallGroups, + "customRegister": false, + "runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}), + "runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}), + "serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}), + "runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}), + "runtimeSchemeBuilder": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "SchemeBuilder"}), + "runtimeUtilMust": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/util/runtime", Name: "Must"}), + "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), + "metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}), + } + globals := map[string]string{ + "Scheme": "Scheme", + "Codecs": "Codecs", + "ParameterCodec": "ParameterCodec", + "Registry": "Registry", + } + for k, v := range globals { + if g.PrivateScheme { + m[k] = strings.ToLower(v[0:1]) + v[1:] + } else { + m[k] = v + } + } + + sw.Do(globalsTemplate, m) + + if g.OutputPath != "" { + if _, err := os.Stat(filepath.Join(g.OutputPath, strings.ToLower("register_custom.go"))); err == nil { + m["customRegister"] = true + } + } + + if g.CreateRegistry { + sw.Do(registryRegistration, m) + } else { + sw.Do(simpleRegistration, m) + } + + return sw.Error() +} + +var globalsTemplate = ` +var $.Scheme$ = $.runtimeNewScheme|raw$() +var $.Codecs$ = $.serializerNewCodecFactory|raw$($.Scheme$) +var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$)` + +var registryRegistration = ` + +func init() { + $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"}) + Install($.Scheme$) +} + +// Install registers the API group and adds types to a scheme +func Install(scheme *$.runtimeScheme|raw$) { + $- range .allInstallGroups$ + $.InstallPackageAlias$.Install(scheme) + $- end$ + $if .customRegister$ + ExtraInstall(scheme) + $end -$ +} +` + +var simpleRegistration = ` +var localSchemeBuilder = $.runtimeSchemeBuilder|raw${ + $- range .allGroupVersions$ + $.PackageAlias$.AddToScheme, + $- end$ + $if .customRegister$ + ExtraAddToScheme, + $end -$ +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"}) + $.runtimeUtilMust|raw$(AddToScheme($.Scheme$)) +} +` diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/BUILD new file mode 100644 index 0000000000..cc2374681d --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/BUILD @@ -0,0 +1,34 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["tags_test.go"], + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["tags.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/generators/util", + importpath = "k8s.io/code-generator/cmd/client-gen/generators/util", + deps = ["//vendor/k8s.io/gengo/types:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go b/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go new file mode 100644 index 0000000000..0b7d68ca88 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go @@ -0,0 +1,341 @@ +/* +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 util + +import ( + "errors" + "fmt" + "strings" + + "k8s.io/gengo/types" +) + +var supportedTags = []string{ + "genclient", + "genclient:nonNamespaced", + "genclient:noVerbs", + "genclient:onlyVerbs", + "genclient:skipVerbs", + "genclient:noStatus", + "genclient:readonly", + "genclient:method", +} + +// SupportedVerbs is a list of supported verbs for +onlyVerbs and +skipVerbs. +var SupportedVerbs = []string{ + "create", + "update", + "updateStatus", + "delete", + "deleteCollection", + "get", + "list", + "watch", + "patch", +} + +// ReadonlyVerbs represents a list of read-only verbs. +var ReadonlyVerbs = []string{ + "get", + "list", + "watch", +} + +// genClientPrefix is the default prefix for all genclient tags. +const genClientPrefix = "genclient:" + +// unsupportedExtensionVerbs is a list of verbs we don't support generating +// extension client functions for. +var unsupportedExtensionVerbs = []string{ + "updateStatus", + "deleteCollection", + "watch", + "delete", +} + +// inputTypeSupportedVerbs is a list of verb types that supports overriding the +// input argument type. +var inputTypeSupportedVerbs = []string{ + "create", + "update", +} + +// resultTypeSupportedVerbs is a list of verb types that supports overriding the +// resulting type. +var resultTypeSupportedVerbs = []string{ + "create", + "update", + "get", + "list", + "patch", +} + +// Extensions allows to extend the default set of client verbs +// (CRUD+watch+patch+list+deleteCollection) for a given type with custom defined +// verbs. Custom verbs can have custom input and result types and also allow to +// use a sub-resource in a request instead of top-level resource type. +// +// Example: +// +// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale +// +// type ReplicaSet struct { ... } +// +// The 'method=UpdateScale' is the name of the client function. +// The 'verb=update' here means the client function will use 'PUT' action. +// The 'subresource=scale' means we will use SubResource template to generate this client function. +// The 'input' is the input type used for creation (function argument). +// The 'result' (not needed in this case) is the result type returned from the +// client function. +// +type extension struct { + // VerbName is the name of the custom verb (Scale, Instantiate, etc..) + VerbName string + // VerbType is the type of the verb (only verbs from SupportedVerbs are + // supported) + VerbType string + // SubResourcePath defines a path to a sub-resource to use in the request. + // (optional) + SubResourcePath string + // InputTypeOverride overrides the input parameter type for the verb. By + // default the original type is used. Overriding the input type only works for + // "create" and "update" verb types. The given type must exists in the same + // package as the original type. + // (optional) + InputTypeOverride string + // ResultTypeOverride overrides the resulting object type for the verb. By + // default the original type is used. Overriding the result type works. + // (optional) + ResultTypeOverride string +} + +// IsSubresource indicates if this extension should generate the sub-resource. +func (e *extension) IsSubresource() bool { + return len(e.SubResourcePath) > 0 +} + +// HasVerb checks if the extension matches the given verb. +func (e *extension) HasVerb(verb string) bool { + return e.VerbType == verb +} + +// Input returns the input override package path and the type. +func (e *extension) Input() (string, string) { + parts := strings.Split(e.InputTypeOverride, ".") + return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") +} + +// Result returns the result override package path and the type. +func (e *extension) Result() (string, string) { + parts := strings.Split(e.ResultTypeOverride, ".") + return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") +} + +// Tags represents a genclient configuration for a single type. +type Tags struct { + // +genclient + GenerateClient bool + // +genclient:nonNamespaced + NonNamespaced bool + // +genclient:noStatus + NoStatus bool + // +genclient:noVerbs + NoVerbs bool + // +genclient:skipVerbs=get,update + // +genclient:onlyVerbs=create,delete + SkipVerbs []string + // +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale + Extensions []extension +} + +// HasVerb returns true if we should include the given verb in final client interface and +// generate the function for it. +func (t Tags) HasVerb(verb string) bool { + if len(t.SkipVerbs) == 0 { + return true + } + for _, s := range t.SkipVerbs { + if verb == s { + return false + } + } + return true +} + +// MustParseClientGenTags calls ParseClientGenTags but instead of returning error it panics. +func MustParseClientGenTags(lines []string) Tags { + tags, err := ParseClientGenTags(lines) + if err != nil { + panic(err.Error()) + } + return tags +} + +// ParseClientGenTags parse the provided genclient tags and validates that no unknown +// tags are provided. +func ParseClientGenTags(lines []string) (Tags, error) { + ret := Tags{} + values := types.ExtractCommentTags("+", lines) + value := []string{} + value, ret.GenerateClient = values["genclient"] + // Check the old format and error when used to avoid generating client when //+genclient=false + if len(value) > 0 && len(value[0]) > 0 { + return ret, fmt.Errorf("+genclient=%s is invalid, use //+genclient if you want to generate client or omit it when you want to disable generation", value) + } + _, ret.NonNamespaced = values[genClientPrefix+"nonNamespaced"] + // Check the old format and error when used + if value := values["nonNamespaced"]; len(value) > 0 && len(value[0]) > 0 { + return ret, fmt.Errorf("+nonNamespaced=%s is invalid, use //+genclient:nonNamespaced instead", value[0]) + } + _, ret.NoVerbs = values[genClientPrefix+"noVerbs"] + _, ret.NoStatus = values[genClientPrefix+"noStatus"] + onlyVerbs := []string{} + if _, isReadonly := values[genClientPrefix+"readonly"]; isReadonly { + onlyVerbs = ReadonlyVerbs + } + // Check the old format and error when used + if value := values["readonly"]; len(value) > 0 && len(value[0]) > 0 { + return ret, fmt.Errorf("+readonly=%s is invalid, use //+genclient:readonly instead", value[0]) + } + if v, exists := values[genClientPrefix+"skipVerbs"]; exists { + ret.SkipVerbs = strings.Split(v[0], ",") + } + if v, exists := values[genClientPrefix+"onlyVerbs"]; exists || len(onlyVerbs) > 0 { + if len(v) > 0 { + onlyVerbs = append(onlyVerbs, strings.Split(v[0], ",")...) + } + skipVerbs := []string{} + for _, m := range SupportedVerbs { + skip := true + for _, o := range onlyVerbs { + if o == m { + skip = false + break + } + } + // Check for conflicts + for _, v := range skipVerbs { + if v == m { + return ret, fmt.Errorf("verb %q used both in genclient:skipVerbs and genclient:onlyVerbs", v) + } + } + if skip { + skipVerbs = append(skipVerbs, m) + } + } + ret.SkipVerbs = skipVerbs + } + var err error + if ret.Extensions, err = parseClientExtensions(values); err != nil { + return ret, err + } + return ret, validateClientGenTags(values) +} + +func parseClientExtensions(tags map[string][]string) ([]extension, error) { + var ret []extension + for name, values := range tags { + if !strings.HasPrefix(name, genClientPrefix+"method") { + continue + } + for _, value := range values { + // the value comes in this form: "Foo,verb=create" + ext := extension{} + parts := strings.Split(value, ",") + if len(parts) == 0 { + return nil, fmt.Errorf("invalid of empty extension verb name: %q", value) + } + // The first part represents the name of the extension + ext.VerbName = parts[0] + if len(ext.VerbName) == 0 { + return nil, fmt.Errorf("must specify a verb name (// +genclient:method=Foo,verb=create)") + } + // Parse rest of the arguments + params := parts[1:] + for _, p := range params { + parts := strings.Split(p, "=") + if len(parts) != 2 { + return nil, fmt.Errorf("invalid extension tag specification %q", p) + } + key, val := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]) + if len(val) == 0 { + return nil, fmt.Errorf("empty value of %q for %q extension", key, ext.VerbName) + } + switch key { + case "verb": + ext.VerbType = val + case "subresource": + ext.SubResourcePath = val + case "input": + ext.InputTypeOverride = val + case "result": + ext.ResultTypeOverride = val + default: + return nil, fmt.Errorf("unknown extension configuration key %q", key) + } + } + // Validate resulting extension configuration + if len(ext.VerbType) == 0 { + return nil, fmt.Errorf("verb type must be specified (use '// +genclient:method=%s,verb=create')", ext.VerbName) + } + if len(ext.ResultTypeOverride) > 0 { + supported := false + for _, v := range resultTypeSupportedVerbs { + if ext.VerbType == v { + supported = true + break + } + } + if !supported { + return nil, fmt.Errorf("%s: result type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, resultTypeSupportedVerbs) + } + } + if len(ext.InputTypeOverride) > 0 { + supported := false + for _, v := range inputTypeSupportedVerbs { + if ext.VerbType == v { + supported = true + break + } + } + if !supported { + return nil, fmt.Errorf("%s: input type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, inputTypeSupportedVerbs) + } + } + for _, t := range unsupportedExtensionVerbs { + if ext.VerbType == t { + return nil, fmt.Errorf("verb %q is not supported by extension generator", ext.VerbType) + } + } + ret = append(ret, ext) + } + } + return ret, nil +} + +// validateTags validates that only supported genclient tags were provided. +func validateClientGenTags(values map[string][]string) error { + for _, k := range supportedTags { + delete(values, k) + } + for key := range values { + if strings.HasPrefix(key, strings.TrimSuffix(genClientPrefix, ":")) { + return errors.New("unknown tag detected: " + key) + } + } + return nil +} diff --git a/vendor/k8s.io/kubernetes/pkg/util/maps/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/path/BUILD similarity index 69% rename from vendor/k8s.io/kubernetes/pkg/util/maps/BUILD rename to vendor/k8s.io/code-generator/cmd/client-gen/path/BUILD index 3c63137f08..2b86853c8e 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/maps/BUILD +++ b/vendor/k8s.io/code-generator/cmd/client-gen/path/BUILD @@ -7,11 +7,9 @@ load( go_library( name = "go_default_library", - srcs = [ - "doc.go", - "string.go", - ], - importpath = "k8s.io/kubernetes/pkg/util/maps", + srcs = ["path.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/path", + importpath = "k8s.io/code-generator/cmd/client-gen/path", ) filegroup( diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/path/path.go b/vendor/k8s.io/code-generator/cmd/client-gen/path/path.go new file mode 100644 index 0000000000..19b269bdf2 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/path/path.go @@ -0,0 +1,31 @@ +/* +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 path + +import "strings" + +// Vendorless removes the longest match of "*/vendor/" from the front of p. +// It is useful if a package locates in vendor/, e.g., +// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1, because gengo +// indexes the package with its import path, e.g., +// k8s.io/apimachinery/pkg/apis/meta/v1, +func Vendorless(p string) string { + if pos := strings.LastIndex(p, "/vendor/"); pos != -1 { + return p[pos+len("/vendor/"):] + } + return p +} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/types/BUILD b/vendor/k8s.io/code-generator/cmd/client-gen/types/BUILD new file mode 100644 index 0000000000..4ccf3d81a0 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/types/BUILD @@ -0,0 +1,37 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = [ + "helpers.go", + "types.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen/types", + importpath = "k8s.io/code-generator/cmd/client-gen/types", + deps = ["//vendor/k8s.io/gengo/namer:go_default_library"], +) + +go_test( + name = "go_default_test", + srcs = ["helpers_test.go"], + embed = [":go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go b/vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go new file mode 100644 index 0000000000..59f2fd4449 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go @@ -0,0 +1,121 @@ +/* +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 types + +import ( + "fmt" + "regexp" + "sort" + "strings" + + "k8s.io/gengo/namer" +) + +// ToGroupVersion turns "group/version" string into a GroupVersion struct. It reports error +// if it cannot parse the string. +func ToGroupVersion(gv string) (GroupVersion, error) { + // this can be the internal version for the legacy kube types + // TODO once we've cleared the last uses as strings, this special case should be removed. + if (len(gv) == 0) || (gv == "/") { + return GroupVersion{}, nil + } + + switch strings.Count(gv, "/") { + case 0: + return GroupVersion{Group(gv), ""}, nil + case 1: + i := strings.Index(gv, "/") + return GroupVersion{Group(gv[:i]), Version(gv[i+1:])}, nil + default: + return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv) + } +} + +type sortableSliceOfVersions []string + +func (a sortableSliceOfVersions) Len() int { return len(a) } +func (a sortableSliceOfVersions) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a sortableSliceOfVersions) Less(i, j int) bool { + vi, vj := strings.TrimLeft(a[i], "v"), strings.TrimLeft(a[j], "v") + major := regexp.MustCompile("^[0-9]+") + viMajor, vjMajor := major.FindString(vi), major.FindString(vj) + viRemaining, vjRemaining := strings.TrimLeft(vi, viMajor), strings.TrimLeft(vj, vjMajor) + switch { + case len(viRemaining) == 0 && len(vjRemaining) == 0: + return viMajor < vjMajor + case len(viRemaining) == 0 && len(vjRemaining) != 0: + // stable version is greater than unstable version + return false + case len(viRemaining) != 0 && len(vjRemaining) == 0: + // stable version is greater than unstable version + return true + } + // neither are stable versions + if viMajor != vjMajor { + return viMajor < vjMajor + } + // assuming at most we have one alpha or one beta version, so if vi contains "alpha", it's the lesser one. + return strings.Contains(viRemaining, "alpha") +} + +// Determine the default version among versions. If a user calls a group client +// without specifying the version (e.g., c.CoreV1(), instead of c.CoreV1()), the +// default version will be returned. +func defaultVersion(versions []PackageVersion) Version { + var versionStrings []string + for _, version := range versions { + versionStrings = append(versionStrings, version.Version.String()) + } + sort.Sort(sortableSliceOfVersions(versionStrings)) + return Version(versionStrings[len(versionStrings)-1]) +} + +// ToGroupVersionInfo is a helper function used by generators for groups. +func ToGroupVersionInfo(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupVersionInfo { + var groupVersionPackages []GroupVersionInfo + for _, group := range groups { + for _, version := range group.Versions { + groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: version.Version}] + groupVersionPackages = append(groupVersionPackages, GroupVersionInfo{ + Group: Group(namer.IC(group.Group.NonEmpty())), + Version: Version(namer.IC(version.Version.String())), + PackageAlias: strings.ToLower(groupGoName + version.Version.NonEmpty()), + GroupGoName: groupGoName, + LowerCaseGroupGoName: namer.IL(groupGoName), + }) + } + } + return groupVersionPackages +} + +func ToGroupInstallPackages(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupInstallPackage { + var groupInstallPackages []GroupInstallPackage + for _, group := range groups { + defaultVersion := defaultVersion(group.Versions) + groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: defaultVersion}] + groupInstallPackages = append(groupInstallPackages, GroupInstallPackage{ + Group: Group(namer.IC(group.Group.NonEmpty())), + InstallPackageAlias: strings.ToLower(groupGoName), + }) + } + return groupInstallPackages +} + +// NormalizeGroupVersion calls normalizes the GroupVersion. +//func NormalizeGroupVersion(gv GroupVersion) GroupVersion { +// return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)} +//} diff --git a/vendor/k8s.io/code-generator/cmd/client-gen/types/types.go b/vendor/k8s.io/code-generator/cmd/client-gen/types/types.go new file mode 100644 index 0000000000..7d1606c508 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/client-gen/types/types.go @@ -0,0 +1,75 @@ +/* +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 types + +type Version string + +func (v Version) String() string { + return string(v) +} + +func (v Version) NonEmpty() string { + if v == "" { + return "internalVersion" + } + return v.String() +} + +type Group string + +func (g Group) String() string { + return string(g) +} + +func (g Group) NonEmpty() string { + if g == "api" { + return "core" + } + return string(g) +} + +type PackageVersion struct { + Version + // The fully qualified package, e.g. k8s.io/kubernetes/pkg/apis/apps, where the types.go is found. + Package string +} + +type GroupVersion struct { + Group Group + Version Version +} + +type GroupVersions struct { + // The name of the package for this group, e.g. apps. + PackageName string + Group Group + Versions []PackageVersion +} + +// GroupVersionInfo contains all the info around a group version. +type GroupVersionInfo struct { + Group Group + Version Version + PackageAlias string + GroupGoName string + LowerCaseGroupGoName string +} + +type GroupInstallPackage struct { + Group Group + InstallPackageAlias string +} diff --git a/vendor/k8s.io/code-generator/cmd/deepcopy-gen/BUILD b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/BUILD new file mode 100644 index 0000000000..a1a48d4d91 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/BUILD @@ -0,0 +1,43 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", +) + +go_binary( + name = "deepcopy-gen", + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/deepcopy-gen", + importpath = "k8s.io/code-generator/cmd/deepcopy-gen", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/deepcopy-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/gengo/examples/deepcopy-gen/generators:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/deepcopy-gen/args:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/BUILD b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/BUILD new file mode 100644 index 0000000000..7e87036660 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["args.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args", + importpath = "k8s.io/code-generator/cmd/deepcopy-gen/args", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/gengo/examples/deepcopy-gen/generators:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.go b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.go new file mode 100644 index 0000000000..789713012a --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.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 args + +import ( + "fmt" + + "github.com/spf13/pflag" + "k8s.io/gengo/args" + "k8s.io/gengo/examples/deepcopy-gen/generators" +) + +// CustomArgs is used by the gengo framework to pass args specific to this generator. +type CustomArgs generators.CustomArgs + +// NewDefaults returns default arguments for the generator. +func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { + genericArgs := args.Default().WithoutDefaultFlagParsing() + customArgs := &CustomArgs{} + genericArgs.CustomArgs = (*generators.CustomArgs)(customArgs) // convert to upstream type to make type-casts work there + genericArgs.OutputFileBaseName = "deepcopy_generated" + return genericArgs, customArgs +} + +// AddFlags add the generator flags to the flag set. +func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) { + pflag.CommandLine.StringSliceVar(&ca.BoundingDirs, "bounding-dirs", ca.BoundingDirs, + "Comma-separated list of import paths which bound the types for which deep-copies will be generated.") +} + +// Validate checks the given arguments. +func Validate(genericArgs *args.GeneratorArgs) error { + _ = genericArgs.CustomArgs.(*generators.CustomArgs) + + if len(genericArgs.OutputFileBaseName) == 0 { + return fmt.Errorf("output file base name cannot be empty") + } + + return nil +} diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/BUILD b/vendor/k8s.io/code-generator/cmd/informer-gen/BUILD new file mode 100644 index 0000000000..5a11f5433f --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", +) + +go_binary( + name = "informer-gen", + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/informer-gen", + importpath = "k8s.io/code-generator/cmd/informer-gen", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/informer-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/informer-gen/generators:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/informer-gen/args:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/informer-gen/generators:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/args/BUILD b/vendor/k8s.io/code-generator/cmd/informer-gen/args/BUILD new file mode 100644 index 0000000000..9cf600783e --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/args/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["args.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/informer-gen/args", + importpath = "k8s.io/code-generator/cmd/informer-gen/args", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go b/vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go new file mode 100644 index 0000000000..ba7f720917 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go @@ -0,0 +1,77 @@ +/* +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 args + +import ( + "fmt" + "path" + + "github.com/spf13/pflag" + codegenutil "k8s.io/code-generator/pkg/util" + "k8s.io/gengo/args" +) + +// CustomArgs is used by the gengo framework to pass args specific to this generator. +type CustomArgs struct { + VersionedClientSetPackage string + InternalClientSetPackage string + ListersPackage string + SingleDirectory bool +} + +// NewDefaults returns default arguments for the generator. +func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { + genericArgs := args.Default().WithoutDefaultFlagParsing() + customArgs := &CustomArgs{ + SingleDirectory: false, + } + genericArgs.CustomArgs = customArgs + + if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 { + genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/informers") + customArgs.VersionedClientSetPackage = path.Join(pkg, "pkg/client/clientset/versioned") + customArgs.InternalClientSetPackage = path.Join(pkg, "pkg/client/clientset/internalversion") + customArgs.ListersPackage = path.Join(pkg, "pkg/client/listers") + } + + return genericArgs, customArgs +} + +// AddFlags add the generator flags to the flag set. +func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) { + fs.StringVar(&ca.InternalClientSetPackage, "internal-clientset-package", ca.InternalClientSetPackage, "the full package name for the internal clientset to use") + fs.StringVar(&ca.VersionedClientSetPackage, "versioned-clientset-package", ca.VersionedClientSetPackage, "the full package name for the versioned clientset to use") + fs.StringVar(&ca.ListersPackage, "listers-package", ca.ListersPackage, "the full package name for the listers to use") + fs.BoolVar(&ca.SingleDirectory, "single-directory", ca.SingleDirectory, "if true, omit the intermediate \"internalversion\" and \"externalversions\" subdirectories") +} + +// Validate checks the given arguments. +func Validate(genericArgs *args.GeneratorArgs) error { + customArgs := genericArgs.CustomArgs.(*CustomArgs) + + if len(genericArgs.OutputPackagePath) == 0 { + return fmt.Errorf("output package cannot be empty") + } + if len(customArgs.VersionedClientSetPackage) == 0 { + return fmt.Errorf("versioned clientset package cannot be empty") + } + if len(customArgs.ListersPackage) == 0 { + return fmt.Errorf("listers package cannot be empty") + } + + return nil +} diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/BUILD b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/BUILD new file mode 100644 index 0000000000..1717edd83f --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/BUILD @@ -0,0 +1,47 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "factory.go", + "factoryinterface.go", + "generic.go", + "groupinterface.go", + "informer.go", + "packages.go", + "tags.go", + "types.go", + "versioninterface.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/informer-gen/generators", + importpath = "k8s.io/code-generator/cmd/informer-gen/generators", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/informer-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/namer:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/gengo/generator:go_default_library", + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go new file mode 100644 index 0000000000..6e5793109b --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go @@ -0,0 +1,258 @@ +/* +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 generators + +import ( + "io" + "path" + + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/klog" +) + +// factoryGenerator produces a file of listers for a given GroupVersion and +// type. +type factoryGenerator struct { + generator.DefaultGen + outputPackage string + imports namer.ImportTracker + groupVersions map[string]clientgentypes.GroupVersions + gvGoNames map[string]string + clientSetPackage string + internalInterfacesPackage string + filtered bool +} + +var _ generator.Generator = &factoryGenerator{} + +func (g *factoryGenerator) Filter(c *generator.Context, t *types.Type) bool { + if !g.filtered { + g.filtered = true + return true + } + return false +} + +func (g *factoryGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *factoryGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + return +} + +func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + klog.V(5).Infof("processing type %v", t) + + gvInterfaces := make(map[string]*types.Type) + gvNewFuncs := make(map[string]*types.Type) + for groupPkgName := range g.groupVersions { + gvInterfaces[groupPkgName] = c.Universe.Type(types.Name{Package: path.Join(g.outputPackage, groupPkgName), Name: "Interface"}) + gvNewFuncs[groupPkgName] = c.Universe.Function(types.Name{Package: path.Join(g.outputPackage, groupPkgName), Name: "New"}) + } + m := map[string]interface{}{ + "cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer), + "groupVersions": g.groupVersions, + "gvInterfaces": gvInterfaces, + "gvNewFuncs": gvNewFuncs, + "gvGoNames": g.gvGoNames, + "interfacesNewInformerFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "NewInformerFunc"}), + "interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}), + "informerFactoryInterface": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}), + "clientSetInterface": c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}), + "reflectType": c.Universe.Type(reflectType), + "runtimeObject": c.Universe.Type(runtimeObject), + "schemaGroupVersionResource": c.Universe.Type(schemaGroupVersionResource), + "syncMutex": c.Universe.Type(syncMutex), + "timeDuration": c.Universe.Type(timeDuration), + "namespaceAll": c.Universe.Type(metav1NamespaceAll), + "object": c.Universe.Type(metav1Object), + } + + sw.Do(sharedInformerFactoryStruct, m) + sw.Do(sharedInformerFactoryInterface, m) + + return sw.Error() +} + +var sharedInformerFactoryStruct = ` +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client {{.clientSetInterface|raw}} + namespace string + tweakListOptions {{.interfacesTweakListOptionsFunc|raw}} + lock {{.syncMutex|raw}} + defaultResync {{.timeDuration|raw}} + customResync map[{{.reflectType|raw}}]{{.timeDuration|raw}} + + informers map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}} + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[{{.reflectType|raw}}]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[{{.object|raw}}]{{.timeDuration|raw}}) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, namespace string, tweakListOptions {{.interfacesTweakListOptionsFunc|raw}}) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}), + startedInformers: make(map[{{.reflectType|raw}}]bool), + customResync: make(map[{{.reflectType|raw}}]{{.timeDuration|raw}}), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func()map[reflect.Type]cache.SharedIndexInformer{ + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj {{.runtimeObject|raw}}, newFunc {{.interfacesNewInformerFunc|raw}}) {{.cacheSharedIndexInformer|raw}} { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +` + +var sharedInformerFactoryInterface = ` +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + {{.informerFactoryInterface|raw}} + ForResource(resource {{.schemaGroupVersionResource|raw}}) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + {{$gvInterfaces := .gvInterfaces}} + {{$gvGoNames := .gvGoNames}} + {{range $groupName, $group := .groupVersions}}{{index $gvGoNames $groupName}}() {{index $gvInterfaces $groupName|raw}} + {{end}} +} + +{{$gvNewFuncs := .gvNewFuncs}} +{{$gvGoNames := .gvGoNames}} +{{range $groupPkgName, $group := .groupVersions}} +func (f *sharedInformerFactory) {{index $gvGoNames $groupPkgName}}() {{index $gvInterfaces $groupPkgName|raw}} { + return {{index $gvNewFuncs $groupPkgName|raw}}(f, f.namespace, f.tweakListOptions) +} +{{end}} +` diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go new file mode 100644 index 0000000000..fc0668c5be --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go @@ -0,0 +1,90 @@ +/* +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 generators + +import ( + "io" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/klog" +) + +// factoryInterfaceGenerator produces a file of interfaces used to break a dependency cycle for +// informer registration +type factoryInterfaceGenerator struct { + generator.DefaultGen + outputPackage string + imports namer.ImportTracker + clientSetPackage string + filtered bool +} + +var _ generator.Generator = &factoryInterfaceGenerator{} + +func (g *factoryInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool { + if !g.filtered { + g.filtered = true + return true + } + return false +} + +func (g *factoryInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *factoryInterfaceGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + return +} + +func (g *factoryInterfaceGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + klog.V(5).Infof("processing type %v", t) + + m := map[string]interface{}{ + "cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer), + "clientSetPackage": c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}), + "runtimeObject": c.Universe.Type(runtimeObject), + "timeDuration": c.Universe.Type(timeDuration), + "v1ListOptions": c.Universe.Type(v1ListOptions), + } + + sw.Do(externalSharedInformerFactoryInterface, m) + + return sw.Error() +} + +var externalSharedInformerFactoryInterface = ` +// NewInformerFunc takes {{.clientSetPackage|raw}} and {{.timeDuration|raw}} to return a SharedIndexInformer. +type NewInformerFunc func({{.clientSetPackage|raw}}, {{.timeDuration|raw}}) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj {{.runtimeObject|raw}}, newFunc NewInformerFunc) {{.cacheSharedIndexInformer|raw}} +} + +// TweakListOptionsFunc is a function that transforms a {{.v1ListOptions|raw}}. +type TweakListOptionsFunc func(*{{.v1ListOptions|raw}}) +` diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go new file mode 100644 index 0000000000..cad907990f --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go @@ -0,0 +1,184 @@ +/* +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 generators + +import ( + "io" + "sort" + "strings" + + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + codegennamer "k8s.io/code-generator/pkg/namer" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// genericGenerator generates the generic informer. +type genericGenerator struct { + generator.DefaultGen + outputPackage string + imports namer.ImportTracker + groupVersions map[string]clientgentypes.GroupVersions + groupGoNames map[string]string + typesForGroupVersion map[clientgentypes.GroupVersion][]*types.Type + filtered bool +} + +var _ generator.Generator = &genericGenerator{} + +func (g *genericGenerator) Filter(c *generator.Context, t *types.Type) bool { + if !g.filtered { + g.filtered = true + return true + } + return false +} + +func (g *genericGenerator) Namers(c *generator.Context) namer.NameSystems { + pluralExceptions := map[string]string{ + "Endpoints": "Endpoints", + } + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + "allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions), + "publicPlural": namer.NewPublicPluralNamer(pluralExceptions), + "resource": codegennamer.NewTagOverrideNamer("resourceName", namer.NewAllLowercasePluralNamer(pluralExceptions)), + } +} + +func (g *genericGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + imports = append(imports, "fmt") + return +} + +type group struct { + GroupGoName string + Name string + Versions []*version +} + +type groupSort []group + +func (g groupSort) Len() int { return len(g) } +func (g groupSort) Less(i, j int) bool { return strings.ToLower(g[i].Name) < strings.ToLower(g[j].Name) } +func (g groupSort) Swap(i, j int) { g[i], g[j] = g[j], g[i] } + +type version struct { + Name string + GoName string + Resources []*types.Type +} + +type versionSort []*version + +func (v versionSort) Len() int { return len(v) } +func (v versionSort) Less(i, j int) bool { + return strings.ToLower(v[i].Name) < strings.ToLower(v[j].Name) +} +func (v versionSort) Swap(i, j int) { v[i], v[j] = v[j], v[i] } + +func (g *genericGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "{{", "}}") + + groups := []group{} + schemeGVs := make(map[*version]*types.Type) + + orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} + for groupPackageName, groupVersions := range g.groupVersions { + group := group{ + GroupGoName: g.groupGoNames[groupPackageName], + Name: groupVersions.Group.NonEmpty(), + Versions: []*version{}, + } + for _, v := range groupVersions.Versions { + gv := clientgentypes.GroupVersion{Group: groupVersions.Group, Version: v.Version} + version := &version{ + Name: v.Version.NonEmpty(), + GoName: namer.IC(v.Version.NonEmpty()), + Resources: orderer.OrderTypes(g.typesForGroupVersion[gv]), + } + func() { + schemeGVs[version] = c.Universe.Variable(types.Name{Package: g.typesForGroupVersion[gv][0].Name.Package, Name: "SchemeGroupVersion"}) + }() + group.Versions = append(group.Versions, version) + } + sort.Sort(versionSort(group.Versions)) + groups = append(groups, group) + } + sort.Sort(groupSort(groups)) + + m := map[string]interface{}{ + "cacheGenericLister": c.Universe.Type(cacheGenericLister), + "cacheNewGenericLister": c.Universe.Function(cacheNewGenericLister), + "cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer), + "groups": groups, + "schemeGVs": schemeGVs, + "schemaGroupResource": c.Universe.Type(schemaGroupResource), + "schemaGroupVersionResource": c.Universe.Type(schemaGroupVersionResource), + } + + sw.Do(genericInformer, m) + sw.Do(forResource, m) + + return sw.Error() +} + +var genericInformer = ` +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() {{.cacheSharedIndexInformer|raw}} + Lister() {{.cacheGenericLister|raw}} +} + +type genericInformer struct { + informer {{.cacheSharedIndexInformer|raw}} + resource {{.schemaGroupResource|raw}} +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() {{.cacheSharedIndexInformer|raw}} { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() {{.cacheGenericLister|raw}} { + return {{.cacheNewGenericLister|raw}}(f.Informer().GetIndexer(), f.resource) +} +` + +var forResource = ` +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource {{.schemaGroupVersionResource|raw}}) (GenericInformer, error) { + switch resource { + {{range $group := .groups -}}{{$GroupGoName := .GroupGoName -}} + {{range $version := .Versions -}} + // Group={{$group.Name}}, Version={{.Name}} + {{range .Resources -}} + case {{index $.schemeGVs $version|raw}}.WithResource("{{.|resource}}"): + return &genericInformer{resource: resource.GroupResource(), informer: f.{{$GroupGoName}}().{{$version.GoName}}().{{.|publicPlural}}().Informer()}, nil + {{end}} + {{end}} + {{end -}} + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} +` diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go new file mode 100644 index 0000000000..0bba93c4b2 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go @@ -0,0 +1,118 @@ +/* +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 generators + +import ( + "io" + "path/filepath" + "strings" + + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// groupInterfaceGenerator generates the per-group interface file. +type groupInterfaceGenerator struct { + generator.DefaultGen + outputPackage string + imports namer.ImportTracker + groupVersions clientgentypes.GroupVersions + filtered bool + internalInterfacesPackage string +} + +var _ generator.Generator = &groupInterfaceGenerator{} + +func (g *groupInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool { + if !g.filtered { + g.filtered = true + return true + } + return false +} + +func (g *groupInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *groupInterfaceGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + return +} + +type versionData struct { + Name string + Interface *types.Type + New *types.Type +} + +func (g *groupInterfaceGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + versions := make([]versionData, 0, len(g.groupVersions.Versions)) + for _, version := range g.groupVersions.Versions { + gv := clientgentypes.GroupVersion{Group: g.groupVersions.Group, Version: version.Version} + versionPackage := filepath.Join(g.outputPackage, strings.ToLower(gv.Version.NonEmpty())) + iface := c.Universe.Type(types.Name{Package: versionPackage, Name: "Interface"}) + versions = append(versions, versionData{ + Name: namer.IC(version.Version.NonEmpty()), + Interface: iface, + New: c.Universe.Function(types.Name{Package: versionPackage, Name: "New"}), + }) + } + m := map[string]interface{}{ + "interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}), + "interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}), + "versions": versions, + } + + sw.Do(groupTemplate, m) + + return sw.Error() +} + +var groupTemplate = ` +// Interface provides access to each of this group's versions. +type Interface interface { + $range .versions -$ + // $.Name$ provides access to shared informers for resources in $.Name$. + $.Name$() $.Interface|raw$ + $end$ +} + +type group struct { + factory $.interfacesSharedInformerFactory|raw$ + namespace string + tweakListOptions $.interfacesTweakListOptionsFunc|raw$ +} + +// New returns a new Interface. +func New(f $.interfacesSharedInformerFactory|raw$, namespace string, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +$range .versions$ +// $.Name$ returns a new $.Interface|raw$. +func (g *group) $.Name$() $.Interface|raw$ { + return $.New|raw$(g.factory, g.namespace, g.tweakListOptions) +} +$end$ +` diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go new file mode 100644 index 0000000000..9204d6215a --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go @@ -0,0 +1,186 @@ +/* +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 generators + +import ( + "fmt" + "io" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + + "k8s.io/klog" +) + +// informerGenerator produces a file of listers for a given GroupVersion and +// type. +type informerGenerator struct { + generator.DefaultGen + outputPackage string + groupPkgName string + groupVersion clientgentypes.GroupVersion + groupGoName string + typeToGenerate *types.Type + imports namer.ImportTracker + clientSetPackage string + listersPackage string + internalInterfacesPackage string +} + +var _ generator.Generator = &informerGenerator{} + +func (g *informerGenerator) Filter(c *generator.Context, t *types.Type) bool { + return t == g.typeToGenerate +} + +func (g *informerGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *informerGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + return +} + +func (g *informerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + klog.V(5).Infof("processing type %v", t) + + listerPackage := fmt.Sprintf("%s/%s/%s", g.listersPackage, g.groupPkgName, strings.ToLower(g.groupVersion.Version.NonEmpty())) + clientSetInterface := c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}) + informerFor := "InformerFor" + + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + + m := map[string]interface{}{ + "apiScheme": c.Universe.Type(apiScheme), + "cacheIndexers": c.Universe.Type(cacheIndexers), + "cacheListWatch": c.Universe.Type(cacheListWatch), + "cacheMetaNamespaceIndexFunc": c.Universe.Function(cacheMetaNamespaceIndexFunc), + "cacheNamespaceIndex": c.Universe.Variable(cacheNamespaceIndex), + "cacheNewSharedIndexInformer": c.Universe.Function(cacheNewSharedIndexInformer), + "cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer), + "clientSetInterface": clientSetInterface, + "group": namer.IC(g.groupGoName), + "informerFor": informerFor, + "interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}), + "interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}), + "listOptions": c.Universe.Type(listOptions), + "lister": c.Universe.Type(types.Name{Package: listerPackage, Name: t.Name.Name + "Lister"}), + "namespaceAll": c.Universe.Type(metav1NamespaceAll), + "namespaced": !tags.NonNamespaced, + "newLister": c.Universe.Function(types.Name{Package: listerPackage, Name: "New" + t.Name.Name + "Lister"}), + "runtimeObject": c.Universe.Type(runtimeObject), + "timeDuration": c.Universe.Type(timeDuration), + "type": t, + "v1ListOptions": c.Universe.Type(v1ListOptions), + "version": namer.IC(g.groupVersion.Version.String()), + "watchInterface": c.Universe.Type(watchInterface), + } + + sw.Do(typeInformerInterface, m) + sw.Do(typeInformerStruct, m) + sw.Do(typeInformerPublicConstructor, m) + sw.Do(typeFilteredInformerPublicConstructor, m) + sw.Do(typeInformerConstructor, m) + sw.Do(typeInformerInformer, m) + sw.Do(typeInformerLister, m) + + return sw.Error() +} + +var typeInformerInterface = ` +// $.type|public$Informer provides access to a shared informer and lister for +// $.type|publicPlural$. +type $.type|public$Informer interface { + Informer() $.cacheSharedIndexInformer|raw$ + Lister() $.lister|raw$ +} +` + +var typeInformerStruct = ` +type $.type|private$Informer struct { + factory $.interfacesSharedInformerFactory|raw$ + tweakListOptions $.interfacesTweakListOptionsFunc|raw$ + $if .namespaced$namespace string$end$ +} +` + +var typeInformerPublicConstructor = ` +// New$.type|public$Informer constructs a new informer for $.type|public$ 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 New$.type|public$Informer(client $.clientSetInterface|raw$$if .namespaced$, namespace string$end$, resyncPeriod $.timeDuration|raw$, indexers $.cacheIndexers|raw$) $.cacheSharedIndexInformer|raw$ { + return NewFiltered$.type|public$Informer(client$if .namespaced$, namespace$end$, resyncPeriod, indexers, nil) +} +` + +var typeFilteredInformerPublicConstructor = ` +// NewFiltered$.type|public$Informer constructs a new informer for $.type|public$ 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 NewFiltered$.type|public$Informer(client $.clientSetInterface|raw$$if .namespaced$, namespace string$end$, resyncPeriod $.timeDuration|raw$, indexers $.cacheIndexers|raw$, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) $.cacheSharedIndexInformer|raw$ { + return $.cacheNewSharedIndexInformer|raw$( + &$.cacheListWatch|raw${ + ListFunc: func(options $.v1ListOptions|raw$) ($.runtimeObject|raw$, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$namespace$end$).List(options) + }, + WatchFunc: func(options $.v1ListOptions|raw$) ($.watchInterface|raw$, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$namespace$end$).Watch(options) + }, + }, + &$.type|raw${}, + resyncPeriod, + indexers, + ) +} +` + +var typeInformerConstructor = ` +func (f *$.type|private$Informer) defaultInformer(client $.clientSetInterface|raw$, resyncPeriod $.timeDuration|raw$) $.cacheSharedIndexInformer|raw$ { + return NewFiltered$.type|public$Informer(client$if .namespaced$, f.namespace$end$, resyncPeriod, $.cacheIndexers|raw${$.cacheNamespaceIndex|raw$: $.cacheMetaNamespaceIndexFunc|raw$}, f.tweakListOptions) +} +` + +var typeInformerInformer = ` +func (f *$.type|private$Informer) Informer() $.cacheSharedIndexInformer|raw$ { + return f.factory.$.informerFor$(&$.type|raw${}, f.defaultInformer) +} +` + +var typeInformerLister = ` +func (f *$.type|private$Informer) Lister() $.lister|raw$ { + return $.newLister|raw$(f.Informer().GetIndexer()) +} +` diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go new file mode 100644 index 0000000000..cfb91cebac --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go @@ -0,0 +1,352 @@ +/* +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 generators + +import ( + "fmt" + "path" + "path/filepath" + "strings" + + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + "k8s.io/klog" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + informergenargs "k8s.io/code-generator/cmd/informer-gen/args" +) + +// NameSystems returns the name system used by the generators in this package. +func NameSystems() namer.NameSystems { + pluralExceptions := map[string]string{ + "Endpoints": "Endpoints", + } + return namer.NameSystems{ + "public": namer.NewPublicNamer(0), + "private": namer.NewPrivateNamer(0), + "raw": namer.NewRawNamer("", nil), + "publicPlural": namer.NewPublicPluralNamer(pluralExceptions), + "allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions), + "lowercaseSingular": &lowercaseSingularNamer{}, + } +} + +// lowercaseSingularNamer implements Namer +type lowercaseSingularNamer struct{} + +// Name returns t's name in all lowercase. +func (n *lowercaseSingularNamer) Name(t *types.Type) string { + return strings.ToLower(t.Name.Name) +} + +// DefaultNameSystem returns the default name system for ordering the types to be +// processed by the generators in this package. +func DefaultNameSystem() string { + return "public" +} + +// objectMetaForPackage returns the type of ObjectMeta used by package p. +func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) { + generatingForPackage := false + for _, t := range p.Types { + if !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient { + continue + } + generatingForPackage = true + for _, member := range t.Members { + if member.Name == "ObjectMeta" { + return member.Type, isInternal(member), nil + } + } + } + if generatingForPackage { + return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path) + } + return nil, false, nil +} + +// isInternal returns true if the tags for a member do not contain a json tag +func isInternal(m types.Member) bool { + return !strings.Contains(m.Tags, "json") +} + +func packageForInternalInterfaces(base string) string { + return filepath.Join(base, "internalinterfaces") +} + +func vendorless(p string) string { + if pos := strings.LastIndex(p, "/vendor/"); pos != -1 { + return p[pos+len("/vendor/"):] + } + return p +} + +// Packages makes the client package definition. +func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + boilerplate, err := arguments.LoadGoBoilerplate() + if err != nil { + klog.Fatalf("Failed loading boilerplate: %v", err) + } + + customArgs, ok := arguments.CustomArgs.(*informergenargs.CustomArgs) + if !ok { + klog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs) + } + + internalVersionPackagePath := filepath.Join(arguments.OutputPackagePath) + externalVersionPackagePath := filepath.Join(arguments.OutputPackagePath) + if !customArgs.SingleDirectory { + internalVersionPackagePath = filepath.Join(arguments.OutputPackagePath, "internalversion") + externalVersionPackagePath = filepath.Join(arguments.OutputPackagePath, "externalversions") + } + + var packageList generator.Packages + typesForGroupVersion := make(map[clientgentypes.GroupVersion][]*types.Type) + + externalGroupVersions := make(map[string]clientgentypes.GroupVersions) + internalGroupVersions := make(map[string]clientgentypes.GroupVersions) + groupGoNames := make(map[string]string) + for _, inputDir := range arguments.InputDirs { + p := context.Universe.Package(vendorless(inputDir)) + + objectMeta, internal, err := objectMetaForPackage(p) + if err != nil { + klog.Fatal(err) + } + if objectMeta == nil { + // no types in this package had genclient + continue + } + + var gv clientgentypes.GroupVersion + var targetGroupVersions map[string]clientgentypes.GroupVersions + + if internal { + lastSlash := strings.LastIndex(p.Path, "/") + if lastSlash == -1 { + klog.Fatalf("error constructing internal group version for package %q", p.Path) + } + gv.Group = clientgentypes.Group(p.Path[lastSlash+1:]) + targetGroupVersions = internalGroupVersions + } else { + parts := strings.Split(p.Path, "/") + gv.Group = clientgentypes.Group(parts[len(parts)-2]) + gv.Version = clientgentypes.Version(parts[len(parts)-1]) + targetGroupVersions = externalGroupVersions + } + groupPackageName := gv.Group.NonEmpty() + gvPackage := path.Clean(p.Path) + + // If there's a comment of the form "// +groupName=somegroup" or + // "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the + // group when generating. + if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil { + gv.Group = clientgentypes.Group(override[0]) + } + + // If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as + // the Go group identifier in CamelCase. It defaults + groupGoNames[groupPackageName] = namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0]) + if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil { + groupGoNames[groupPackageName] = namer.IC(override[0]) + } + + var typesToGenerate []*types.Type + for _, t := range p.Types { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if !tags.GenerateClient || tags.NoVerbs || !tags.HasVerb("list") || !tags.HasVerb("watch") { + continue + } + + typesToGenerate = append(typesToGenerate, t) + + if _, ok := typesForGroupVersion[gv]; !ok { + typesForGroupVersion[gv] = []*types.Type{} + } + typesForGroupVersion[gv] = append(typesForGroupVersion[gv], t) + } + if len(typesToGenerate) == 0 { + continue + } + + groupVersionsEntry, ok := targetGroupVersions[groupPackageName] + if !ok { + groupVersionsEntry = clientgentypes.GroupVersions{ + PackageName: groupPackageName, + Group: gv.Group, + } + } + groupVersionsEntry.Versions = append(groupVersionsEntry.Versions, clientgentypes.PackageVersion{Version: gv.Version, Package: gvPackage}) + targetGroupVersions[groupPackageName] = groupVersionsEntry + + orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} + typesToGenerate = orderer.OrderTypes(typesToGenerate) + + if internal { + packageList = append(packageList, versionPackage(internalVersionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesToGenerate, customArgs.InternalClientSetPackage, customArgs.ListersPackage)) + } else { + packageList = append(packageList, versionPackage(externalVersionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesToGenerate, customArgs.VersionedClientSetPackage, customArgs.ListersPackage)) + } + } + + if len(externalGroupVersions) != 0 { + packageList = append(packageList, factoryInterfacePackage(externalVersionPackagePath, boilerplate, customArgs.VersionedClientSetPackage)) + packageList = append(packageList, factoryPackage(externalVersionPackagePath, boilerplate, groupGoNames, externalGroupVersions, customArgs.VersionedClientSetPackage, typesForGroupVersion)) + for _, gvs := range externalGroupVersions { + packageList = append(packageList, groupPackage(externalVersionPackagePath, gvs, boilerplate)) + } + } + + if len(internalGroupVersions) != 0 { + packageList = append(packageList, factoryInterfacePackage(internalVersionPackagePath, boilerplate, customArgs.InternalClientSetPackage)) + packageList = append(packageList, factoryPackage(internalVersionPackagePath, boilerplate, groupGoNames, internalGroupVersions, customArgs.InternalClientSetPackage, typesForGroupVersion)) + for _, gvs := range internalGroupVersions { + packageList = append(packageList, groupPackage(internalVersionPackagePath, gvs, boilerplate)) + } + } + + return packageList +} + +func factoryPackage(basePackage string, boilerplate []byte, groupGoNames map[string]string, groupVersions map[string]clientgentypes.GroupVersions, clientSetPackage string, typesForGroupVersion map[clientgentypes.GroupVersion][]*types.Type) generator.Package { + return &generator.DefaultPackage{ + PackageName: filepath.Base(basePackage), + PackagePath: basePackage, + HeaderText: boilerplate, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = append(generators, &factoryGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "factory", + }, + outputPackage: basePackage, + imports: generator.NewImportTracker(), + groupVersions: groupVersions, + clientSetPackage: clientSetPackage, + internalInterfacesPackage: packageForInternalInterfaces(basePackage), + gvGoNames: groupGoNames, + }) + + generators = append(generators, &genericGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "generic", + }, + outputPackage: basePackage, + imports: generator.NewImportTracker(), + groupVersions: groupVersions, + typesForGroupVersion: typesForGroupVersion, + groupGoNames: groupGoNames, + }) + + return generators + }, + } +} + +func factoryInterfacePackage(basePackage string, boilerplate []byte, clientSetPackage string) generator.Package { + packagePath := packageForInternalInterfaces(basePackage) + + return &generator.DefaultPackage{ + PackageName: filepath.Base(packagePath), + PackagePath: packagePath, + HeaderText: boilerplate, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = append(generators, &factoryInterfaceGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "factory_interfaces", + }, + outputPackage: packagePath, + imports: generator.NewImportTracker(), + clientSetPackage: clientSetPackage, + }) + + return generators + }, + } +} + +func groupPackage(basePackage string, groupVersions clientgentypes.GroupVersions, boilerplate []byte) generator.Package { + packagePath := filepath.Join(basePackage, groupVersions.PackageName) + groupPkgName := strings.Split(string(groupVersions.Group), ".")[0] + + return &generator.DefaultPackage{ + PackageName: groupPkgName, + PackagePath: packagePath, + HeaderText: boilerplate, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = append(generators, &groupInterfaceGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "interface", + }, + outputPackage: packagePath, + groupVersions: groupVersions, + imports: generator.NewImportTracker(), + internalInterfacesPackage: packageForInternalInterfaces(basePackage), + }) + return generators + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("watch") + }, + } +} + +func versionPackage(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, clientSetPackage, listersPackage string) generator.Package { + packagePath := filepath.Join(basePackage, groupPkgName, strings.ToLower(gv.Version.NonEmpty())) + + return &generator.DefaultPackage{ + PackageName: strings.ToLower(gv.Version.NonEmpty()), + PackagePath: packagePath, + HeaderText: boilerplate, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = append(generators, &versionInterfaceGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "interface", + }, + outputPackage: packagePath, + imports: generator.NewImportTracker(), + types: typesToGenerate, + internalInterfacesPackage: packageForInternalInterfaces(basePackage), + }) + + for _, t := range typesToGenerate { + generators = append(generators, &informerGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: strings.ToLower(t.Name.Name), + }, + outputPackage: packagePath, + groupPkgName: groupPkgName, + groupVersion: gv, + groupGoName: groupGoName, + typeToGenerate: t, + imports: generator.NewImportTracker(), + clientSetPackage: clientSetPackage, + listersPackage: listersPackage, + internalInterfacesPackage: packageForInternalInterfaces(basePackage), + }) + } + return generators + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("watch") + }, + } +} diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go new file mode 100644 index 0000000000..d25d5b6304 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go @@ -0,0 +1,33 @@ +/* +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 generators + +import ( + "k8s.io/gengo/types" + "k8s.io/klog" +) + +// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if +// it exists, the value is boolean. If the tag did not exist, it returns +// false. +func extractBoolTagOrDie(key string, lines []string) bool { + val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines) + if err != nil { + klog.Fatal(err) + } + return val +} diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go new file mode 100644 index 0000000000..27d4bd51ab --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go @@ -0,0 +1,42 @@ +/* +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 generators + +import "k8s.io/gengo/types" + +var ( + apiScheme = types.Name{Package: "k8s.io/kubernetes/pkg/api/legacyscheme", Name: "Scheme"} + cacheGenericLister = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "GenericLister"} + cacheIndexers = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "Indexers"} + cacheListWatch = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "ListWatch"} + cacheMetaNamespaceIndexFunc = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "MetaNamespaceIndexFunc"} + cacheNamespaceIndex = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NamespaceIndex"} + cacheNewGenericLister = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NewGenericLister"} + cacheNewSharedIndexInformer = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NewSharedIndexInformer"} + cacheSharedIndexInformer = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "SharedIndexInformer"} + listOptions = types.Name{Package: "k8s.io/kubernetes/pkg/apis/core", Name: "ListOptions"} + reflectType = types.Name{Package: "reflect", Name: "Type"} + runtimeObject = types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Object"} + schemaGroupResource = types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupResource"} + schemaGroupVersionResource = types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersionResource"} + syncMutex = types.Name{Package: "sync", Name: "Mutex"} + timeDuration = types.Name{Package: "time", Name: "Duration"} + v1ListOptions = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"} + metav1NamespaceAll = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "NamespaceAll"} + metav1Object = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "Object"} + watchInterface = types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"} +) diff --git a/vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go new file mode 100644 index 0000000000..f80350c5f6 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go @@ -0,0 +1,109 @@ +/* +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 generators + +import ( + "io" + + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" +) + +// versionInterfaceGenerator generates the per-version interface file. +type versionInterfaceGenerator struct { + generator.DefaultGen + outputPackage string + imports namer.ImportTracker + types []*types.Type + filtered bool + internalInterfacesPackage string +} + +var _ generator.Generator = &versionInterfaceGenerator{} + +func (g *versionInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool { + if !g.filtered { + g.filtered = true + return true + } + return false +} + +func (g *versionInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *versionInterfaceGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + return +} + +func (g *versionInterfaceGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + m := map[string]interface{}{ + "interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}), + "interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}), + "types": g.types, + } + + sw.Do(versionTemplate, m) + for _, typeDef := range g.types { + tags, err := util.ParseClientGenTags(typeDef.SecondClosestCommentLines) + if err != nil { + return err + } + m["namespaced"] = !tags.NonNamespaced + m["type"] = typeDef + sw.Do(versionFuncTemplate, m) + } + + return sw.Error() +} + +var versionTemplate = ` +// Interface provides access to all the informers in this group version. +type Interface interface { + $range .types -$ + // $.|publicPlural$ returns a $.|public$Informer. + $.|publicPlural$() $.|public$Informer + $end$ +} + +type version struct { + factory $.interfacesSharedInformerFactory|raw$ + namespace string + tweakListOptions $.interfacesTweakListOptionsFunc|raw$ +} + +// New returns a new Interface. +func New(f $.interfacesSharedInformerFactory|raw$, namespace string, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} +` + +var versionFuncTemplate = ` +// $.type|publicPlural$ returns a $.type|public$Informer. +func (v *version) $.type|publicPlural$() $.type|public$Informer { + return &$.type|private$Informer{factory: v.factory$if .namespaced$, namespace: v.namespace$end$, tweakListOptions: v.tweakListOptions} +} +` diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions b/vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions @@ -0,0 +1 @@ +{} diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/BUILD b/vendor/k8s.io/code-generator/cmd/lister-gen/BUILD new file mode 100644 index 0000000000..e2286b8a49 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/BUILD @@ -0,0 +1,44 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", +) + +go_binary( + name = "lister-gen", + embed = [":go_default_library"], +) + +go_library( + name = "go_default_library", + srcs = ["main.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/lister-gen", + importpath = "k8s.io/code-generator/cmd/lister-gen", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/lister-gen/args:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/lister-gen/generators:go_default_library", + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/code-generator/cmd/lister-gen/args:all-srcs", + "//staging/src/k8s.io/code-generator/cmd/lister-gen/generators:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/args/BUILD b/vendor/k8s.io/code-generator/cmd/lister-gen/args/BUILD new file mode 100644 index 0000000000..cff7c2ce45 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/args/BUILD @@ -0,0 +1,28 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["args.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/lister-gen/args", + importpath = "k8s.io/code-generator/cmd/lister-gen/args", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/code-generator/pkg/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go b/vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go new file mode 100644 index 0000000000..34914ea8c9 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go @@ -0,0 +1,56 @@ +/* +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 args + +import ( + "fmt" + "path" + + "github.com/spf13/pflag" + codegenutil "k8s.io/code-generator/pkg/util" + "k8s.io/gengo/args" +) + +// CustomArgs is used by the gengo framework to pass args specific to this generator. +type CustomArgs struct{} + +// NewDefaults returns default arguments for the generator. +func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { + genericArgs := args.Default().WithoutDefaultFlagParsing() + customArgs := &CustomArgs{} + genericArgs.CustomArgs = customArgs + + if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 { + genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/listers") + } + + return genericArgs, customArgs +} + +// AddFlags add the generator flags to the flag set. +func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {} + +// Validate checks the given arguments. +func Validate(genericArgs *args.GeneratorArgs) error { + _ = genericArgs.CustomArgs.(*CustomArgs) + + if len(genericArgs.OutputPackagePath) == 0 { + return fmt.Errorf("output package cannot be empty") + } + + return nil +} diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/generators/BUILD b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/BUILD new file mode 100644 index 0000000000..ec1a2ec626 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/BUILD @@ -0,0 +1,39 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "expansion.go", + "lister.go", + "tags.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/lister-gen/generators", + importpath = "k8s.io/code-generator/cmd/lister-gen/generators", + deps = [ + "//staging/src/k8s.io/code-generator/cmd/client-gen/generators/util:go_default_library", + "//staging/src/k8s.io/code-generator/cmd/client-gen/types:go_default_library", + "//vendor/k8s.io/gengo/args:go_default_library", + "//vendor/k8s.io/gengo/generator:go_default_library", + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go new file mode 100644 index 0000000000..dd45d7749c --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go @@ -0,0 +1,67 @@ +/* +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 generators + +import ( + "io" + "os" + "path/filepath" + "strings" + + "k8s.io/gengo/generator" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" +) + +// expansionGenerator produces a file for a expansion interfaces. +type expansionGenerator struct { + generator.DefaultGen + packagePath string + types []*types.Type +} + +// We only want to call GenerateType() once per group. +func (g *expansionGenerator) Filter(c *generator.Context, t *types.Type) bool { + return t == g.types[0] +} + +func (g *expansionGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + for _, t := range g.types { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if _, err := os.Stat(filepath.Join(g.packagePath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) { + sw.Do(expansionInterfaceTemplate, t) + if !tags.NonNamespaced { + sw.Do(namespacedExpansionInterfaceTemplate, t) + } + } + } + return sw.Error() +} + +var expansionInterfaceTemplate = ` +// $.|public$ListerExpansion allows custom methods to be added to +// $.|public$Lister. +type $.|public$ListerExpansion interface {} +` + +var namespacedExpansionInterfaceTemplate = ` +// $.|public$NamespaceListerExpansion allows custom methods to be added to +// $.|public$NamespaceLister. +type $.|public$NamespaceListerExpansion interface {} +` diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go new file mode 100644 index 0000000000..c8ed5ad4d3 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go @@ -0,0 +1,371 @@ +/* +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 generators + +import ( + "fmt" + "io" + "path/filepath" + "strings" + + "k8s.io/gengo/args" + "k8s.io/gengo/generator" + "k8s.io/gengo/namer" + "k8s.io/gengo/types" + + "k8s.io/code-generator/cmd/client-gen/generators/util" + clientgentypes "k8s.io/code-generator/cmd/client-gen/types" + + "k8s.io/klog" +) + +// NameSystems returns the name system used by the generators in this package. +func NameSystems() namer.NameSystems { + pluralExceptions := map[string]string{ + "Endpoints": "Endpoints", + } + return namer.NameSystems{ + "public": namer.NewPublicNamer(0), + "private": namer.NewPrivateNamer(0), + "raw": namer.NewRawNamer("", nil), + "publicPlural": namer.NewPublicPluralNamer(pluralExceptions), + "allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions), + "lowercaseSingular": &lowercaseSingularNamer{}, + } +} + +// lowercaseSingularNamer implements Namer +type lowercaseSingularNamer struct{} + +// Name returns t's name in all lowercase. +func (n *lowercaseSingularNamer) Name(t *types.Type) string { + return strings.ToLower(t.Name.Name) +} + +// DefaultNameSystem returns the default name system for ordering the types to be +// processed by the generators in this package. +func DefaultNameSystem() string { + return "public" +} + +// Packages makes the client package definition. +func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { + boilerplate, err := arguments.LoadGoBoilerplate() + if err != nil { + klog.Fatalf("Failed loading boilerplate: %v", err) + } + + var packageList generator.Packages + for _, inputDir := range arguments.InputDirs { + p := context.Universe.Package(inputDir) + + objectMeta, internal, err := objectMetaForPackage(p) + if err != nil { + klog.Fatal(err) + } + if objectMeta == nil { + // no types in this package had genclient + continue + } + + var gv clientgentypes.GroupVersion + var internalGVPkg string + + if internal { + lastSlash := strings.LastIndex(p.Path, "/") + if lastSlash == -1 { + klog.Fatalf("error constructing internal group version for package %q", p.Path) + } + gv.Group = clientgentypes.Group(p.Path[lastSlash+1:]) + internalGVPkg = p.Path + } else { + parts := strings.Split(p.Path, "/") + gv.Group = clientgentypes.Group(parts[len(parts)-2]) + gv.Version = clientgentypes.Version(parts[len(parts)-1]) + + internalGVPkg = strings.Join(parts[0:len(parts)-1], "/") + } + groupPackageName := strings.ToLower(gv.Group.NonEmpty()) + + // If there's a comment of the form "// +groupName=somegroup" or + // "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the + // group when generating. + if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil { + gv.Group = clientgentypes.Group(strings.SplitN(override[0], ".", 2)[0]) + } + + var typesToGenerate []*types.Type + for _, t := range p.Types { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if !tags.GenerateClient || !tags.HasVerb("list") || !tags.HasVerb("get") { + continue + } + typesToGenerate = append(typesToGenerate, t) + } + if len(typesToGenerate) == 0 { + continue + } + orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} + typesToGenerate = orderer.OrderTypes(typesToGenerate) + + packagePath := filepath.Join(arguments.OutputPackagePath, groupPackageName, strings.ToLower(gv.Version.NonEmpty())) + packageList = append(packageList, &generator.DefaultPackage{ + PackageName: strings.ToLower(gv.Version.NonEmpty()), + PackagePath: packagePath, + HeaderText: boilerplate, + GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { + generators = append(generators, &expansionGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: "expansion_generated", + }, + packagePath: filepath.Join(arguments.OutputBase, packagePath), + types: typesToGenerate, + }) + + for _, t := range typesToGenerate { + generators = append(generators, &listerGenerator{ + DefaultGen: generator.DefaultGen{ + OptionalName: strings.ToLower(t.Name.Name), + }, + outputPackage: arguments.OutputPackagePath, + groupVersion: gv, + internalGVPkg: internalGVPkg, + typeToGenerate: t, + imports: generator.NewImportTracker(), + objectMeta: objectMeta, + }) + } + return generators + }, + FilterFunc: func(c *generator.Context, t *types.Type) bool { + tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("get") + }, + }) + } + + return packageList +} + +// objectMetaForPackage returns the type of ObjectMeta used by package p. +func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) { + generatingForPackage := false + for _, t := range p.Types { + // filter out types which dont have genclient. + if !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient { + continue + } + generatingForPackage = true + for _, member := range t.Members { + if member.Name == "ObjectMeta" { + return member.Type, isInternal(member), nil + } + } + } + if generatingForPackage { + return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path) + } + return nil, false, nil +} + +// isInternal returns true if the tags for a member do not contain a json tag +func isInternal(m types.Member) bool { + return !strings.Contains(m.Tags, "json") +} + +// listerGenerator produces a file of listers for a given GroupVersion and +// type. +type listerGenerator struct { + generator.DefaultGen + outputPackage string + groupVersion clientgentypes.GroupVersion + internalGVPkg string + typeToGenerate *types.Type + imports namer.ImportTracker + objectMeta *types.Type +} + +var _ generator.Generator = &listerGenerator{} + +func (g *listerGenerator) Filter(c *generator.Context, t *types.Type) bool { + return t == g.typeToGenerate +} + +func (g *listerGenerator) Namers(c *generator.Context) namer.NameSystems { + return namer.NameSystems{ + "raw": namer.NewRawNamer(g.outputPackage, g.imports), + } +} + +func (g *listerGenerator) Imports(c *generator.Context) (imports []string) { + imports = append(imports, g.imports.ImportLines()...) + imports = append(imports, "k8s.io/apimachinery/pkg/api/errors") + imports = append(imports, "k8s.io/apimachinery/pkg/labels") + // for Indexer + imports = append(imports, "k8s.io/client-go/tools/cache") + return +} + +func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { + sw := generator.NewSnippetWriter(w, c, "$", "$") + + klog.V(5).Infof("processing type %v", t) + m := map[string]interface{}{ + "Resource": c.Universe.Function(types.Name{Package: t.Name.Package, Name: "Resource"}), + "type": t, + "objectMeta": g.objectMeta, + } + + tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)) + if err != nil { + return err + } + + if tags.NonNamespaced { + sw.Do(typeListerInterface_NonNamespaced, m) + } else { + sw.Do(typeListerInterface, m) + } + + sw.Do(typeListerStruct, m) + sw.Do(typeListerConstructor, m) + sw.Do(typeLister_List, m) + + if tags.NonNamespaced { + sw.Do(typeLister_NonNamespacedGet, m) + return sw.Error() + } + + sw.Do(typeLister_NamespaceLister, m) + sw.Do(namespaceListerInterface, m) + sw.Do(namespaceListerStruct, m) + sw.Do(namespaceLister_List, m) + sw.Do(namespaceLister_Get, m) + + return sw.Error() +} + +var typeListerInterface = ` +// $.type|public$Lister helps list $.type|publicPlural$. +type $.type|public$Lister interface { + // List lists all $.type|publicPlural$ in the indexer. + List(selector labels.Selector) (ret []*$.type|raw$, err error) + // $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$. + $.type|publicPlural$(namespace string) $.type|public$NamespaceLister + $.type|public$ListerExpansion +} +` + +var typeListerInterface_NonNamespaced = ` +// $.type|public$Lister helps list $.type|publicPlural$. +type $.type|public$Lister interface { + // List lists all $.type|publicPlural$ in the indexer. + List(selector labels.Selector) (ret []*$.type|raw$, err error) + // Get retrieves the $.type|public$ from the index for a given name. + Get(name string) (*$.type|raw$, error) + $.type|public$ListerExpansion +} +` + +var typeListerStruct = ` +// $.type|private$Lister implements the $.type|public$Lister interface. +type $.type|private$Lister struct { + indexer cache.Indexer +} +` + +var typeListerConstructor = ` +// New$.type|public$Lister returns a new $.type|public$Lister. +func New$.type|public$Lister(indexer cache.Indexer) $.type|public$Lister { + return &$.type|private$Lister{indexer: indexer} +} +` + +var typeLister_List = ` +// List lists all $.type|publicPlural$ in the indexer. +func (s *$.type|private$Lister) List(selector labels.Selector) (ret []*$.type|raw$, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*$.type|raw$)) + }) + return ret, err +} +` + +var typeLister_NamespaceLister = ` +// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$. +func (s *$.type|private$Lister) $.type|publicPlural$(namespace string) $.type|public$NamespaceLister { + return $.type|private$NamespaceLister{indexer: s.indexer, namespace: namespace} +} +` + +var typeLister_NonNamespacedGet = ` +// Get retrieves the $.type|public$ from the index for a given name. +func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name) + } + return obj.(*$.type|raw$), nil +} +` + +var namespaceListerInterface = ` +// $.type|public$NamespaceLister helps list and get $.type|publicPlural$. +type $.type|public$NamespaceLister interface { + // List lists all $.type|publicPlural$ in the indexer for a given namespace. + List(selector labels.Selector) (ret []*$.type|raw$, err error) + // Get retrieves the $.type|public$ from the indexer for a given namespace and name. + Get(name string) (*$.type|raw$, error) + $.type|public$NamespaceListerExpansion +} +` + +var namespaceListerStruct = ` +// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister +// interface. +type $.type|private$NamespaceLister struct { + indexer cache.Indexer + namespace string +} +` + +var namespaceLister_List = ` +// List lists all $.type|publicPlural$ in the indexer for a given namespace. +func (s $.type|private$NamespaceLister) List(selector labels.Selector) (ret []*$.type|raw$, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*$.type|raw$)) + }) + return ret, err +} +` + +var namespaceLister_Get = ` +// Get retrieves the $.type|public$ from the indexer for a given namespace and name. +func (s $.type|private$NamespaceLister) Get(name string) (*$.type|raw$, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name) + } + return obj.(*$.type|raw$), nil +} +` diff --git a/vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go new file mode 100644 index 0000000000..d25d5b6304 --- /dev/null +++ b/vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go @@ -0,0 +1,33 @@ +/* +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 generators + +import ( + "k8s.io/gengo/types" + "k8s.io/klog" +) + +// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if +// it exists, the value is boolean. If the tag did not exist, it returns +// false. +func extractBoolTagOrDie(key string, lines []string) bool { + val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines) + if err != nil { + klog.Fatal(err) + } + return val +} diff --git a/vendor/k8s.io/code-generator/code-of-conduct.md b/vendor/k8s.io/code-generator/code-of-conduct.md new file mode 100644 index 0000000000..0d15c00cf3 --- /dev/null +++ b/vendor/k8s.io/code-generator/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/vendor/k8s.io/code-generator/generate-groups.sh b/vendor/k8s.io/code-generator/generate-groups.sh new file mode 100755 index 0000000000..d82002ddaf --- /dev/null +++ b/vendor/k8s.io/code-generator/generate-groups.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +# 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. + +set -o errexit +set -o nounset +set -o pipefail + +# generate-groups generates everything for a project with external types only, e.g. a project based +# on CustomResourceDefinitions. + +if [ "$#" -lt 4 ] || [ "${1}" == "--help" ]; then + cat < ... + + the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all". + the output package name (e.g. github.com/example/project/pkg/generated). + the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis). + the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative + to . + ... arbitrary flags passed to all generator binaries. + + +Examples: + $(basename "$0") all github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" + $(basename "$0") deepcopy,client github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" +EOF + exit 0 +fi + +GENS="$1" +OUTPUT_PKG="$2" +APIS_PKG="$3" +GROUPS_WITH_VERSIONS="$4" +shift 4 + +( + # To support running this script from anywhere, we have to first cd into this directory + # so we can install the tools. + cd "$(dirname "${0}")" + go install ./cmd/{defaulter-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +) + +function codegen::join() { local IFS="$1"; shift; echo "$*"; } + +# enumerate group versions +FQ_APIS=() # e.g. k8s.io/api/apps/v1 +for GVs in ${GROUPS_WITH_VERSIONS}; do + IFS=: read -r G Vs <<<"${GVs}" + + # enumerate versions + for V in ${Vs//,/ }; do + FQ_APIS+=("${APIS_PKG}/${G}/${V}") + done +done + +if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then + echo "Generating deepcopy funcs" + "${GOPATH}/bin/deepcopy-gen" --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" -O zz_generated.deepcopy --bounding-dirs "${APIS_PKG}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "client" <<<"${GENS}"; then + echo "Generating clientset for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" + "${GOPATH}/bin/client-gen" --clientset-name "${CLIENTSET_NAME_VERSIONED:-versioned}" --input-base "" --input "$(codegen::join , "${FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "lister" <<<"${GENS}"; then + echo "Generating listers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/listers" + "${GOPATH}/bin/lister-gen" --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/listers" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "informer" <<<"${GENS}"; then + echo "Generating informers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/informers" + "${GOPATH}/bin/informer-gen" \ + --input-dirs "$(codegen::join , "${FQ_APIS[@]}")" \ + --versioned-clientset-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}/${CLIENTSET_NAME_VERSIONED:-versioned}" \ + --listers-package "${OUTPUT_PKG}/listers" \ + --output-package "${OUTPUT_PKG}/informers" \ + "$@" +fi diff --git a/vendor/k8s.io/code-generator/generate-internal-groups.sh b/vendor/k8s.io/code-generator/generate-internal-groups.sh new file mode 100755 index 0000000000..258b53b56f --- /dev/null +++ b/vendor/k8s.io/code-generator/generate-internal-groups.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +# 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. + +set -o errexit +set -o nounset +set -o pipefail + +# generate-internal-groups generates everything for a project with internal types, e.g. an +# user-provided API server based on k8s.io/apiserver. + +if [ "$#" -lt 5 ] || [ "${1}" == "--help" ]; then + cat < ... + + the generators comma separated to run (deepcopy,defaulter,conversion,client,lister,informer) or "all". + the output package name (e.g. github.com/example/project/pkg/generated). + the internal types dir (e.g. github.com/example/project/pkg/apis). + the external types dir (e.g. github.com/example/project/pkg/apis or githubcom/example/apis). + the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative + to . + ... arbitrary flags passed to all generator binaries. + +Examples: + $(basename "$0") all github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" + $(basename "$0") deepcopy,defaulter,conversion github.com/example/project/pkg/client github.com/example/project/pkg/apis github.com/example/project/apis "foo:v1 bar:v1alpha1,v1beta1" +EOF + exit 0 +fi + +GENS="$1" +OUTPUT_PKG="$2" +INT_APIS_PKG="$3" +EXT_APIS_PKG="$4" +GROUPS_WITH_VERSIONS="$5" +shift 5 + +go install ./"$(dirname "${0}")"/cmd/{defaulter-gen,conversion-gen,client-gen,lister-gen,informer-gen,deepcopy-gen} +function codegen::join() { local IFS="$1"; shift; echo "$*"; } + +# enumerate group versions +ALL_FQ_APIS=() # e.g. k8s.io/kubernetes/pkg/apis/apps k8s.io/api/apps/v1 +INT_FQ_APIS=() # e.g. k8s.io/kubernetes/pkg/apis/apps +EXT_FQ_APIS=() # e.g. k8s.io/api/apps/v1 +for GVs in ${GROUPS_WITH_VERSIONS}; do + IFS=: read -r G Vs <<<"${GVs}" + + if [ -n "${INT_APIS_PKG}" ]; then + ALL_FQ_APIS+=("${INT_APIS_PKG}/${G}") + INT_FQ_APIS+=("${INT_APIS_PKG}/${G}") + fi + + # enumerate versions + for V in ${Vs//,/ }; do + ALL_FQ_APIS+=("${EXT_APIS_PKG}/${G}/${V}") + EXT_FQ_APIS+=("${EXT_APIS_PKG}/${G}/${V}") + done +done + +if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then + echo "Generating deepcopy funcs" + "${GOPATH}/bin/deepcopy-gen" --input-dirs "$(codegen::join , "${ALL_FQ_APIS[@]}")" -O zz_generated.deepcopy --bounding-dirs "${INT_APIS_PKG},${EXT_APIS_PKG}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "defaulter" <<<"${GENS}"; then + echo "Generating defaulters" + "${GOPATH}/bin/defaulter-gen" --input-dirs "$(codegen::join , "${EXT_FQ_APIS[@]}")" -O zz_generated.defaults "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "conversion" <<<"${GENS}"; then + echo "Generating conversions" + "${GOPATH}/bin/conversion-gen" --input-dirs "$(codegen::join , "${ALL_FQ_APIS[@]}")" -O zz_generated.conversion "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "client" <<<"${GENS}"; then + echo "Generating clientset for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" + if [ -n "${INT_APIS_PKG}" ]; then + IFS=" " read -r -a APIS <<< "$(printf '%s/ ' "${INT_FQ_APIS[@]}")" + "${GOPATH}/bin/client-gen" --clientset-name "${CLIENTSET_NAME_INTERNAL:-internalversion}" --input-base "" --input "$(codegen::join , "${APIS[@]}")" --output-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" "$@" + fi + "${GOPATH}/bin/client-gen" --clientset-name "${CLIENTSET_NAME_VERSIONED:-versioned}" --input-base "" --input "$(codegen::join , "${EXT_FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "lister" <<<"${GENS}"; then + echo "Generating listers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/listers" + "${GOPATH}/bin/lister-gen" --input-dirs "$(codegen::join , "${ALL_FQ_APIS[@]}")" --output-package "${OUTPUT_PKG}/listers" "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "informer" <<<"${GENS}"; then + echo "Generating informers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/informers" + "${GOPATH}/bin/informer-gen" \ + --input-dirs "$(codegen::join , "${ALL_FQ_APIS[@]}")" \ + --versioned-clientset-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}/${CLIENTSET_NAME_VERSIONED:-versioned}" \ + --internal-clientset-package "${OUTPUT_PKG}/${CLIENTSET_PKG_NAME:-clientset}/${CLIENTSET_NAME_INTERNAL:-internalversion}" \ + --listers-package "${OUTPUT_PKG}/listers" \ + --output-package "${OUTPUT_PKG}/informers" \ + "$@" +fi diff --git a/vendor/k8s.io/code-generator/pkg/namer/BUILD b/vendor/k8s.io/code-generator/pkg/namer/BUILD new file mode 100644 index 0000000000..cbed26a69b --- /dev/null +++ b/vendor/k8s.io/code-generator/pkg/namer/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["tag-override.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/pkg/namer", + importpath = "k8s.io/code-generator/pkg/namer", + visibility = ["//visibility:public"], + deps = [ + "//vendor/k8s.io/gengo/namer:go_default_library", + "//vendor/k8s.io/gengo/types:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/pkg/namer/tag-override.go b/vendor/k8s.io/code-generator/pkg/namer/tag-override.go new file mode 100644 index 0000000000..fd8c3a8553 --- /dev/null +++ b/vendor/k8s.io/code-generator/pkg/namer/tag-override.go @@ -0,0 +1,58 @@ +/* +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 namer + +import ( + "k8s.io/gengo/namer" + "k8s.io/gengo/types" +) + +// TagOverrideNamer is a namer which pulls names from a given tag, if specified, +// and otherwise falls back to a different namer. +type TagOverrideNamer struct { + tagName string + fallback namer.Namer +} + +// Name returns the tag value if it exists. It no tag was found the fallback namer will be used +func (n *TagOverrideNamer) Name(t *types.Type) string { + if nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...)); nameOverride != "" { + return nameOverride + } + + return n.fallback.Name(t) +} + +// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as +// the name, or falls back to another Namer if the tag is not present. +func NewTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer { + return &TagOverrideNamer{ + tagName: tagName, + fallback: fallback, + } +} + +// extractTag gets the comment-tags for the key. If the tag did not exist, it +// returns the empty string. +func extractTag(key string, lines []string) string { + val, present := types.ExtractCommentTags("+", lines)[key] + if !present || len(val) < 1 { + return "" + } + + return val[0] +} diff --git a/vendor/k8s.io/code-generator/pkg/util/BUILD b/vendor/k8s.io/code-generator/pkg/util/BUILD new file mode 100644 index 0000000000..d98aaff22c --- /dev/null +++ b/vendor/k8s.io/code-generator/pkg/util/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["build.go"], + importmap = "k8s.io/kubernetes/vendor/k8s.io/code-generator/pkg/util", + importpath = "k8s.io/code-generator/pkg/util", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/code-generator/pkg/util/build.go b/vendor/k8s.io/code-generator/pkg/util/build.go new file mode 100644 index 0000000000..6ea8f52ee0 --- /dev/null +++ b/vendor/k8s.io/code-generator/pkg/util/build.go @@ -0,0 +1,61 @@ +/* +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 util + +import ( + gobuild "go/build" + "path" + "path/filepath" + "reflect" + "strings" +) + +type empty struct{} + +// CurrentPackage returns the go package of the current directory, or "" if it cannot +// be derived from the GOPATH. +func CurrentPackage() string { + for _, root := range gobuild.Default.SrcDirs() { + if pkg, ok := hasSubdir(root, "."); ok { + return pkg + } + } + return "" +} + +func hasSubdir(root, dir string) (rel string, ok bool) { + // ensure a tailing separator to properly compare on word-boundaries + const sep = string(filepath.Separator) + root = filepath.Clean(root) + if !strings.HasSuffix(root, sep) { + root += sep + } + + // check whether root dir starts with root + dir = filepath.Clean(dir) + if !strings.HasPrefix(dir, root) { + return "", false + } + + // cut off root + return filepath.ToSlash(dir[len(root):]), true +} + +// BoilerplatePath uses the boilerplate in code-generator by calculating the relative path to it. +func BoilerplatePath() string { + return path.Join(reflect.TypeOf(empty{}).PkgPath(), "/../../hack/boilerplate.go.txt") +} diff --git a/vendor/k8s.io/kubernetes/staging/BUILD b/vendor/k8s.io/kubernetes/staging/BUILD new file mode 100644 index 0000000000..c65fc44885 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/staging/OWNERS b/vendor/k8s.io/kubernetes/staging/OWNERS new file mode 100644 index 0000000000..0a9750f023 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/OWNERS @@ -0,0 +1,16 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- lavalamp +- smarterclayton +reviewers: +- lavalamp +- smarterclayton +- wojtek-t +- deads2k +- caesarxuchao +- mikedanese +- liggitt +- nikhiljindal +- sttts +- krousey diff --git a/vendor/k8s.io/kubernetes/staging/README.md b/vendor/k8s.io/kubernetes/staging/README.md new file mode 100644 index 0000000000..727c5b33a4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/README.md @@ -0,0 +1,105 @@ +# External Repository Staging Area + +This directory is the staging area for packages that have been split to their +own repository. The content here will be periodically published to respective +top-level k8s.io repositories. + +Repositories currently staged here: + +- [`k8s.io/api`](https://github.com/kubernetes/api) +- [`k8s.io/apiextensions-apiserver`](https://github.com/kubernetes/apiextensions-apiserver) +- [`k8s.io/apimachinery`](https://github.com/kubernetes/apimachinery) +- [`k8s.io/apiserver`](https://github.com/kubernetes/apiserver) +- [`k8s.io/cli-runtime`](https://github.com/kubernetes/cli-runtime) +- [`k8s.io/client-go`](https://github.com/kubernetes/client-go) +- [`k8s.io/cloud-provider`](https://github.com/kubernetes/cloud-provider) +- [`k8s.io/cluster-bootstrap`](https://github.com/kubernetes/cluster-bootstrap) +- [`k8s.io/code-generator`](https://github.com/kubernetes/code-generator) +- [`k8s.io/component-base`](https://github.com/kubernetes/component-base) +- [`k8s.io/csi-api`](https://github.com/kubernetes/csi-api) +- [`k8s.io/csi-translation-lib`](https://github.com/kubernetes/csi-translation-lib) +- [`k8s.io/kube-aggregator`](https://github.com/kubernetes/kube-aggregator) +- [`k8s.io/kube-controller-manager`](https://github.com/kubernetes/kube-controller-manager) +- [`k8s.io/kube-proxy`](https://github.com/kubernetes/kube-proxy) +- [`k8s.io/kube-scheduler`](https://github.com/kubernetes/kube-scheduler) +- [`k8s.io/kubelet`](https://github.com/kubernetes/kubelet) +- [`k8s.io/metrics`](https://github.com/kubernetes/metrics) +- [`k8s.io/node-api`](https://github.com/kubernetes/node-api) +- [`k8s.io/sample-apiserver`](https://github.com/kubernetes/sample-apiserver) +- [`k8s.io/sample-cli-plugin`](https://github.com/kubernetes/sample-cli-plugin) +- [`k8s.io/sample-controller`](https://github.com/kubernetes/sample-controller) + +The code in the staging/ directory is authoritative, i.e. the only copy of the +code. You can directly modify such code. + +## Using staged repositories from Kubernetes code + +Kubernetes code uses the repositories in this directory via symlinks in the +`vendor/k8s.io` directory into this staging area. For example, when +Kubernetes code imports a package from the `k8s.io/client-go` repository, that +import is resolved to `staging/src/k8s.io/client-go` relative to the project +root: + +```go +// pkg/example/some_code.go +package example + +import ( + "k8s.io/client-go/dynamic" // resolves to staging/src/k8s.io/client-go/dynamic +) +``` + +Once the change-over to external repositories is complete, these repositories +will actually be vendored from `k8s.io/`. + +## Creating a new repository in staging + +### Adding the staging repository in `kubernetes/kubernetes`: + +1. Send an email to the SIG Architecture +[mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-architecture) +and the mailing list of the SIG which would own the repo requesting approval +for creating the staging repository. + +2. Once approval has been granted, create the new staging repository. + +3. Add a symlink to the staging repo in `vendor/k8s.io`. + +4. Update [`import-restrictions.yaml`](/staging/publishing/import-restrictions.yaml) +to add the list of other staging repos that this new repo can import. + +5. Add all mandatory template files to the staging repo as mentioned in +https://github.com/kubernetes/kubernetes-template-project. + +6. Make sure that the `.github/PULL_REQUEST_TEMPLATE.md` and +`CONTRIBUTING.md` files mention that PRs are not directly accepted to the repo. + +### Creating the published repository + +1. Create an [issue](https://github.com/kubernetes/org/issues/new?template=repo-create.md) +in the `kubernetes/org` repo to request creation of the respective published +repository in the Kubernetes org. The published repository **must** have an +initial empty commit. It also needs specific access rules and branch settings. +See [#kubernetes/org#58](https://github.com/kubernetes/org/issues/58) +for an example. + +2. Setup branch protection and enable access to the `stage-bots` team +by adding the repo in +[`prow/config.yaml`](https://github.com/kubernetes/test-infra/blob/master/prow/config.yaml). +See [#kubernetes/test-infra#9292](https://github.com/kubernetes/test-infra/pull/9292) +for an example. + +3. Once the repository has been created in the Kubernetes org, +update the publishing-bot to publish the staging repository by updating: + + - [`rules.yaml`](/staging/publishing/rules.yaml): + Make sure that the list of dependencies reflects the staging repos in the `Godeps.json` file. + + - [`fetch-all-latest-and-push.sh`](https://github.com/kubernetes/publishing-bot/blob/master/hack/fetch-all-latest-and-push.sh): + Add the staging repo in the list of repos to be published. + +4. Add the staging and published repositories as a subproject for the +SIG that owns the repos in +[`sigs.yaml`](https://github.com/kubernetes/community/blob/master/sigs.yaml). + +5. Add the repo to the list of staging repos in this `README.md` file. diff --git a/vendor/k8s.io/kubernetes/staging/repos_generated.bzl b/vendor/k8s.io/kubernetes/staging/repos_generated.bzl new file mode 100644 index 0000000000..36a818abb5 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/repos_generated.bzl @@ -0,0 +1,41 @@ +# 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 is autogenerated by hack/update-bazel.sh. +# DO NOT EDIT. + +staging_repos = [ + "k8s.io/api", + "k8s.io/apiextensions-apiserver", + "k8s.io/apimachinery", + "k8s.io/apiserver", + "k8s.io/cli-runtime", + "k8s.io/client-go", + "k8s.io/cloud-provider", + "k8s.io/cluster-bootstrap", + "k8s.io/code-generator", + "k8s.io/component-base", + "k8s.io/csi-api", + "k8s.io/csi-translation-lib", + "k8s.io/kube-aggregator", + "k8s.io/kube-controller-manager", + "k8s.io/kube-proxy", + "k8s.io/kube-scheduler", + "k8s.io/kubelet", + "k8s.io/metrics", + "k8s.io/node-api", + "k8s.io/sample-apiserver", + "k8s.io/sample-cli-plugin", + "k8s.io/sample-controller", +] diff --git a/vendor/k8s.io/kubernetes/staging/src/BUILD b/vendor/k8s.io/kubernetes/staging/src/BUILD new file mode 100644 index 0000000000..cfd27efd16 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/BUILD @@ -0,0 +1,43 @@ +# gazelle gets confused by our staging/ directory, prepending an extra +# "k8s.io/kubernetes/staging/src" to the importpath. +# Using this directive ensures that it sets the correct importpath. +# gazelle:prefix +# gazelle:importmap_prefix k8s.io/kubernetes/vendor + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/api:all-srcs", + "//staging/src/k8s.io/apiextensions-apiserver:all-srcs", + "//staging/src/k8s.io/apimachinery:all-srcs", + "//staging/src/k8s.io/apiserver:all-srcs", + "//staging/src/k8s.io/cli-runtime:all-srcs", + "//staging/src/k8s.io/client-go:all-srcs", + "//staging/src/k8s.io/cloud-provider:all-srcs", + "//staging/src/k8s.io/cluster-bootstrap:all-srcs", + "//staging/src/k8s.io/code-generator:all-srcs", + "//staging/src/k8s.io/component-base:all-srcs", + "//staging/src/k8s.io/csi-api:all-srcs", + "//staging/src/k8s.io/csi-translation-lib:all-srcs", + "//staging/src/k8s.io/kube-aggregator:all-srcs", + "//staging/src/k8s.io/kube-controller-manager:all-srcs", + "//staging/src/k8s.io/kube-proxy:all-srcs", + "//staging/src/k8s.io/kube-scheduler:all-srcs", + "//staging/src/k8s.io/kubelet:all-srcs", + "//staging/src/k8s.io/metrics:all-srcs", + "//staging/src/k8s.io/node-api:all-srcs", + "//staging/src/k8s.io/sample-apiserver:all-srcs", + "//staging/src/k8s.io/sample-cli-plugin:all-srcs", + "//staging/src/k8s.io/sample-controller:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/BUILD new file mode 100644 index 0000000000..02fd33cbc2 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/BUILD @@ -0,0 +1,94 @@ +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs", + "//staging/src/k8s.io/client-go/discovery:all-srcs", + "//staging/src/k8s.io/client-go/dynamic:all-srcs", + "//staging/src/k8s.io/client-go/examples/create-update-delete-deployment:all-srcs", + "//staging/src/k8s.io/client-go/examples/fake-client:all-srcs", + "//staging/src/k8s.io/client-go/examples/in-cluster-client-configuration:all-srcs", + "//staging/src/k8s.io/client-go/examples/out-of-cluster-client-configuration:all-srcs", + "//staging/src/k8s.io/client-go/examples/workqueue:all-srcs", + "//staging/src/k8s.io/client-go/informers:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes_test:all-srcs", + "//staging/src/k8s.io/client-go/listers/admissionregistration/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/apps/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/apps/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/apps/v1beta2:all-srcs", + "//staging/src/k8s.io/client-go/listers/auditregistration/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/authentication/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/authentication/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/authorization/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/authorization/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/autoscaling/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/autoscaling/v2beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/autoscaling/v2beta2:all-srcs", + "//staging/src/k8s.io/client-go/listers/batch/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/batch/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/batch/v2alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/coordination/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/coordination/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/core/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/events/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/extensions/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/imagepolicy/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/networking/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/networking/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/node/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/node/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/policy/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/rbac/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/rbac/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/rbac/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/scheduling/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/scheduling/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/listers/settings/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/storage/v1:all-srcs", + "//staging/src/k8s.io/client-go/listers/storage/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/listers/storage/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/pkg/apis/clientauthentication:all-srcs", + "//staging/src/k8s.io/client-go/pkg/version:all-srcs", + "//staging/src/k8s.io/client-go/plugin/pkg/client/auth:all-srcs", + "//staging/src/k8s.io/client-go/rest:all-srcs", + "//staging/src/k8s.io/client-go/restmapper:all-srcs", + "//staging/src/k8s.io/client-go/scale:all-srcs", + "//staging/src/k8s.io/client-go/testing:all-srcs", + "//staging/src/k8s.io/client-go/third_party/forked/golang/template:all-srcs", + "//staging/src/k8s.io/client-go/tools/auth:all-srcs", + "//staging/src/k8s.io/client-go/tools/cache:all-srcs", + "//staging/src/k8s.io/client-go/tools/clientcmd:all-srcs", + "//staging/src/k8s.io/client-go/tools/leaderelection:all-srcs", + "//staging/src/k8s.io/client-go/tools/metrics:all-srcs", + "//staging/src/k8s.io/client-go/tools/pager:all-srcs", + "//staging/src/k8s.io/client-go/tools/portforward:all-srcs", + "//staging/src/k8s.io/client-go/tools/record:all-srcs", + "//staging/src/k8s.io/client-go/tools/reference:all-srcs", + "//staging/src/k8s.io/client-go/tools/remotecommand:all-srcs", + "//staging/src/k8s.io/client-go/tools/watch:all-srcs", + "//staging/src/k8s.io/client-go/transport:all-srcs", + "//staging/src/k8s.io/client-go/util/cert:all-srcs", + "//staging/src/k8s.io/client-go/util/certificate:all-srcs", + "//staging/src/k8s.io/client-go/util/connrotation:all-srcs", + "//staging/src/k8s.io/client-go/util/exec:all-srcs", + "//staging/src/k8s.io/client-go/util/flowcontrol:all-srcs", + "//staging/src/k8s.io/client-go/util/homedir:all-srcs", + "//staging/src/k8s.io/client-go/util/jsonpath:all-srcs", + "//staging/src/k8s.io/client-go/util/keyutil:all-srcs", + "//staging/src/k8s.io/client-go/util/retry:all-srcs", + "//staging/src/k8s.io/client-go/util/testing:all-srcs", + "//staging/src/k8s.io/client-go/util/workqueue:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/CONTRIBUTING.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/CONTRIBUTING.md new file mode 100644 index 0000000000..267164690d --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing guidelines + +Do not open pull requests directly against this repository, they will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes. + +This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/client-go](https://git.k8s.io/kubernetes/staging/src/k8s.io/client-go) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot). + +Please see [Staging Directory and Publishing](https://git.k8s.io/community/contributors/devel/sig-architecture/staging.md) for more information diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/INSTALL.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/INSTALL.md new file mode 100644 index 0000000000..d3592f490a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/INSTALL.md @@ -0,0 +1,162 @@ +# Installing client-go + +## For the casual user + +If you want to write a simple script, don't care about a reproducible client +library install, don't mind getting head (which may be less stable than a +particular release), then simply: + +```sh +$ go get k8s.io/client-go/... +``` + +This will install `k8s.io/client-go` in your `$GOPATH`. `k8s.io/client-go` +includes most of its own dependencies in its `k8s.io/client-go/vendor` path, +except for `k8s.io/apimachinery` and `glog`. `go get` will recursively download +these excluded repos to your `$GOPATH`, if they don't already exist. If +`k8s.io/apimachinery` preexisted in `$GOPATH`, you also need to: + +```sh +$ go get -u k8s.io/apimachinery/... +``` + +because the head of client-go is only guaranteed to work with the head of +apimachinery. + +We excluded `k8s.io/apimachinery` and `glog` from `k8s.io/client-go/vendor` to +prevent `go get` users from hitting issues like +[#19](https://github.com/kubernetes/client-go/issues/19) and +[#83](https://github.com/kubernetes/client-go/issues/83). If your project share +other dependencies with client-go, and you hit issues similar to #19 or #83, +then you'll need to look down at the next section. + +Note: the official go policy is that libraries should not vendor their +dependencies. This is unworkable for us, since our dependencies change and HEAD +on every dependency has not necessarily been tested with client-go. In fact, +HEAD from all dependencies may not even compile with client-go! + +## Dependency management for the serious (or reluctant) user + +Reasons why you might need to use a dependency management system: +* You use a dependency that client-go also uses, and don't want two copies of + the dependency compiled into your application. For some dependencies with + singletons or global inits (e.g. `glog`) this wouldn't even compile... +* You want to lock in a particular version (so you don't have to change your + code every time we change a public interface). +* You want your install to be reproducible. For example, for your CI system or + for new team members. + +There are three tools you could in theory use for this. Instructions +for each follows. + +### Godep + +[godep](https://github.com/tools/godep) is an older dependency management tool, which is +used by the main Kubernetes repo and `client-go` to manage dependencies. + +Before proceeding with the below instructions, you should ensure that your +$GOPATH is empty except for containing your own package and its dependencies, +and you have a copy of godep somewhere in your $PATH. + +To install `client-go` and place its dependencies in your `$GOPATH`: + +```sh +go get k8s.io/client-go/... +cd $GOPATH/src/k8s.io/client-go +git checkout v9.0.0 # replace v9.0.0 with the required version +# cd 1.5 # only necessary with 1.5 and 1.4 clients. +godep restore ./... +``` + +At this point, `client-go`'s dependencies have been placed in your $GOPATH, but +if you were to build, `client-go` would still see its own copy of its +dependencies in its `vendor` directory. You have two options at this point. + +If you would like to keep dependencies in your own project's vendor directory, +then you can continue like this: + +```sh +cd $GOPATH/src/ +godep save ./... +``` + +Alternatively, if you want to build using the dependencies in your `$GOPATH`, +then `rm -rf vendor/` to remove `client-go`'s copy of its dependencies. + +### Glide + +[Glide](https://github.com/Masterminds/glide) is another popular dependency +management tool for Go. Glide will manage your /vendor directory, but unlike +godep, will not use or modify your $GOPATH (there's no equivalent of +`godep restore` or `godep save`). + +Generally, it's best to avoid Glide's many subcommands, favoring modifying +Glide's manifest file (`glide.yaml`) directly, then running +`glide update --strip-vendor`. First create a `glide.yaml` file at the root of +your project: + +```yaml +package: ( your project's import path ) # e.g. github.com/foo/bar +import: +- package: k8s.io/client-go + version: v9.0.0 # replace v9.0.0 with the required version +``` + +Second, add a Go file that imports `client-go` somewhere in your project, +otherwise `client-go`'s dependencies will not be added to your project's +vendor/. Then run the following command in the same directory as `glide.yaml`: + +```sh +glide update --strip-vendor +``` + +This can also be abbreviated as: + +```sh +glide up -v +``` + +At this point, `k8s.io/client-go` should be added to your project's vendor/. +`client-go`'s dependencies should be flattened and be added to your project's +vendor/ as well. + +Glide will detect the versions of dependencies `client-go` specified in +`client-go`'s Godep.json file, and automatically set the versions of these +imports in your /vendor directory. It will also record the detected version of +all dependencies in the `glide.lock` file. + +Projects that require a different version of a dependency than `client-go` +requests can override the version manually in `glide.yaml`. For example: + +```yaml +package: ( your project's import path ) # e.g. github.com/foo/bar +import: +- package: k8s.io/client-go + version: v9.0.0 # replace v9.0.0 with the required version +# Use a newer version of go-spew even though client-go wants an old one. +- package: github.com/davecgh/go-spew + version: v1.1.0 +``` + +After modifying, run `glide up -v` again to re-populate your /vendor directory. + +Optionally, Glide users can also use [`glide-vc`](https://github.com/sgotti/glide-vc) +after running `glide up -v` to remove unused files from /vendor. + +### Dep (Not supported yet!) + +[dep](https://github.com/golang/dep) is an up-and-coming dependency management +tool, which has the goal of being accepted as part of the standard go toolchain. +However, client-go does **NOT** work well with `dep` yet. To support `dep`, we +need to fix at least two issues: +1. publish native `Gopkg.toml` in client-go and other k8s.io repos, like `k8s.io/apimachinery`; +2. find a way to express transitive constraints (see https://github.com/golang/dep/issues/1124). + +As a workaround, which may or may not be worthwhile, you can specify all +client-go dependencies manually as +[override](https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md#override) +in Gopkg.toml with the versions listed in [Godeps.json](./Godeps/Godeps.json), +and manually update them when you upgrade client-go version. + +We are actively working on the two issues blocking using `dep`. For the +meantime, we recommend using `glide` or `godeps`. diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/LICENSE b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/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/kubernetes/staging/src/k8s.io/client-go/OWNERS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS new file mode 100644 index 0000000000..2f9f0fb4dc --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/OWNERS @@ -0,0 +1,19 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- caesarxuchao +- deads2k +- lavalamp +- liggitt +- smarterclayton +- sttts +reviewers: +- caesarxuchao +- deads2k +- lavalamp +- liggitt +- soltysh +- sttts +- yliaog +labels: +- sig/api-machinery diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS new file mode 100644 index 0000000000..70b7cf9a65 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/SECURITY_CONTACTS @@ -0,0 +1,17 @@ +# Defined below are the security contacts for this repo. +# +# They are the contact point for the Product Security Committee to reach out +# to for triaging and handling of incoming issues. +# +# The below names agree to abide by the +# [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) +# and will be removed and replaced if they violate that agreement. +# +# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE +# INSTRUCTIONS AT https://kubernetes.io/security/ + +cjcullen +jessfraz +liggitt +philips +tallclair diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/code-of-conduct.md b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/code-of-conduct.md new file mode 100644 index 0000000000..0d15c00cf3 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/code-of-conduct.md @@ -0,0 +1,3 @@ +# Kubernetes Community Code of Conduct + +Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD new file mode 100644 index 0000000000..81541d4d49 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/BUILD @@ -0,0 +1,108 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "clientset.go", + "doc.go", + "import.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/kubernetes", + importpath = "k8s.io/client-go/kubernetes", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/client-go/discovery:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/node/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/node/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/client-go/kubernetes/fake:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/scheme:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1beta2:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/auditregistration/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/authentication/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/batch/v2alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/coordination/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/events/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/networking/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/node/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/node/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/policy/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/scheduling/v1beta1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/settings/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1alpha1:all-srcs", + "//staging/src/k8s.io/client-go/kubernetes/typed/storage/v1beta1:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go new file mode 100644 index 0000000000..e2a8102f9c --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/clientset.go @@ -0,0 +1,482 @@ +/* +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 client-gen. DO NOT EDIT. + +package kubernetes + +import ( + discovery "k8s.io/client-go/discovery" + admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1" + appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + appsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1" + appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2" + authenticationv1 "k8s.io/client-go/kubernetes/typed/authentication/v1" + authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1" + authorizationv1beta1 "k8s.io/client-go/kubernetes/typed/authorization/v1beta1" + autoscalingv1 "k8s.io/client-go/kubernetes/typed/autoscaling/v1" + autoscalingv2beta1 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1" + autoscalingv2beta2 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2" + batchv1 "k8s.io/client-go/kubernetes/typed/batch/v1" + batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1" + batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1" + certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" + coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1" + coordinationv1beta1 "k8s.io/client-go/kubernetes/typed/coordination/v1beta1" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + extensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1" + networkingv1 "k8s.io/client-go/kubernetes/typed/networking/v1" + networkingv1beta1 "k8s.io/client-go/kubernetes/typed/networking/v1beta1" + nodev1alpha1 "k8s.io/client-go/kubernetes/typed/node/v1alpha1" + nodev1beta1 "k8s.io/client-go/kubernetes/typed/node/v1beta1" + policyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1" + rbacv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" + rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1" + schedulingv1 "k8s.io/client-go/kubernetes/typed/scheduling/v1" + schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1" + storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1" + storagev1beta1 "k8s.io/client-go/kubernetes/typed/storage/v1beta1" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface + AppsV1() appsv1.AppsV1Interface + AppsV1beta1() appsv1beta1.AppsV1beta1Interface + AppsV1beta2() appsv1beta2.AppsV1beta2Interface + AuthenticationV1() authenticationv1.AuthenticationV1Interface + AuthorizationV1() authorizationv1.AuthorizationV1Interface + AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface + AutoscalingV1() autoscalingv1.AutoscalingV1Interface + AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface + AutoscalingV2beta2() autoscalingv2beta2.AutoscalingV2beta2Interface + BatchV1() batchv1.BatchV1Interface + BatchV1beta1() batchv1beta1.BatchV1beta1Interface + BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface + CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface + CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface + CoordinationV1() coordinationv1.CoordinationV1Interface + CoreV1() corev1.CoreV1Interface + ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface + NetworkingV1() networkingv1.NetworkingV1Interface + NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface + NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface + NodeV1beta1() nodev1beta1.NodeV1beta1Interface + PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface + RbacV1() rbacv1.RbacV1Interface + RbacV1beta1() rbacv1beta1.RbacV1beta1Interface + SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface + SchedulingV1() schedulingv1.SchedulingV1Interface + StorageV1beta1() storagev1beta1.StorageV1beta1Interface + StorageV1() storagev1.StorageV1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client + appsV1 *appsv1.AppsV1Client + appsV1beta1 *appsv1beta1.AppsV1beta1Client + appsV1beta2 *appsv1beta2.AppsV1beta2Client + authenticationV1 *authenticationv1.AuthenticationV1Client + authorizationV1 *authorizationv1.AuthorizationV1Client + authorizationV1beta1 *authorizationv1beta1.AuthorizationV1beta1Client + autoscalingV1 *autoscalingv1.AutoscalingV1Client + autoscalingV2beta1 *autoscalingv2beta1.AutoscalingV2beta1Client + autoscalingV2beta2 *autoscalingv2beta2.AutoscalingV2beta2Client + batchV1 *batchv1.BatchV1Client + batchV1beta1 *batchv1beta1.BatchV1beta1Client + batchV2alpha1 *batchv2alpha1.BatchV2alpha1Client + certificatesV1beta1 *certificatesv1beta1.CertificatesV1beta1Client + coordinationV1beta1 *coordinationv1beta1.CoordinationV1beta1Client + coordinationV1 *coordinationv1.CoordinationV1Client + coreV1 *corev1.CoreV1Client + extensionsV1beta1 *extensionsv1beta1.ExtensionsV1beta1Client + networkingV1 *networkingv1.NetworkingV1Client + networkingV1beta1 *networkingv1beta1.NetworkingV1beta1Client + nodeV1alpha1 *nodev1alpha1.NodeV1alpha1Client + nodeV1beta1 *nodev1beta1.NodeV1beta1Client + policyV1beta1 *policyv1beta1.PolicyV1beta1Client + rbacV1 *rbacv1.RbacV1Client + rbacV1beta1 *rbacv1beta1.RbacV1beta1Client + schedulingV1beta1 *schedulingv1beta1.SchedulingV1beta1Client + schedulingV1 *schedulingv1.SchedulingV1Client + storageV1beta1 *storagev1beta1.StorageV1beta1Client + storageV1 *storagev1.StorageV1Client +} + +// AdmissionregistrationV1beta1 retrieves the AdmissionregistrationV1beta1Client +func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface { + return c.admissionregistrationV1beta1 +} + +// AppsV1 retrieves the AppsV1Client +func (c *Clientset) AppsV1() appsv1.AppsV1Interface { + return c.appsV1 +} + +// AppsV1beta1 retrieves the AppsV1beta1Client +func (c *Clientset) AppsV1beta1() appsv1beta1.AppsV1beta1Interface { + return c.appsV1beta1 +} + +// AppsV1beta2 retrieves the AppsV1beta2Client +func (c *Clientset) AppsV1beta2() appsv1beta2.AppsV1beta2Interface { + return c.appsV1beta2 +} + +// AuthenticationV1 retrieves the AuthenticationV1Client +func (c *Clientset) AuthenticationV1() authenticationv1.AuthenticationV1Interface { + return c.authenticationV1 +} + +// AuthorizationV1 retrieves the AuthorizationV1Client +func (c *Clientset) AuthorizationV1() authorizationv1.AuthorizationV1Interface { + return c.authorizationV1 +} + +// AuthorizationV1beta1 retrieves the AuthorizationV1beta1Client +func (c *Clientset) AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface { + return c.authorizationV1beta1 +} + +// AutoscalingV1 retrieves the AutoscalingV1Client +func (c *Clientset) AutoscalingV1() autoscalingv1.AutoscalingV1Interface { + return c.autoscalingV1 +} + +// AutoscalingV2beta1 retrieves the AutoscalingV2beta1Client +func (c *Clientset) AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface { + return c.autoscalingV2beta1 +} + +// AutoscalingV2beta2 retrieves the AutoscalingV2beta2Client +func (c *Clientset) AutoscalingV2beta2() autoscalingv2beta2.AutoscalingV2beta2Interface { + return c.autoscalingV2beta2 +} + +// BatchV1 retrieves the BatchV1Client +func (c *Clientset) BatchV1() batchv1.BatchV1Interface { + return c.batchV1 +} + +// BatchV1beta1 retrieves the BatchV1beta1Client +func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface { + return c.batchV1beta1 +} + +// BatchV2alpha1 retrieves the BatchV2alpha1Client +func (c *Clientset) BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface { + return c.batchV2alpha1 +} + +// CertificatesV1beta1 retrieves the CertificatesV1beta1Client +func (c *Clientset) CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface { + return c.certificatesV1beta1 +} + +// CoordinationV1beta1 retrieves the CoordinationV1beta1Client +func (c *Clientset) CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface { + return c.coordinationV1beta1 +} + +// CoordinationV1 retrieves the CoordinationV1Client +func (c *Clientset) CoordinationV1() coordinationv1.CoordinationV1Interface { + return c.coordinationV1 +} + +// CoreV1 retrieves the CoreV1Client +func (c *Clientset) CoreV1() corev1.CoreV1Interface { + return c.coreV1 +} + +// ExtensionsV1beta1 retrieves the ExtensionsV1beta1Client +func (c *Clientset) ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface { + return c.extensionsV1beta1 +} + +// NetworkingV1 retrieves the NetworkingV1Client +func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface { + return c.networkingV1 +} + +// NetworkingV1beta1 retrieves the NetworkingV1beta1Client +func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface { + return c.networkingV1beta1 +} + +// NodeV1alpha1 retrieves the NodeV1alpha1Client +func (c *Clientset) NodeV1alpha1() nodev1alpha1.NodeV1alpha1Interface { + return c.nodeV1alpha1 +} + +// NodeV1beta1 retrieves the NodeV1beta1Client +func (c *Clientset) NodeV1beta1() nodev1beta1.NodeV1beta1Interface { + return c.nodeV1beta1 +} + +// PolicyV1beta1 retrieves the PolicyV1beta1Client +func (c *Clientset) PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface { + return c.policyV1beta1 +} + +// RbacV1 retrieves the RbacV1Client +func (c *Clientset) RbacV1() rbacv1.RbacV1Interface { + return c.rbacV1 +} + +// RbacV1beta1 retrieves the RbacV1beta1Client +func (c *Clientset) RbacV1beta1() rbacv1beta1.RbacV1beta1Interface { + return c.rbacV1beta1 +} + +// SchedulingV1beta1 retrieves the SchedulingV1beta1Client +func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface { + return c.schedulingV1beta1 +} + +// SchedulingV1 retrieves the SchedulingV1Client +func (c *Clientset) SchedulingV1() schedulingv1.SchedulingV1Interface { + return c.schedulingV1 +} + +// StorageV1beta1 retrieves the StorageV1beta1Client +func (c *Clientset) StorageV1beta1() storagev1beta1.StorageV1beta1Interface { + return c.storageV1beta1 +} + +// StorageV1 retrieves the StorageV1Client +func (c *Clientset) StorageV1() storagev1.StorageV1Interface { + return c.storageV1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.admissionregistrationV1beta1, err = admissionregistrationv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.appsV1, err = appsv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.appsV1beta1, err = appsv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.appsV1beta2, err = appsv1beta2.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.authenticationV1, err = authenticationv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.authorizationV1, err = authorizationv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.authorizationV1beta1, err = authorizationv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.autoscalingV1, err = autoscalingv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.autoscalingV2beta1, err = autoscalingv2beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.autoscalingV2beta2, err = autoscalingv2beta2.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.batchV1, err = batchv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.batchV1beta1, err = batchv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.batchV2alpha1, err = batchv2alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.certificatesV1beta1, err = certificatesv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.coordinationV1beta1, err = coordinationv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.coordinationV1, err = coordinationv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.coreV1, err = corev1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.extensionsV1beta1, err = extensionsv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.networkingV1, err = networkingv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.networkingV1beta1, err = networkingv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.nodeV1alpha1, err = nodev1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.nodeV1beta1, err = nodev1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.policyV1beta1, err = policyv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.rbacV1, err = rbacv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.rbacV1beta1, err = rbacv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.schedulingV1beta1, err = schedulingv1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.schedulingV1, err = schedulingv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.storageV1beta1, err = storagev1beta1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.storageV1, err = storagev1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.NewForConfigOrDie(c) + cs.appsV1 = appsv1.NewForConfigOrDie(c) + cs.appsV1beta1 = appsv1beta1.NewForConfigOrDie(c) + cs.appsV1beta2 = appsv1beta2.NewForConfigOrDie(c) + cs.authenticationV1 = authenticationv1.NewForConfigOrDie(c) + cs.authorizationV1 = authorizationv1.NewForConfigOrDie(c) + cs.authorizationV1beta1 = authorizationv1beta1.NewForConfigOrDie(c) + cs.autoscalingV1 = autoscalingv1.NewForConfigOrDie(c) + cs.autoscalingV2beta1 = autoscalingv2beta1.NewForConfigOrDie(c) + cs.autoscalingV2beta2 = autoscalingv2beta2.NewForConfigOrDie(c) + cs.batchV1 = batchv1.NewForConfigOrDie(c) + cs.batchV1beta1 = batchv1beta1.NewForConfigOrDie(c) + cs.batchV2alpha1 = batchv2alpha1.NewForConfigOrDie(c) + cs.certificatesV1beta1 = certificatesv1beta1.NewForConfigOrDie(c) + cs.coordinationV1beta1 = coordinationv1beta1.NewForConfigOrDie(c) + cs.coordinationV1 = coordinationv1.NewForConfigOrDie(c) + cs.coreV1 = corev1.NewForConfigOrDie(c) + cs.extensionsV1beta1 = extensionsv1beta1.NewForConfigOrDie(c) + cs.networkingV1 = networkingv1.NewForConfigOrDie(c) + cs.networkingV1beta1 = networkingv1beta1.NewForConfigOrDie(c) + cs.nodeV1alpha1 = nodev1alpha1.NewForConfigOrDie(c) + cs.nodeV1beta1 = nodev1beta1.NewForConfigOrDie(c) + cs.policyV1beta1 = policyv1beta1.NewForConfigOrDie(c) + cs.rbacV1 = rbacv1.NewForConfigOrDie(c) + cs.rbacV1beta1 = rbacv1beta1.NewForConfigOrDie(c) + cs.schedulingV1beta1 = schedulingv1beta1.NewForConfigOrDie(c) + cs.schedulingV1 = schedulingv1.NewForConfigOrDie(c) + cs.storageV1beta1 = storagev1beta1.NewForConfigOrDie(c) + cs.storageV1 = storagev1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.New(c) + cs.appsV1 = appsv1.New(c) + cs.appsV1beta1 = appsv1beta1.New(c) + cs.appsV1beta2 = appsv1beta2.New(c) + cs.authenticationV1 = authenticationv1.New(c) + cs.authorizationV1 = authorizationv1.New(c) + cs.authorizationV1beta1 = authorizationv1beta1.New(c) + cs.autoscalingV1 = autoscalingv1.New(c) + cs.autoscalingV2beta1 = autoscalingv2beta1.New(c) + cs.autoscalingV2beta2 = autoscalingv2beta2.New(c) + cs.batchV1 = batchv1.New(c) + cs.batchV1beta1 = batchv1beta1.New(c) + cs.batchV2alpha1 = batchv2alpha1.New(c) + cs.certificatesV1beta1 = certificatesv1beta1.New(c) + cs.coordinationV1beta1 = coordinationv1beta1.New(c) + cs.coordinationV1 = coordinationv1.New(c) + cs.coreV1 = corev1.New(c) + cs.extensionsV1beta1 = extensionsv1beta1.New(c) + cs.networkingV1 = networkingv1.New(c) + cs.networkingV1beta1 = networkingv1beta1.New(c) + cs.nodeV1alpha1 = nodev1alpha1.New(c) + cs.nodeV1beta1 = nodev1beta1.New(c) + cs.policyV1beta1 = policyv1beta1.New(c) + cs.rbacV1 = rbacv1.New(c) + cs.rbacV1beta1 = rbacv1beta1.New(c) + cs.schedulingV1beta1 = schedulingv1beta1.New(c) + cs.schedulingV1 = schedulingv1.New(c) + cs.storageV1beta1 = storagev1beta1.New(c) + cs.storageV1 = storagev1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go new file mode 100644 index 0000000000..b272334ad0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/doc.go @@ -0,0 +1,20 @@ +/* +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 client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package kubernetes diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/import.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/import.go new file mode 100644 index 0000000000..c4f9a91bcf --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes/import.go @@ -0,0 +1,19 @@ +/* +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. +*/ + +// This file exists to enforce this clientset's vanity import path. + +package kubernetes // import "k8s.io/client-go/kubernetes" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD new file mode 100644 index 0000000000..8746085e1a --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/BUILD @@ -0,0 +1,78 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = [ + "client_config_test.go", + "loader_test.go", + "merged_client_builder_test.go", + "overrides_test.go", + "validation_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd/api/latest:go_default_library", + "//vendor/github.com/imdario/mergo:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/sigs.k8s.io/yaml:go_default_library", + ], +) + +go_library( + name = "go_default_library", + srcs = [ + "auth_loaders.go", + "client_config.go", + "config.go", + "doc.go", + "flag.go", + "helpers.go", + "loader.go", + "merged_client_builder.go", + "overrides.go", + "validation.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/client-go/tools/clientcmd", + importpath = "k8s.io/client-go/tools/clientcmd", + deps = [ + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", + "//staging/src/k8s.io/client-go/rest:go_default_library", + "//staging/src/k8s.io/client-go/tools/auth:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd/api/latest:go_default_library", + "//staging/src/k8s.io/client-go/util/homedir:go_default_library", + "//vendor/github.com/imdario/mergo:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/golang.org/x/crypto/ssh/terminal:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/client-go/tools/clientcmd/api:all-srcs", + ], + tags = ["automanaged"], +) diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go new file mode 100644 index 0000000000..1d3c11d8fc --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/auth_loaders.go @@ -0,0 +1,111 @@ +/* +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 clientcmd + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + + "golang.org/x/crypto/ssh/terminal" + + clientauth "k8s.io/client-go/tools/auth" +) + +// AuthLoaders are used to build clientauth.Info objects. +type AuthLoader interface { + // LoadAuth takes a path to a config file and can then do anything it needs in order to return a valid clientauth.Info + LoadAuth(path string) (*clientauth.Info, error) +} + +// default implementation of an AuthLoader +type defaultAuthLoader struct{} + +// LoadAuth for defaultAuthLoader simply delegates to clientauth.LoadFromFile +func (*defaultAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { + return clientauth.LoadFromFile(path) +} + +type PromptingAuthLoader struct { + reader io.Reader +} + +// LoadAuth parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. +func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { + // Prompt for user/pass and write a file if none exists. + if _, err := os.Stat(path); os.IsNotExist(err) { + authPtr, err := a.Prompt() + auth := *authPtr + if err != nil { + return nil, err + } + data, err := json.Marshal(auth) + if err != nil { + return &auth, err + } + err = ioutil.WriteFile(path, data, 0600) + return &auth, err + } + authPtr, err := clientauth.LoadFromFile(path) + if err != nil { + return nil, err + } + return authPtr, nil +} + +// Prompt pulls the user and password from a reader +func (a *PromptingAuthLoader) Prompt() (*clientauth.Info, error) { + var err error + auth := &clientauth.Info{} + auth.User, err = promptForString("Username", a.reader, true) + if err != nil { + return nil, err + } + auth.Password, err = promptForString("Password", nil, false) + if err != nil { + return nil, err + } + return auth, nil +} + +func promptForString(field string, r io.Reader, show bool) (result string, err error) { + fmt.Printf("Please enter %s: ", field) + if show { + _, err = fmt.Fscan(r, &result) + } else { + var data []byte + if terminal.IsTerminal(int(os.Stdin.Fd())) { + data, err = terminal.ReadPassword(int(os.Stdin.Fd())) + result = string(data) + } else { + return "", fmt.Errorf("error reading input for %s", field) + } + } + return result, err +} + +// NewPromptingAuthLoader is an AuthLoader that parses an AuthInfo object from a file path. It prompts user and creates file if it doesn't exist. +func NewPromptingAuthLoader(reader io.Reader) *PromptingAuthLoader { + return &PromptingAuthLoader{reader} +} + +// NewDefaultAuthLoader returns a default implementation of an AuthLoader that only reads from a config file +func NewDefaultAuthLoader() AuthLoader { + return &defaultAuthLoader{} +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go new file mode 100644 index 0000000000..a7b8c1c6e4 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go @@ -0,0 +1,569 @@ +/* +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 clientcmd + +import ( + "fmt" + "io" + "io/ioutil" + "net/url" + "os" + "strings" + + "github.com/imdario/mergo" + "k8s.io/klog" + + restclient "k8s.io/client-go/rest" + clientauth "k8s.io/client-go/tools/auth" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +var ( + // ClusterDefaults has the same behavior as the old EnvVar and DefaultCluster fields + // DEPRECATED will be replaced + ClusterDefaults = clientcmdapi.Cluster{Server: getDefaultServer()} + // DefaultClientConfig represents the legacy behavior of this package for defaulting + // DEPRECATED will be replace + DefaultClientConfig = DirectClientConfig{*clientcmdapi.NewConfig(), "", &ConfigOverrides{ + ClusterDefaults: ClusterDefaults, + }, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}} +) + +// getDefaultServer returns a default setting for DefaultClientConfig +// DEPRECATED +func getDefaultServer() string { + if server := os.Getenv("KUBERNETES_MASTER"); len(server) > 0 { + return server + } + return "http://localhost:8080" +} + +// ClientConfig is used to make it easy to get an api server client +type ClientConfig interface { + // RawConfig returns the merged result of all overrides + RawConfig() (clientcmdapi.Config, error) + // ClientConfig returns a complete client config + ClientConfig() (*restclient.Config, error) + // Namespace returns the namespace resulting from the merged + // result of all overrides and a boolean indicating if it was + // overridden + Namespace() (string, bool, error) + // ConfigAccess returns the rules for loading/persisting the config. + ConfigAccess() ConfigAccess +} + +type PersistAuthProviderConfigForUser func(user string) restclient.AuthProviderConfigPersister + +type promptedCredentials struct { + username string + password string +} + +// DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information +type DirectClientConfig struct { + config clientcmdapi.Config + contextName string + overrides *ConfigOverrides + fallbackReader io.Reader + configAccess ConfigAccess + // promptedCredentials store the credentials input by the user + promptedCredentials promptedCredentials +} + +// NewDefaultClientConfig creates a DirectClientConfig using the config.CurrentContext as the context name +func NewDefaultClientConfig(config clientcmdapi.Config, overrides *ConfigOverrides) ClientConfig { + return &DirectClientConfig{config, config.CurrentContext, overrides, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}} +} + +// NewNonInteractiveClientConfig creates a DirectClientConfig using the passed context name and does not have a fallback reader for auth information +func NewNonInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, configAccess ConfigAccess) ClientConfig { + return &DirectClientConfig{config, contextName, overrides, nil, configAccess, promptedCredentials{}} +} + +// NewInteractiveClientConfig creates a DirectClientConfig using the passed context name and a reader in case auth information is not provided via files or flags +func NewInteractiveClientConfig(config clientcmdapi.Config, contextName string, overrides *ConfigOverrides, fallbackReader io.Reader, configAccess ConfigAccess) ClientConfig { + return &DirectClientConfig{config, contextName, overrides, fallbackReader, configAccess, promptedCredentials{}} +} + +// NewClientConfigFromBytes takes your kubeconfig and gives you back a ClientConfig +func NewClientConfigFromBytes(configBytes []byte) (ClientConfig, error) { + config, err := Load(configBytes) + if err != nil { + return nil, err + } + + return &DirectClientConfig{*config, "", &ConfigOverrides{}, nil, nil, promptedCredentials{}}, nil +} + +// RESTConfigFromKubeConfig is a convenience method to give back a restconfig from your kubeconfig bytes. +// For programmatic access, this is what you want 80% of the time +func RESTConfigFromKubeConfig(configBytes []byte) (*restclient.Config, error) { + clientConfig, err := NewClientConfigFromBytes(configBytes) + if err != nil { + return nil, err + } + return clientConfig.ClientConfig() +} + +func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) { + return config.config, nil +} + +// ClientConfig implements ClientConfig +func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) { + // check that getAuthInfo, getContext, and getCluster do not return an error. + // Do this before checking if the current config is usable in the event that an + // AuthInfo, Context, or Cluster config with user-defined names are not found. + // This provides a user with the immediate cause for error if one is found + configAuthInfo, err := config.getAuthInfo() + if err != nil { + return nil, err + } + + _, err = config.getContext() + if err != nil { + return nil, err + } + + configClusterInfo, err := config.getCluster() + if err != nil { + return nil, err + } + + if err := config.ConfirmUsable(); err != nil { + return nil, err + } + + clientConfig := &restclient.Config{} + clientConfig.Host = configClusterInfo.Server + + if len(config.overrides.Timeout) > 0 { + timeout, err := ParseTimeout(config.overrides.Timeout) + if err != nil { + return nil, err + } + clientConfig.Timeout = timeout + } + + if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 { + u.RawQuery = "" + u.Fragment = "" + clientConfig.Host = u.String() + } + if len(configAuthInfo.Impersonate) > 0 { + clientConfig.Impersonate = restclient.ImpersonationConfig{ + UserName: configAuthInfo.Impersonate, + Groups: configAuthInfo.ImpersonateGroups, + Extra: configAuthInfo.ImpersonateUserExtra, + } + } + + // only try to read the auth information if we are secure + if restclient.IsConfigTransportTLS(*clientConfig) { + var err error + var persister restclient.AuthProviderConfigPersister + if config.configAccess != nil { + authInfoName, _ := config.getAuthInfoName() + persister = PersisterForUser(config.configAccess, authInfoName) + } + userAuthPartialConfig, err := config.getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader, persister) + if err != nil { + return nil, err + } + mergo.MergeWithOverwrite(clientConfig, userAuthPartialConfig) + + serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo) + if err != nil { + return nil, err + } + mergo.MergeWithOverwrite(clientConfig, serverAuthPartialConfig) + } + + return clientConfig, nil +} + +// clientauth.Info object contain both user identification and server identification. We want different precedence orders for +// both, so we have to split the objects and merge them separately +// we want this order of precedence for the server identification +// 1. configClusterInfo (the final result of command line flags and merged .kubeconfig files) +// 2. configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority) +// 3. load the ~/.kubernetes_auth file as a default +func getServerIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, configClusterInfo clientcmdapi.Cluster) (*restclient.Config, error) { + mergedConfig := &restclient.Config{} + + // configClusterInfo holds the information identify the server provided by .kubeconfig + configClientConfig := &restclient.Config{} + configClientConfig.CAFile = configClusterInfo.CertificateAuthority + configClientConfig.CAData = configClusterInfo.CertificateAuthorityData + configClientConfig.Insecure = configClusterInfo.InsecureSkipTLSVerify + mergo.MergeWithOverwrite(mergedConfig, configClientConfig) + + return mergedConfig, nil +} + +// clientauth.Info object contain both user identification and server identification. We want different precedence orders for +// both, so we have to split the objects and merge them separately +// we want this order of precedence for user identification +// 1. configAuthInfo minus auth-path (the final result of command line flags and merged .kubeconfig files) +// 2. configAuthInfo.auth-path (this file can contain information that conflicts with #1, and we want #1 to win the priority) +// 3. if there is not enough information to identify the user, load try the ~/.kubernetes_auth file +// 4. if there is not enough information to identify the user, prompt if possible +func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo, fallbackReader io.Reader, persistAuthConfig restclient.AuthProviderConfigPersister) (*restclient.Config, error) { + mergedConfig := &restclient.Config{} + + // blindly overwrite existing values based on precedence + if len(configAuthInfo.Token) > 0 { + mergedConfig.BearerToken = configAuthInfo.Token + } else if len(configAuthInfo.TokenFile) > 0 { + tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile) + if err != nil { + return nil, err + } + mergedConfig.BearerToken = string(tokenBytes) + mergedConfig.BearerTokenFile = configAuthInfo.TokenFile + } + if len(configAuthInfo.Impersonate) > 0 { + mergedConfig.Impersonate = restclient.ImpersonationConfig{ + UserName: configAuthInfo.Impersonate, + Groups: configAuthInfo.ImpersonateGroups, + Extra: configAuthInfo.ImpersonateUserExtra, + } + } + if len(configAuthInfo.ClientCertificate) > 0 || len(configAuthInfo.ClientCertificateData) > 0 { + mergedConfig.CertFile = configAuthInfo.ClientCertificate + mergedConfig.CertData = configAuthInfo.ClientCertificateData + mergedConfig.KeyFile = configAuthInfo.ClientKey + mergedConfig.KeyData = configAuthInfo.ClientKeyData + } + if len(configAuthInfo.Username) > 0 || len(configAuthInfo.Password) > 0 { + mergedConfig.Username = configAuthInfo.Username + mergedConfig.Password = configAuthInfo.Password + } + if configAuthInfo.AuthProvider != nil { + mergedConfig.AuthProvider = configAuthInfo.AuthProvider + mergedConfig.AuthConfigPersister = persistAuthConfig + } + if configAuthInfo.Exec != nil { + mergedConfig.ExecProvider = configAuthInfo.Exec + } + + // if there still isn't enough information to authenticate the user, try prompting + if !canIdentifyUser(*mergedConfig) && (fallbackReader != nil) { + if len(config.promptedCredentials.username) > 0 && len(config.promptedCredentials.password) > 0 { + mergedConfig.Username = config.promptedCredentials.username + mergedConfig.Password = config.promptedCredentials.password + return mergedConfig, nil + } + prompter := NewPromptingAuthLoader(fallbackReader) + promptedAuthInfo, err := prompter.Prompt() + if err != nil { + return nil, err + } + promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo) + previouslyMergedConfig := mergedConfig + mergedConfig = &restclient.Config{} + mergo.MergeWithOverwrite(mergedConfig, promptedConfig) + mergo.MergeWithOverwrite(mergedConfig, previouslyMergedConfig) + config.promptedCredentials.username = mergedConfig.Username + config.promptedCredentials.password = mergedConfig.Password + } + + return mergedConfig, nil +} + +// makeUserIdentificationFieldsConfig returns a client.Config capable of being merged using mergo for only user identification information +func makeUserIdentificationConfig(info clientauth.Info) *restclient.Config { + config := &restclient.Config{} + config.Username = info.User + config.Password = info.Password + config.CertFile = info.CertFile + config.KeyFile = info.KeyFile + config.BearerToken = info.BearerToken + return config +} + +// makeUserIdentificationFieldsConfig returns a client.Config capable of being merged using mergo for only server identification information +func makeServerIdentificationConfig(info clientauth.Info) restclient.Config { + config := restclient.Config{} + config.CAFile = info.CAFile + if info.Insecure != nil { + config.Insecure = *info.Insecure + } + return config +} + +func canIdentifyUser(config restclient.Config) bool { + return len(config.Username) > 0 || + (len(config.CertFile) > 0 || len(config.CertData) > 0) || + len(config.BearerToken) > 0 || + config.AuthProvider != nil || + config.ExecProvider != nil +} + +// Namespace implements ClientConfig +func (config *DirectClientConfig) Namespace() (string, bool, error) { + if config.overrides != nil && config.overrides.Context.Namespace != "" { + // In the event we have an empty config but we do have a namespace override, we should return + // the namespace override instead of having config.ConfirmUsable() return an error. This allows + // things like in-cluster clients to execute `kubectl get pods --namespace=foo` and have the + // --namespace flag honored instead of being ignored. + return config.overrides.Context.Namespace, true, nil + } + + if err := config.ConfirmUsable(); err != nil { + return "", false, err + } + + configContext, err := config.getContext() + if err != nil { + return "", false, err + } + + if len(configContext.Namespace) == 0 { + return "default", false, nil + } + + return configContext.Namespace, false, nil +} + +// ConfigAccess implements ClientConfig +func (config *DirectClientConfig) ConfigAccess() ConfigAccess { + return config.configAccess +} + +// ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config, +// but no errors in the sections requested or referenced. It does not return early so that it can find as many errors as possible. +func (config *DirectClientConfig) ConfirmUsable() error { + validationErrors := make([]error, 0) + + var contextName string + if len(config.contextName) != 0 { + contextName = config.contextName + } else { + contextName = config.config.CurrentContext + } + + if len(contextName) > 0 { + _, exists := config.config.Contexts[contextName] + if !exists { + validationErrors = append(validationErrors, &errContextNotFound{contextName}) + } + } + + authInfoName, _ := config.getAuthInfoName() + authInfo, _ := config.getAuthInfo() + validationErrors = append(validationErrors, validateAuthInfo(authInfoName, authInfo)...) + clusterName, _ := config.getClusterName() + cluster, _ := config.getCluster() + validationErrors = append(validationErrors, validateClusterInfo(clusterName, cluster)...) + // when direct client config is specified, and our only error is that no server is defined, we should + // return a standard "no config" error + if len(validationErrors) == 1 && validationErrors[0] == ErrEmptyCluster { + return newErrConfigurationInvalid([]error{ErrEmptyConfig}) + } + return newErrConfigurationInvalid(validationErrors) +} + +// getContextName returns the default, or user-set context name, and a boolean that indicates +// whether the default context name has been overwritten by a user-set flag, or left as its default value +func (config *DirectClientConfig) getContextName() (string, bool) { + if len(config.overrides.CurrentContext) != 0 { + return config.overrides.CurrentContext, true + } + if len(config.contextName) != 0 { + return config.contextName, false + } + + return config.config.CurrentContext, false +} + +// getAuthInfoName returns a string containing the current authinfo name for the current context, +// and a boolean indicating whether the default authInfo name is overwritten by a user-set flag, or +// left as its default value +func (config *DirectClientConfig) getAuthInfoName() (string, bool) { + if len(config.overrides.Context.AuthInfo) != 0 { + return config.overrides.Context.AuthInfo, true + } + context, _ := config.getContext() + return context.AuthInfo, false +} + +// getClusterName returns a string containing the default, or user-set cluster name, and a boolean +// indicating whether the default clusterName has been overwritten by a user-set flag, or left as +// its default value +func (config *DirectClientConfig) getClusterName() (string, bool) { + if len(config.overrides.Context.Cluster) != 0 { + return config.overrides.Context.Cluster, true + } + context, _ := config.getContext() + return context.Cluster, false +} + +// getContext returns the clientcmdapi.Context, or an error if a required context is not found. +func (config *DirectClientConfig) getContext() (clientcmdapi.Context, error) { + contexts := config.config.Contexts + contextName, required := config.getContextName() + + mergedContext := clientcmdapi.NewContext() + if configContext, exists := contexts[contextName]; exists { + mergo.MergeWithOverwrite(mergedContext, configContext) + } else if required { + return clientcmdapi.Context{}, fmt.Errorf("context %q does not exist", contextName) + } + mergo.MergeWithOverwrite(mergedContext, config.overrides.Context) + + return *mergedContext, nil +} + +// getAuthInfo returns the clientcmdapi.AuthInfo, or an error if a required auth info is not found. +func (config *DirectClientConfig) getAuthInfo() (clientcmdapi.AuthInfo, error) { + authInfos := config.config.AuthInfos + authInfoName, required := config.getAuthInfoName() + + mergedAuthInfo := clientcmdapi.NewAuthInfo() + if configAuthInfo, exists := authInfos[authInfoName]; exists { + mergo.MergeWithOverwrite(mergedAuthInfo, configAuthInfo) + } else if required { + return clientcmdapi.AuthInfo{}, fmt.Errorf("auth info %q does not exist", authInfoName) + } + mergo.MergeWithOverwrite(mergedAuthInfo, config.overrides.AuthInfo) + + return *mergedAuthInfo, nil +} + +// getCluster returns the clientcmdapi.Cluster, or an error if a required cluster is not found. +func (config *DirectClientConfig) getCluster() (clientcmdapi.Cluster, error) { + clusterInfos := config.config.Clusters + clusterInfoName, required := config.getClusterName() + + mergedClusterInfo := clientcmdapi.NewCluster() + mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterDefaults) + if configClusterInfo, exists := clusterInfos[clusterInfoName]; exists { + mergo.MergeWithOverwrite(mergedClusterInfo, configClusterInfo) + } else if required { + return clientcmdapi.Cluster{}, fmt.Errorf("cluster %q does not exist", clusterInfoName) + } + mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterInfo) + // An override of --insecure-skip-tls-verify=true and no accompanying CA/CA data should clear already-set CA/CA data + // otherwise, a kubeconfig containing a CA reference would return an error that "CA and insecure-skip-tls-verify couldn't both be set" + caLen := len(config.overrides.ClusterInfo.CertificateAuthority) + caDataLen := len(config.overrides.ClusterInfo.CertificateAuthorityData) + if config.overrides.ClusterInfo.InsecureSkipTLSVerify && caLen == 0 && caDataLen == 0 { + mergedClusterInfo.CertificateAuthority = "" + mergedClusterInfo.CertificateAuthorityData = nil + } + + return *mergedClusterInfo, nil +} + +// inClusterClientConfig makes a config that will work from within a kubernetes cluster container environment. +// Can take options overrides for flags explicitly provided to the command inside the cluster container. +type inClusterClientConfig struct { + overrides *ConfigOverrides + inClusterConfigProvider func() (*restclient.Config, error) +} + +var _ ClientConfig = &inClusterClientConfig{} + +func (config *inClusterClientConfig) RawConfig() (clientcmdapi.Config, error) { + return clientcmdapi.Config{}, fmt.Errorf("inCluster environment config doesn't support multiple clusters") +} + +func (config *inClusterClientConfig) ClientConfig() (*restclient.Config, error) { + if config.inClusterConfigProvider == nil { + config.inClusterConfigProvider = restclient.InClusterConfig + } + + icc, err := config.inClusterConfigProvider() + if err != nil { + return nil, err + } + + // in-cluster configs only takes a host, token, or CA file + // if any of them were individually provided, overwrite anything else + if config.overrides != nil { + if server := config.overrides.ClusterInfo.Server; len(server) > 0 { + icc.Host = server + } + if token := config.overrides.AuthInfo.Token; len(token) > 0 { + icc.BearerToken = token + } + if certificateAuthorityFile := config.overrides.ClusterInfo.CertificateAuthority; len(certificateAuthorityFile) > 0 { + icc.TLSClientConfig.CAFile = certificateAuthorityFile + } + } + + return icc, err +} + +func (config *inClusterClientConfig) Namespace() (string, bool, error) { + // This way assumes you've set the POD_NAMESPACE environment variable using the downward API. + // This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up + if ns := os.Getenv("POD_NAMESPACE"); ns != "" { + return ns, false, nil + } + + // Fall back to the namespace associated with the service account token, if available + if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil { + if ns := strings.TrimSpace(string(data)); len(ns) > 0 { + return ns, false, nil + } + } + + return "default", false, nil +} + +func (config *inClusterClientConfig) ConfigAccess() ConfigAccess { + return NewDefaultClientConfigLoadingRules() +} + +// Possible returns true if loading an inside-kubernetes-cluster is possible. +func (config *inClusterClientConfig) Possible() bool { + fi, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/token") + return os.Getenv("KUBERNETES_SERVICE_HOST") != "" && + os.Getenv("KUBERNETES_SERVICE_PORT") != "" && + err == nil && !fi.IsDir() +} + +// BuildConfigFromFlags is a helper function that builds configs from a master +// url or a kubeconfig filepath. These are passed in as command line flags for cluster +// components. Warnings should reflect this usage. If neither masterUrl or kubeconfigPath +// are passed in we fallback to inClusterConfig. If inClusterConfig fails, we fallback +// to the default config. +func BuildConfigFromFlags(masterUrl, kubeconfigPath string) (*restclient.Config, error) { + if kubeconfigPath == "" && masterUrl == "" { + klog.Warningf("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.") + kubeconfig, err := restclient.InClusterConfig() + if err == nil { + return kubeconfig, nil + } + klog.Warning("error creating inClusterConfig, falling back to default config: ", err) + } + return NewNonInteractiveDeferredLoadingClientConfig( + &ClientConfigLoadingRules{ExplicitPath: kubeconfigPath}, + &ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterUrl}}).ClientConfig() +} + +// BuildConfigFromKubeconfigGetter is a helper function that builds configs from a master +// url and a kubeconfigGetter. +func BuildConfigFromKubeconfigGetter(masterUrl string, kubeconfigGetter KubeconfigGetter) (*restclient.Config, error) { + // TODO: We do not need a DeferredLoader here. Refactor code and see if we can use DirectClientConfig here. + cc := NewNonInteractiveDeferredLoadingClientConfig( + &ClientConfigGetter{kubeconfigGetter: kubeconfigGetter}, + &ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterUrl}}) + return cc.ClientConfig() +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go new file mode 100644 index 0000000000..b8cc396882 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/config.go @@ -0,0 +1,490 @@ +/* +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 clientcmd + +import ( + "errors" + "os" + "path" + "path/filepath" + "reflect" + "sort" + + "k8s.io/klog" + + restclient "k8s.io/client-go/rest" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +// ConfigAccess is used by subcommands and methods in this package to load and modify the appropriate config files +type ConfigAccess interface { + // GetLoadingPrecedence returns the slice of files that should be used for loading and inspecting the config + GetLoadingPrecedence() []string + // GetStartingConfig returns the config that subcommands should being operating against. It may or may not be merged depending on loading rules + GetStartingConfig() (*clientcmdapi.Config, error) + // GetDefaultFilename returns the name of the file you should write into (create if necessary), if you're trying to create a new stanza as opposed to updating an existing one. + GetDefaultFilename() string + // IsExplicitFile indicates whether or not this command is interested in exactly one file. This implementation only ever does that via a flag, but implementations that handle local, global, and flags may have more + IsExplicitFile() bool + // GetExplicitFile returns the particular file this command is operating against. This implementation only ever has one, but implementations that handle local, global, and flags may have more + GetExplicitFile() string +} + +type PathOptions struct { + // GlobalFile is the full path to the file to load as the global (final) option + GlobalFile string + // EnvVar is the env var name that points to the list of kubeconfig files to load + EnvVar string + // ExplicitFileFlag is the name of the flag to use for prompting for the kubeconfig file + ExplicitFileFlag string + + // GlobalFileSubpath is an optional value used for displaying help + GlobalFileSubpath string + + LoadingRules *ClientConfigLoadingRules +} + +func (o *PathOptions) GetEnvVarFiles() []string { + if len(o.EnvVar) == 0 { + return []string{} + } + + envVarValue := os.Getenv(o.EnvVar) + if len(envVarValue) == 0 { + return []string{} + } + + fileList := filepath.SplitList(envVarValue) + // prevent the same path load multiple times + return deduplicate(fileList) +} + +func (o *PathOptions) GetLoadingPrecedence() []string { + if envVarFiles := o.GetEnvVarFiles(); len(envVarFiles) > 0 { + return envVarFiles + } + + return []string{o.GlobalFile} +} + +func (o *PathOptions) GetStartingConfig() (*clientcmdapi.Config, error) { + // don't mutate the original + loadingRules := *o.LoadingRules + loadingRules.Precedence = o.GetLoadingPrecedence() + + clientConfig := NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, &ConfigOverrides{}) + rawConfig, err := clientConfig.RawConfig() + if os.IsNotExist(err) { + return clientcmdapi.NewConfig(), nil + } + if err != nil { + return nil, err + } + + return &rawConfig, nil +} + +func (o *PathOptions) GetDefaultFilename() string { + if o.IsExplicitFile() { + return o.GetExplicitFile() + } + + if envVarFiles := o.GetEnvVarFiles(); len(envVarFiles) > 0 { + if len(envVarFiles) == 1 { + return envVarFiles[0] + } + + // if any of the envvar files already exists, return it + for _, envVarFile := range envVarFiles { + if _, err := os.Stat(envVarFile); err == nil { + return envVarFile + } + } + + // otherwise, return the last one in the list + return envVarFiles[len(envVarFiles)-1] + } + + return o.GlobalFile +} + +func (o *PathOptions) IsExplicitFile() bool { + if len(o.LoadingRules.ExplicitPath) > 0 { + return true + } + + return false +} + +func (o *PathOptions) GetExplicitFile() string { + return o.LoadingRules.ExplicitPath +} + +func NewDefaultPathOptions() *PathOptions { + ret := &PathOptions{ + GlobalFile: RecommendedHomeFile, + EnvVar: RecommendedConfigPathEnvVar, + ExplicitFileFlag: RecommendedConfigPathFlag, + + GlobalFileSubpath: path.Join(RecommendedHomeDir, RecommendedFileName), + + LoadingRules: NewDefaultClientConfigLoadingRules(), + } + ret.LoadingRules.DoNotResolvePaths = true + + return ret +} + +// ModifyConfig takes a Config object, iterates through Clusters, AuthInfos, and Contexts, uses the LocationOfOrigin if specified or +// uses the default destination file to write the results into. This results in multiple file reads, but it's very easy to follow. +// Preferences and CurrentContext should always be set in the default destination file. Since we can't distinguish between empty and missing values +// (no nil strings), we're forced have separate handling for them. In the kubeconfig cases, newConfig should have at most one difference, +// that means that this code will only write into a single file. If you want to relativizePaths, you must provide a fully qualified path in any +// modified element. +func ModifyConfig(configAccess ConfigAccess, newConfig clientcmdapi.Config, relativizePaths bool) error { + possibleSources := configAccess.GetLoadingPrecedence() + // sort the possible kubeconfig files so we always "lock" in the same order + // to avoid deadlock (note: this can fail w/ symlinks, but... come on). + sort.Strings(possibleSources) + for _, filename := range possibleSources { + if err := lockFile(filename); err != nil { + return err + } + defer unlockFile(filename) + } + + startingConfig, err := configAccess.GetStartingConfig() + if err != nil { + return err + } + + // We need to find all differences, locate their original files, read a partial config to modify only that stanza and write out the file. + // Special case the test for current context and preferences since those always write to the default file. + if reflect.DeepEqual(*startingConfig, newConfig) { + // nothing to do + return nil + } + + if startingConfig.CurrentContext != newConfig.CurrentContext { + if err := writeCurrentContext(configAccess, newConfig.CurrentContext); err != nil { + return err + } + } + + if !reflect.DeepEqual(startingConfig.Preferences, newConfig.Preferences) { + if err := writePreferences(configAccess, newConfig.Preferences); err != nil { + return err + } + } + + // Search every cluster, authInfo, and context. First from new to old for differences, then from old to new for deletions + for key, cluster := range newConfig.Clusters { + startingCluster, exists := startingConfig.Clusters[key] + if !reflect.DeepEqual(cluster, startingCluster) || !exists { + destinationFile := cluster.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + configToWrite, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + t := *cluster + + configToWrite.Clusters[key] = &t + configToWrite.Clusters[key].LocationOfOrigin = destinationFile + if relativizePaths { + if err := RelativizeClusterLocalPaths(configToWrite.Clusters[key]); err != nil { + return err + } + } + + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + } + + // seenConfigs stores a map of config source filenames to computed config objects + seenConfigs := map[string]*clientcmdapi.Config{} + + for key, context := range newConfig.Contexts { + startingContext, exists := startingConfig.Contexts[key] + if !reflect.DeepEqual(context, startingContext) || !exists { + destinationFile := context.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + // we only obtain a fresh config object from its source file + // if we have not seen it already - this prevents us from + // reading and writing to the same number of files repeatedly + // when multiple / all contexts share the same destination file. + configToWrite, seen := seenConfigs[destinationFile] + if !seen { + var err error + configToWrite, err = getConfigFromFile(destinationFile) + if err != nil { + return err + } + seenConfigs[destinationFile] = configToWrite + } + + configToWrite.Contexts[key] = context + } + } + + // actually persist config object changes + for destinationFile, configToWrite := range seenConfigs { + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + + for key, authInfo := range newConfig.AuthInfos { + startingAuthInfo, exists := startingConfig.AuthInfos[key] + if !reflect.DeepEqual(authInfo, startingAuthInfo) || !exists { + destinationFile := authInfo.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + configToWrite, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + t := *authInfo + configToWrite.AuthInfos[key] = &t + configToWrite.AuthInfos[key].LocationOfOrigin = destinationFile + if relativizePaths { + if err := RelativizeAuthInfoLocalPaths(configToWrite.AuthInfos[key]); err != nil { + return err + } + } + + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + } + + for key, cluster := range startingConfig.Clusters { + if _, exists := newConfig.Clusters[key]; !exists { + destinationFile := cluster.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + configToWrite, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + delete(configToWrite.Clusters, key) + + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + } + + for key, context := range startingConfig.Contexts { + if _, exists := newConfig.Contexts[key]; !exists { + destinationFile := context.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + configToWrite, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + delete(configToWrite.Contexts, key) + + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + } + + for key, authInfo := range startingConfig.AuthInfos { + if _, exists := newConfig.AuthInfos[key]; !exists { + destinationFile := authInfo.LocationOfOrigin + if len(destinationFile) == 0 { + destinationFile = configAccess.GetDefaultFilename() + } + + configToWrite, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + delete(configToWrite.AuthInfos, key) + + if err := WriteToFile(*configToWrite, destinationFile); err != nil { + return err + } + } + } + + return nil +} + +func PersisterForUser(configAccess ConfigAccess, user string) restclient.AuthProviderConfigPersister { + return &persister{configAccess, user} +} + +type persister struct { + configAccess ConfigAccess + user string +} + +func (p *persister) Persist(config map[string]string) error { + newConfig, err := p.configAccess.GetStartingConfig() + if err != nil { + return err + } + authInfo, ok := newConfig.AuthInfos[p.user] + if ok && authInfo.AuthProvider != nil { + authInfo.AuthProvider.Config = config + ModifyConfig(p.configAccess, *newConfig, false) + } + return nil +} + +// writeCurrentContext takes three possible paths. +// If newCurrentContext is the same as the startingConfig's current context, then we exit. +// If newCurrentContext has a value, then that value is written into the default destination file. +// If newCurrentContext is empty, then we find the config file that is setting the CurrentContext and clear the value from that file +func writeCurrentContext(configAccess ConfigAccess, newCurrentContext string) error { + if startingConfig, err := configAccess.GetStartingConfig(); err != nil { + return err + } else if startingConfig.CurrentContext == newCurrentContext { + return nil + } + + if configAccess.IsExplicitFile() { + file := configAccess.GetExplicitFile() + currConfig, err := getConfigFromFile(file) + if err != nil { + return err + } + currConfig.CurrentContext = newCurrentContext + if err := WriteToFile(*currConfig, file); err != nil { + return err + } + + return nil + } + + if len(newCurrentContext) > 0 { + destinationFile := configAccess.GetDefaultFilename() + config, err := getConfigFromFile(destinationFile) + if err != nil { + return err + } + config.CurrentContext = newCurrentContext + + if err := WriteToFile(*config, destinationFile); err != nil { + return err + } + + return nil + } + + // we're supposed to be clearing the current context. We need to find the first spot in the chain that is setting it and clear it + for _, file := range configAccess.GetLoadingPrecedence() { + if _, err := os.Stat(file); err == nil { + currConfig, err := getConfigFromFile(file) + if err != nil { + return err + } + + if len(currConfig.CurrentContext) > 0 { + currConfig.CurrentContext = newCurrentContext + if err := WriteToFile(*currConfig, file); err != nil { + return err + } + + return nil + } + } + } + + return errors.New("no config found to write context") +} + +func writePreferences(configAccess ConfigAccess, newPrefs clientcmdapi.Preferences) error { + if startingConfig, err := configAccess.GetStartingConfig(); err != nil { + return err + } else if reflect.DeepEqual(startingConfig.Preferences, newPrefs) { + return nil + } + + if configAccess.IsExplicitFile() { + file := configAccess.GetExplicitFile() + currConfig, err := getConfigFromFile(file) + if err != nil { + return err + } + currConfig.Preferences = newPrefs + if err := WriteToFile(*currConfig, file); err != nil { + return err + } + + return nil + } + + for _, file := range configAccess.GetLoadingPrecedence() { + currConfig, err := getConfigFromFile(file) + if err != nil { + return err + } + + if !reflect.DeepEqual(currConfig.Preferences, newPrefs) { + currConfig.Preferences = newPrefs + if err := WriteToFile(*currConfig, file); err != nil { + return err + } + + return nil + } + } + + return errors.New("no config found to write preferences") +} + +// getConfigFromFile tries to read a kubeconfig file and if it can't, returns an error. One exception, missing files result in empty configs, not an error. +func getConfigFromFile(filename string) (*clientcmdapi.Config, error) { + config, err := LoadFromFile(filename) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + if config == nil { + config = clientcmdapi.NewConfig() + } + return config, nil +} + +// GetConfigFromFileOrDie tries to read a kubeconfig file and if it can't, it calls exit. One exception, missing files result in empty configs, not an exit +func GetConfigFromFileOrDie(filename string) *clientcmdapi.Config { + config, err := getConfigFromFile(filename) + if err != nil { + klog.FatalDepth(1, err) + } + + return config +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/doc.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/doc.go new file mode 100644 index 0000000000..424311ee12 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/doc.go @@ -0,0 +1,37 @@ +/* +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 clientcmd provides one stop shopping for building a working client from a fixed config, +from a .kubeconfig file, from command line flags, or from any merged combination. + +Sample usage from merged .kubeconfig files (local directory, home directory) + + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + // if you want to change the loading rules (which files in which order), you can do so here + + configOverrides := &clientcmd.ConfigOverrides{} + // if you want to change override values or bind them to flags, there are methods to help you + + kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides) + config, err := kubeConfig.ClientConfig() + if err != nil { + // Do something + } + client, err := metav1.New(config) + // ... +*/ +package clientcmd // import "k8s.io/client-go/tools/clientcmd" diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/flag.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/flag.go new file mode 100644 index 0000000000..8d60d201cd --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/flag.go @@ -0,0 +1,49 @@ +/* +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 clientcmd + +// transformingStringValue implements pflag.Value to store string values, +// allowing transforming them while being set +type transformingStringValue struct { + target *string + transformer func(string) (string, error) +} + +func newTransformingStringValue(val string, target *string, transformer func(string) (string, error)) *transformingStringValue { + *target = val + return &transformingStringValue{ + target: target, + transformer: transformer, + } +} + +func (t *transformingStringValue) Set(val string) error { + val, err := t.transformer(val) + if err != nil { + return err + } + *t.target = val + return nil +} + +func (t *transformingStringValue) Type() string { + return "string" +} + +func (t *transformingStringValue) String() string { + return string(*t.target) +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/helpers.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/helpers.go new file mode 100644 index 0000000000..b609d1a766 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/helpers.go @@ -0,0 +1,35 @@ +/* +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 clientcmd + +import ( + "fmt" + "strconv" + "time" +) + +// ParseTimeout returns a parsed duration from a string +// A duration string value must be a positive integer, optionally followed by a corresponding time unit (s|m|h). +func ParseTimeout(duration string) (time.Duration, error) { + if i, err := strconv.ParseInt(duration, 10, 64); err == nil && i >= 0 { + return (time.Duration(i) * time.Second), nil + } + if requestTimeout, err := time.ParseDuration(duration); err == nil { + return requestTimeout, nil + } + return 0, fmt.Errorf("Invalid timeout value. Timeout must be a single integer in seconds, or an integer followed by a corresponding time unit (e.g. 1s | 2m | 3h)") +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go new file mode 100644 index 0000000000..7e928a9185 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/loader.go @@ -0,0 +1,633 @@ +/* +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 clientcmd + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path" + "path/filepath" + "reflect" + goruntime "runtime" + "strings" + + "github.com/imdario/mergo" + "k8s.io/klog" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + restclient "k8s.io/client-go/rest" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest" + "k8s.io/client-go/util/homedir" +) + +const ( + RecommendedConfigPathFlag = "kubeconfig" + RecommendedConfigPathEnvVar = "KUBECONFIG" + RecommendedHomeDir = ".kube" + RecommendedFileName = "config" + RecommendedSchemaName = "schema" +) + +var ( + RecommendedConfigDir = path.Join(homedir.HomeDir(), RecommendedHomeDir) + RecommendedHomeFile = path.Join(RecommendedConfigDir, RecommendedFileName) + RecommendedSchemaFile = path.Join(RecommendedConfigDir, RecommendedSchemaName) +) + +// currentMigrationRules returns a map that holds the history of recommended home directories used in previous versions. +// Any future changes to RecommendedHomeFile and related are expected to add a migration rule here, in order to make +// sure existing config files are migrated to their new locations properly. +func currentMigrationRules() map[string]string { + oldRecommendedHomeFile := path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig") + oldRecommendedWindowsHomeFile := path.Join(os.Getenv("HOME"), RecommendedHomeDir, RecommendedFileName) + + migrationRules := map[string]string{} + migrationRules[RecommendedHomeFile] = oldRecommendedHomeFile + if goruntime.GOOS == "windows" { + migrationRules[RecommendedHomeFile] = oldRecommendedWindowsHomeFile + } + return migrationRules +} + +type ClientConfigLoader interface { + ConfigAccess + // IsDefaultConfig returns true if the returned config matches the defaults. + IsDefaultConfig(*restclient.Config) bool + // Load returns the latest config + Load() (*clientcmdapi.Config, error) +} + +type KubeconfigGetter func() (*clientcmdapi.Config, error) + +type ClientConfigGetter struct { + kubeconfigGetter KubeconfigGetter +} + +// ClientConfigGetter implements the ClientConfigLoader interface. +var _ ClientConfigLoader = &ClientConfigGetter{} + +func (g *ClientConfigGetter) Load() (*clientcmdapi.Config, error) { + return g.kubeconfigGetter() +} + +func (g *ClientConfigGetter) GetLoadingPrecedence() []string { + return nil +} +func (g *ClientConfigGetter) GetStartingConfig() (*clientcmdapi.Config, error) { + return g.kubeconfigGetter() +} +func (g *ClientConfigGetter) GetDefaultFilename() string { + return "" +} +func (g *ClientConfigGetter) IsExplicitFile() bool { + return false +} +func (g *ClientConfigGetter) GetExplicitFile() string { + return "" +} +func (g *ClientConfigGetter) IsDefaultConfig(config *restclient.Config) bool { + return false +} + +// ClientConfigLoadingRules is an ExplicitPath and string slice of specific locations that are used for merging together a Config +// Callers can put the chain together however they want, but we'd recommend: +// EnvVarPathFiles if set (a list of files if set) OR the HomeDirectoryPath +// ExplicitPath is special, because if a user specifically requests a certain file be used and error is reported if this file is not present +type ClientConfigLoadingRules struct { + ExplicitPath string + Precedence []string + + // MigrationRules is a map of destination files to source files. If a destination file is not present, then the source file is checked. + // If the source file is present, then it is copied to the destination file BEFORE any further loading happens. + MigrationRules map[string]string + + // DoNotResolvePaths indicates whether or not to resolve paths with respect to the originating files. This is phrased as a negative so + // that a default object that doesn't set this will usually get the behavior it wants. + DoNotResolvePaths bool + + // DefaultClientConfig is an optional field indicating what rules to use to calculate a default configuration. + // This should match the overrides passed in to ClientConfig loader. + DefaultClientConfig ClientConfig +} + +// ClientConfigLoadingRules implements the ClientConfigLoader interface. +var _ ClientConfigLoader = &ClientConfigLoadingRules{} + +// NewDefaultClientConfigLoadingRules returns a ClientConfigLoadingRules object with default fields filled in. You are not required to +// use this constructor +func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules { + chain := []string{} + + envVarFiles := os.Getenv(RecommendedConfigPathEnvVar) + if len(envVarFiles) != 0 { + fileList := filepath.SplitList(envVarFiles) + // prevent the same path load multiple times + chain = append(chain, deduplicate(fileList)...) + + } else { + chain = append(chain, RecommendedHomeFile) + } + + return &ClientConfigLoadingRules{ + Precedence: chain, + MigrationRules: currentMigrationRules(), + } +} + +// Load starts by running the MigrationRules and then +// takes the loading rules and returns a Config object based on following rules. +// if the ExplicitPath, return the unmerged explicit file +// Otherwise, return a merged config based on the Precedence slice +// A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored. +// Read errors or files with non-deserializable content produce errors. +// The first file to set a particular map key wins and map key's value is never changed. +// BUT, if you set a struct value that is NOT contained inside of map, the value WILL be changed. +// This results in some odd looking logic to merge in one direction, merge in the other, and then merge the two. +// It also means that if two files specify a "red-user", only values from the first file's red-user are used. Even +// non-conflicting entries from the second file's "red-user" are discarded. +// Relative paths inside of the .kubeconfig files are resolved against the .kubeconfig file's parent folder +// and only absolute file paths are returned. +func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) { + if err := rules.Migrate(); err != nil { + return nil, err + } + + errlist := []error{} + + kubeConfigFiles := []string{} + + // Make sure a file we were explicitly told to use exists + if len(rules.ExplicitPath) > 0 { + if _, err := os.Stat(rules.ExplicitPath); os.IsNotExist(err) { + return nil, err + } + kubeConfigFiles = append(kubeConfigFiles, rules.ExplicitPath) + + } else { + kubeConfigFiles = append(kubeConfigFiles, rules.Precedence...) + } + + kubeconfigs := []*clientcmdapi.Config{} + // read and cache the config files so that we only look at them once + for _, filename := range kubeConfigFiles { + if len(filename) == 0 { + // no work to do + continue + } + + config, err := LoadFromFile(filename) + if os.IsNotExist(err) { + // skip missing files + continue + } + if err != nil { + errlist = append(errlist, fmt.Errorf("Error loading config file \"%s\": %v", filename, err)) + continue + } + + kubeconfigs = append(kubeconfigs, config) + } + + // first merge all of our maps + mapConfig := clientcmdapi.NewConfig() + + for _, kubeconfig := range kubeconfigs { + mergo.MergeWithOverwrite(mapConfig, kubeconfig) + } + + // merge all of the struct values in the reverse order so that priority is given correctly + // errors are not added to the list the second time + nonMapConfig := clientcmdapi.NewConfig() + for i := len(kubeconfigs) - 1; i >= 0; i-- { + kubeconfig := kubeconfigs[i] + mergo.MergeWithOverwrite(nonMapConfig, kubeconfig) + } + + // since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and + // get the values we expect. + config := clientcmdapi.NewConfig() + mergo.MergeWithOverwrite(config, mapConfig) + mergo.MergeWithOverwrite(config, nonMapConfig) + + if rules.ResolvePaths() { + if err := ResolveLocalPaths(config); err != nil { + errlist = append(errlist, err) + } + } + return config, utilerrors.NewAggregate(errlist) +} + +// Migrate uses the MigrationRules map. If a destination file is not present, then the source file is checked. +// If the source file is present, then it is copied to the destination file BEFORE any further loading happens. +func (rules *ClientConfigLoadingRules) Migrate() error { + if rules.MigrationRules == nil { + return nil + } + + for destination, source := range rules.MigrationRules { + if _, err := os.Stat(destination); err == nil { + // if the destination already exists, do nothing + continue + } else if os.IsPermission(err) { + // if we can't access the file, skip it + continue + } else if !os.IsNotExist(err) { + // if we had an error other than non-existence, fail + return err + } + + if sourceInfo, err := os.Stat(source); err != nil { + if os.IsNotExist(err) || os.IsPermission(err) { + // if the source file doesn't exist or we can't access it, there's no work to do. + continue + } + + // if we had an error other than non-existence, fail + return err + } else if sourceInfo.IsDir() { + return fmt.Errorf("cannot migrate %v to %v because it is a directory", source, destination) + } + + in, err := os.Open(source) + if err != nil { + return err + } + defer in.Close() + out, err := os.Create(destination) + if err != nil { + return err + } + defer out.Close() + + if _, err = io.Copy(out, in); err != nil { + return err + } + } + + return nil +} + +// GetLoadingPrecedence implements ConfigAccess +func (rules *ClientConfigLoadingRules) GetLoadingPrecedence() []string { + return rules.Precedence +} + +// GetStartingConfig implements ConfigAccess +func (rules *ClientConfigLoadingRules) GetStartingConfig() (*clientcmdapi.Config, error) { + clientConfig := NewNonInteractiveDeferredLoadingClientConfig(rules, &ConfigOverrides{}) + rawConfig, err := clientConfig.RawConfig() + if os.IsNotExist(err) { + return clientcmdapi.NewConfig(), nil + } + if err != nil { + return nil, err + } + + return &rawConfig, nil +} + +// GetDefaultFilename implements ConfigAccess +func (rules *ClientConfigLoadingRules) GetDefaultFilename() string { + // Explicit file if we have one. + if rules.IsExplicitFile() { + return rules.GetExplicitFile() + } + // Otherwise, first existing file from precedence. + for _, filename := range rules.GetLoadingPrecedence() { + if _, err := os.Stat(filename); err == nil { + return filename + } + } + // If none exists, use the first from precedence. + if len(rules.Precedence) > 0 { + return rules.Precedence[0] + } + return "" +} + +// IsExplicitFile implements ConfigAccess +func (rules *ClientConfigLoadingRules) IsExplicitFile() bool { + return len(rules.ExplicitPath) > 0 +} + +// GetExplicitFile implements ConfigAccess +func (rules *ClientConfigLoadingRules) GetExplicitFile() string { + return rules.ExplicitPath +} + +// IsDefaultConfig returns true if the provided configuration matches the default +func (rules *ClientConfigLoadingRules) IsDefaultConfig(config *restclient.Config) bool { + if rules.DefaultClientConfig == nil { + return false + } + defaultConfig, err := rules.DefaultClientConfig.ClientConfig() + if err != nil { + return false + } + return reflect.DeepEqual(config, defaultConfig) +} + +// LoadFromFile takes a filename and deserializes the contents into Config object +func LoadFromFile(filename string) (*clientcmdapi.Config, error) { + kubeconfigBytes, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + config, err := Load(kubeconfigBytes) + if err != nil { + return nil, err + } + klog.V(6).Infoln("Config loaded from file", filename) + + // set LocationOfOrigin on every Cluster, User, and Context + for key, obj := range config.AuthInfos { + obj.LocationOfOrigin = filename + config.AuthInfos[key] = obj + } + for key, obj := range config.Clusters { + obj.LocationOfOrigin = filename + config.Clusters[key] = obj + } + for key, obj := range config.Contexts { + obj.LocationOfOrigin = filename + config.Contexts[key] = obj + } + + if config.AuthInfos == nil { + config.AuthInfos = map[string]*clientcmdapi.AuthInfo{} + } + if config.Clusters == nil { + config.Clusters = map[string]*clientcmdapi.Cluster{} + } + if config.Contexts == nil { + config.Contexts = map[string]*clientcmdapi.Context{} + } + + return config, nil +} + +// Load takes a byte slice and deserializes the contents into Config object. +// Encapsulates deserialization without assuming the source is a file. +func Load(data []byte) (*clientcmdapi.Config, error) { + config := clientcmdapi.NewConfig() + // if there's no data in a file, return the default object instead of failing (DecodeInto reject empty input) + if len(data) == 0 { + return config, nil + } + decoded, _, err := clientcmdlatest.Codec.Decode(data, &schema.GroupVersionKind{Version: clientcmdlatest.Version, Kind: "Config"}, config) + if err != nil { + return nil, err + } + return decoded.(*clientcmdapi.Config), nil +} + +// WriteToFile serializes the config to yaml and writes it out to a file. If not present, it creates the file with the mode 0600. If it is present +// it stomps the contents +func WriteToFile(config clientcmdapi.Config, filename string) error { + content, err := Write(config) + if err != nil { + return err + } + dir := filepath.Dir(filename) + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err = os.MkdirAll(dir, 0755); err != nil { + return err + } + } + + if err := ioutil.WriteFile(filename, content, 0600); err != nil { + return err + } + return nil +} + +func lockFile(filename string) error { + // TODO: find a way to do this with actual file locks. Will + // probably need separate solution for windows and Linux. + + // Make sure the dir exists before we try to create a lock file. + dir := filepath.Dir(filename) + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err = os.MkdirAll(dir, 0755); err != nil { + return err + } + } + f, err := os.OpenFile(lockName(filename), os.O_CREATE|os.O_EXCL, 0) + if err != nil { + return err + } + f.Close() + return nil +} + +func unlockFile(filename string) error { + return os.Remove(lockName(filename)) +} + +func lockName(filename string) string { + return filename + ".lock" +} + +// Write serializes the config to yaml. +// Encapsulates serialization without assuming the destination is a file. +func Write(config clientcmdapi.Config) ([]byte, error) { + return runtime.Encode(clientcmdlatest.Codec, &config) +} + +func (rules ClientConfigLoadingRules) ResolvePaths() bool { + return !rules.DoNotResolvePaths +} + +// ResolveLocalPaths resolves all relative paths in the config object with respect to the stanza's LocationOfOrigin +// this cannot be done directly inside of LoadFromFile because doing so there would make it impossible to load a file without +// modification of its contents. +func ResolveLocalPaths(config *clientcmdapi.Config) error { + for _, cluster := range config.Clusters { + if len(cluster.LocationOfOrigin) == 0 { + continue + } + base, err := filepath.Abs(filepath.Dir(cluster.LocationOfOrigin)) + if err != nil { + return fmt.Errorf("Could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err) + } + + if err := ResolvePaths(GetClusterFileReferences(cluster), base); err != nil { + return err + } + } + for _, authInfo := range config.AuthInfos { + if len(authInfo.LocationOfOrigin) == 0 { + continue + } + base, err := filepath.Abs(filepath.Dir(authInfo.LocationOfOrigin)) + if err != nil { + return fmt.Errorf("Could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err) + } + + if err := ResolvePaths(GetAuthInfoFileReferences(authInfo), base); err != nil { + return err + } + } + + return nil +} + +// RelativizeClusterLocalPaths first absolutizes the paths by calling ResolveLocalPaths. This assumes that any NEW path is already +// absolute, but any existing path will be resolved relative to LocationOfOrigin +func RelativizeClusterLocalPaths(cluster *clientcmdapi.Cluster) error { + if len(cluster.LocationOfOrigin) == 0 { + return fmt.Errorf("no location of origin for %s", cluster.Server) + } + base, err := filepath.Abs(filepath.Dir(cluster.LocationOfOrigin)) + if err != nil { + return fmt.Errorf("could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err) + } + + if err := ResolvePaths(GetClusterFileReferences(cluster), base); err != nil { + return err + } + if err := RelativizePathWithNoBacksteps(GetClusterFileReferences(cluster), base); err != nil { + return err + } + + return nil +} + +// RelativizeAuthInfoLocalPaths first absolutizes the paths by calling ResolveLocalPaths. This assumes that any NEW path is already +// absolute, but any existing path will be resolved relative to LocationOfOrigin +func RelativizeAuthInfoLocalPaths(authInfo *clientcmdapi.AuthInfo) error { + if len(authInfo.LocationOfOrigin) == 0 { + return fmt.Errorf("no location of origin for %v", authInfo) + } + base, err := filepath.Abs(filepath.Dir(authInfo.LocationOfOrigin)) + if err != nil { + return fmt.Errorf("could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err) + } + + if err := ResolvePaths(GetAuthInfoFileReferences(authInfo), base); err != nil { + return err + } + if err := RelativizePathWithNoBacksteps(GetAuthInfoFileReferences(authInfo), base); err != nil { + return err + } + + return nil +} + +func RelativizeConfigPaths(config *clientcmdapi.Config, base string) error { + return RelativizePathWithNoBacksteps(GetConfigFileReferences(config), base) +} + +func ResolveConfigPaths(config *clientcmdapi.Config, base string) error { + return ResolvePaths(GetConfigFileReferences(config), base) +} + +func GetConfigFileReferences(config *clientcmdapi.Config) []*string { + refs := []*string{} + + for _, cluster := range config.Clusters { + refs = append(refs, GetClusterFileReferences(cluster)...) + } + for _, authInfo := range config.AuthInfos { + refs = append(refs, GetAuthInfoFileReferences(authInfo)...) + } + + return refs +} + +func GetClusterFileReferences(cluster *clientcmdapi.Cluster) []*string { + return []*string{&cluster.CertificateAuthority} +} + +func GetAuthInfoFileReferences(authInfo *clientcmdapi.AuthInfo) []*string { + s := []*string{&authInfo.ClientCertificate, &authInfo.ClientKey, &authInfo.TokenFile} + // Only resolve exec command if it isn't PATH based. + if authInfo.Exec != nil && strings.ContainsRune(authInfo.Exec.Command, filepath.Separator) { + s = append(s, &authInfo.Exec.Command) + } + return s +} + +// ResolvePaths updates the given refs to be absolute paths, relative to the given base directory +func ResolvePaths(refs []*string, base string) error { + for _, ref := range refs { + // Don't resolve empty paths + if len(*ref) > 0 { + // Don't resolve absolute paths + if !filepath.IsAbs(*ref) { + *ref = filepath.Join(base, *ref) + } + } + } + return nil +} + +// RelativizePathWithNoBacksteps updates the given refs to be relative paths, relative to the given base directory as long as they do not require backsteps. +// Any path requiring a backstep is left as-is as long it is absolute. Any non-absolute path that can't be relativized produces an error +func RelativizePathWithNoBacksteps(refs []*string, base string) error { + for _, ref := range refs { + // Don't relativize empty paths + if len(*ref) > 0 { + rel, err := MakeRelative(*ref, base) + if err != nil { + return err + } + + // if we have a backstep, don't mess with the path + if strings.HasPrefix(rel, "../") { + if filepath.IsAbs(*ref) { + continue + } + + return fmt.Errorf("%v requires backsteps and is not absolute", *ref) + } + + *ref = rel + } + } + return nil +} + +func MakeRelative(path, base string) (string, error) { + if len(path) > 0 { + rel, err := filepath.Rel(base, path) + if err != nil { + return path, err + } + return rel, nil + } + return path, nil +} + +// deduplicate removes any duplicated values and returns a new slice, keeping the order unchanged +func deduplicate(s []string) []string { + encountered := map[string]bool{} + ret := make([]string, 0) + for i := range s { + if encountered[s[i]] { + continue + } + encountered[s[i]] = true + ret = append(ret, s[i]) + } + return ret +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go new file mode 100644 index 0000000000..9cc112a280 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/merged_client_builder.go @@ -0,0 +1,173 @@ +/* +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 clientcmd + +import ( + "io" + "sync" + + "k8s.io/klog" + + restclient "k8s.io/client-go/rest" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +// DeferredLoadingClientConfig is a ClientConfig interface that is backed by a client config loader. +// It is used in cases where the loading rules may change after you've instantiated them and you want to be sure that +// the most recent rules are used. This is useful in cases where you bind flags to loading rule parameters before +// the parse happens and you want your calling code to be ignorant of how the values are being mutated to avoid +// passing extraneous information down a call stack +type DeferredLoadingClientConfig struct { + loader ClientConfigLoader + overrides *ConfigOverrides + fallbackReader io.Reader + + clientConfig ClientConfig + loadingLock sync.Mutex + + // provided for testing + icc InClusterConfig +} + +// InClusterConfig abstracts details of whether the client is running in a cluster for testing. +type InClusterConfig interface { + ClientConfig + Possible() bool +} + +// NewNonInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name +func NewNonInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides) ClientConfig { + return &DeferredLoadingClientConfig{loader: loader, overrides: overrides, icc: &inClusterClientConfig{overrides: overrides}} +} + +// NewInteractiveDeferredLoadingClientConfig creates a ConfigClientClientConfig using the passed context name and the fallback auth reader +func NewInteractiveDeferredLoadingClientConfig(loader ClientConfigLoader, overrides *ConfigOverrides, fallbackReader io.Reader) ClientConfig { + return &DeferredLoadingClientConfig{loader: loader, overrides: overrides, icc: &inClusterClientConfig{overrides: overrides}, fallbackReader: fallbackReader} +} + +func (config *DeferredLoadingClientConfig) createClientConfig() (ClientConfig, error) { + if config.clientConfig == nil { + config.loadingLock.Lock() + defer config.loadingLock.Unlock() + + if config.clientConfig == nil { + mergedConfig, err := config.loader.Load() + if err != nil { + return nil, err + } + + var mergedClientConfig ClientConfig + if config.fallbackReader != nil { + mergedClientConfig = NewInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.fallbackReader, config.loader) + } else { + mergedClientConfig = NewNonInteractiveClientConfig(*mergedConfig, config.overrides.CurrentContext, config.overrides, config.loader) + } + + config.clientConfig = mergedClientConfig + } + } + + return config.clientConfig, nil +} + +func (config *DeferredLoadingClientConfig) RawConfig() (clientcmdapi.Config, error) { + mergedConfig, err := config.createClientConfig() + if err != nil { + return clientcmdapi.Config{}, err + } + + return mergedConfig.RawConfig() +} + +// ClientConfig implements ClientConfig +func (config *DeferredLoadingClientConfig) ClientConfig() (*restclient.Config, error) { + mergedClientConfig, err := config.createClientConfig() + if err != nil { + return nil, err + } + + // load the configuration and return on non-empty errors and if the + // content differs from the default config + mergedConfig, err := mergedClientConfig.ClientConfig() + switch { + case err != nil: + if !IsEmptyConfig(err) { + // return on any error except empty config + return nil, err + } + case mergedConfig != nil: + // the configuration is valid, but if this is equal to the defaults we should try + // in-cluster configuration + if !config.loader.IsDefaultConfig(mergedConfig) { + return mergedConfig, nil + } + } + + // check for in-cluster configuration and use it + if config.icc.Possible() { + klog.V(4).Infof("Using in-cluster configuration") + return config.icc.ClientConfig() + } + + // return the result of the merged client config + return mergedConfig, err +} + +// Namespace implements KubeConfig +func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) { + mergedKubeConfig, err := config.createClientConfig() + if err != nil { + return "", false, err + } + + ns, overridden, err := mergedKubeConfig.Namespace() + // if we get an error and it is not empty config, or if the merged config defined an explicit namespace, or + // if in-cluster config is not possible, return immediately + if (err != nil && !IsEmptyConfig(err)) || overridden || !config.icc.Possible() { + // return on any error except empty config + return ns, overridden, err + } + + if len(ns) > 0 { + // if we got a non-default namespace from the kubeconfig, use it + if ns != "default" { + return ns, false, nil + } + + // if we got a default namespace, determine whether it was explicit or implicit + if raw, err := mergedKubeConfig.RawConfig(); err == nil { + // determine the current context + currentContext := raw.CurrentContext + if config.overrides != nil && len(config.overrides.CurrentContext) > 0 { + currentContext = config.overrides.CurrentContext + } + if context := raw.Contexts[currentContext]; context != nil && len(context.Namespace) > 0 { + return ns, false, nil + } + } + } + + klog.V(4).Infof("Using in-cluster namespace") + + // allow the namespace from the service account token directory to be used. + return config.icc.Namespace() +} + +// ConfigAccess implements ClientConfig +func (config *DeferredLoadingClientConfig) ConfigAccess() ConfigAccess { + return config.loader +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go new file mode 100644 index 0000000000..bfca032847 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/overrides.go @@ -0,0 +1,247 @@ +/* +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 clientcmd + +import ( + "strconv" + "strings" + + "github.com/spf13/pflag" + + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +// ConfigOverrides holds values that should override whatever information is pulled from the actual Config object. You can't +// simply use an actual Config object, because Configs hold maps, but overrides are restricted to "at most one" +type ConfigOverrides struct { + AuthInfo clientcmdapi.AuthInfo + // ClusterDefaults are applied before the configured cluster info is loaded. + ClusterDefaults clientcmdapi.Cluster + ClusterInfo clientcmdapi.Cluster + Context clientcmdapi.Context + CurrentContext string + Timeout string +} + +// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly +// corresponds to ConfigOverrides +type ConfigOverrideFlags struct { + AuthOverrideFlags AuthOverrideFlags + ClusterOverrideFlags ClusterOverrideFlags + ContextOverrideFlags ContextOverrideFlags + CurrentContext FlagInfo + Timeout FlagInfo +} + +// AuthOverrideFlags holds the flag names to be used for binding command line flags for AuthInfo objects +type AuthOverrideFlags struct { + ClientCertificate FlagInfo + ClientKey FlagInfo + Token FlagInfo + Impersonate FlagInfo + ImpersonateGroups FlagInfo + Username FlagInfo + Password FlagInfo +} + +// ContextOverrideFlags holds the flag names to be used for binding command line flags for Cluster objects +type ContextOverrideFlags struct { + ClusterName FlagInfo + AuthInfoName FlagInfo + Namespace FlagInfo +} + +// ClusterOverride holds the flag names to be used for binding command line flags for Cluster objects +type ClusterOverrideFlags struct { + APIServer FlagInfo + APIVersion FlagInfo + CertificateAuthority FlagInfo + InsecureSkipTLSVerify FlagInfo +} + +// FlagInfo contains information about how to register a flag. This struct is useful if you want to provide a way for an extender to +// get back a set of recommended flag names, descriptions, and defaults, but allow for customization by an extender. This makes for +// coherent extension, without full prescription +type FlagInfo struct { + // LongName is the long string for a flag. If this is empty, then the flag will not be bound + LongName string + // ShortName is the single character for a flag. If this is empty, then there will be no short flag + ShortName string + // Default is the default value for the flag + Default string + // Description is the description for the flag + Description string +} + +// AddSecretAnnotation add secret flag to Annotation. +func (f FlagInfo) AddSecretAnnotation(flags *pflag.FlagSet) FlagInfo { + flags.SetAnnotation(f.LongName, "classified", []string{"true"}) + return f +} + +// BindStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered +func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo { + // you can't register a flag without a long name + if len(f.LongName) > 0 { + flags.StringVarP(target, f.LongName, f.ShortName, f.Default, f.Description) + } + return f +} + +// BindTransformingStringFlag binds the flag based on the provided info. If LongName == "", nothing is registered +func (f FlagInfo) BindTransformingStringFlag(flags *pflag.FlagSet, target *string, transformer func(string) (string, error)) FlagInfo { + // you can't register a flag without a long name + if len(f.LongName) > 0 { + flags.VarP(newTransformingStringValue(f.Default, target, transformer), f.LongName, f.ShortName, f.Description) + } + return f +} + +// BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered +func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo { + // you can't register a flag without a long name + if len(f.LongName) > 0 { + sliceVal := []string{} + if len(f.Default) > 0 { + sliceVal = []string{f.Default} + } + flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description) + } + return f +} + +// BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered +func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo { + // you can't register a flag without a long name + if len(f.LongName) > 0 { + // try to parse Default as a bool. If it fails, assume false + boolVal, err := strconv.ParseBool(f.Default) + if err != nil { + boolVal = false + } + + flags.BoolVarP(target, f.LongName, f.ShortName, boolVal, f.Description) + } + return f +} + +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" + FlagEmbedCerts = "embed-certs" + FlagBearerToken = "token" + FlagImpersonate = "as" + FlagImpersonateGroup = "as-group" + FlagUsername = "username" + FlagPassword = "password" + FlagTimeout = "request-timeout" +) + +// RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing +func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags { + return ConfigOverrideFlags{ + AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix), + ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix), + ContextOverrideFlags: RecommendedContextOverrideFlags(prefix), + + CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"}, + Timeout: FlagInfo{prefix + FlagTimeout, "", "0", "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."}, + } +} + +// RecommendedAuthOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing +func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags { + return AuthOverrideFlags{ + ClientCertificate: FlagInfo{prefix + FlagCertFile, "", "", "Path to a client certificate file for TLS"}, + ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"}, + Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"}, + Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"}, + ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group to impersonate for the operation, this flag can be repeated to specify multiple groups."}, + Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"}, + Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"}, + } +} + +// RecommendedClusterOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing +func RecommendedClusterOverrideFlags(prefix string) ClusterOverrideFlags { + return ClusterOverrideFlags{ + APIServer: FlagInfo{prefix + FlagAPIServer, "", "", "The address and port of the Kubernetes API server"}, + CertificateAuthority: FlagInfo{prefix + FlagCAFile, "", "", "Path to a cert file for the certificate authority"}, + InsecureSkipTLSVerify: FlagInfo{prefix + FlagInsecure, "", "false", "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure"}, + } +} + +// RecommendedContextOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing +func RecommendedContextOverrideFlags(prefix string) ContextOverrideFlags { + return ContextOverrideFlags{ + ClusterName: FlagInfo{prefix + FlagClusterName, "", "", "The name of the kubeconfig cluster to use"}, + AuthInfoName: FlagInfo{prefix + FlagAuthInfoName, "", "", "The name of the kubeconfig user to use"}, + Namespace: FlagInfo{prefix + FlagNamespace, "n", "", "If present, the namespace scope for this CLI request"}, + } +} + +// BindOverrideFlags is a convenience method to bind the specified flags to their associated variables +func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNames ConfigOverrideFlags) { + BindAuthInfoFlags(&overrides.AuthInfo, flags, flagNames.AuthOverrideFlags) + BindClusterFlags(&overrides.ClusterInfo, flags, flagNames.ClusterOverrideFlags) + BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags) + flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext) + flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout) +} + +// BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables +func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, flagNames AuthOverrideFlags) { + flagNames.ClientCertificate.BindStringFlag(flags, &authInfo.ClientCertificate).AddSecretAnnotation(flags) + flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags) + flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags) + flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags) + flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags) + flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags) + flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags) +} + +// BindClusterFlags is a convenience method to bind the specified flags to their associated variables +func BindClusterFlags(clusterInfo *clientcmdapi.Cluster, flags *pflag.FlagSet, flagNames ClusterOverrideFlags) { + flagNames.APIServer.BindStringFlag(flags, &clusterInfo.Server) + flagNames.CertificateAuthority.BindStringFlag(flags, &clusterInfo.CertificateAuthority) + flagNames.InsecureSkipTLSVerify.BindBoolFlag(flags, &clusterInfo.InsecureSkipTLSVerify) +} + +// BindFlags is a convenience method to bind the specified flags to their associated variables +func BindContextFlags(contextInfo *clientcmdapi.Context, flags *pflag.FlagSet, flagNames ContextOverrideFlags) { + flagNames.ClusterName.BindStringFlag(flags, &contextInfo.Cluster) + flagNames.AuthInfoName.BindStringFlag(flags, &contextInfo.AuthInfo) + flagNames.Namespace.BindTransformingStringFlag(flags, &contextInfo.Namespace, RemoveNamespacesPrefix) +} + +// RemoveNamespacesPrefix is a transformer that strips "ns/", "namespace/" and "namespaces/" prefixes case-insensitively +func RemoveNamespacesPrefix(value string) (string, error) { + for _, prefix := range []string{"namespaces/", "namespace/", "ns/"} { + if len(value) > len(prefix) && strings.EqualFold(value[0:len(prefix)], prefix) { + value = value[len(prefix):] + break + } + } + return value, nil +} diff --git a/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/validation.go b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/validation.go new file mode 100644 index 0000000000..629c0b30a0 --- /dev/null +++ b/vendor/k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd/validation.go @@ -0,0 +1,298 @@ +/* +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 clientcmd + +import ( + "errors" + "fmt" + "os" + "reflect" + "strings" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/validation" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +var ( + ErrNoContext = errors.New("no context chosen") + ErrEmptyConfig = errors.New("no configuration has been provided") + // message is for consistency with old behavior + ErrEmptyCluster = errors.New("cluster has no server defined") +) + +type errContextNotFound struct { + ContextName string +} + +func (e *errContextNotFound) Error() string { + return fmt.Sprintf("context was not found for specified context: %v", e.ContextName) +} + +// IsContextNotFound returns a boolean indicating whether the error is known to +// report that a context was not found +func IsContextNotFound(err error) bool { + if err == nil { + return false + } + if _, ok := err.(*errContextNotFound); ok || err == ErrNoContext { + return true + } + return strings.Contains(err.Error(), "context was not found for specified context") +} + +// IsEmptyConfig returns true if the provided error indicates the provided configuration +// is empty. +func IsEmptyConfig(err error) bool { + switch t := err.(type) { + case errConfigurationInvalid: + return len(t) == 1 && t[0] == ErrEmptyConfig + } + return err == ErrEmptyConfig +} + +// errConfigurationInvalid is a set of errors indicating the configuration is invalid. +type errConfigurationInvalid []error + +// errConfigurationInvalid implements error and Aggregate +var _ error = errConfigurationInvalid{} +var _ utilerrors.Aggregate = errConfigurationInvalid{} + +func newErrConfigurationInvalid(errs []error) error { + switch len(errs) { + case 0: + return nil + default: + return errConfigurationInvalid(errs) + } +} + +// Error implements the error interface +func (e errConfigurationInvalid) Error() string { + return fmt.Sprintf("invalid configuration: %v", utilerrors.NewAggregate(e).Error()) +} + +// Errors implements the AggregateError interface +func (e errConfigurationInvalid) Errors() []error { + return e +} + +// IsConfigurationInvalid returns true if the provided error indicates the configuration is invalid. +func IsConfigurationInvalid(err error) bool { + switch err.(type) { + case *errContextNotFound, errConfigurationInvalid: + return true + } + return IsContextNotFound(err) +} + +// Validate checks for errors in the Config. It does not return early so that it can find as many errors as possible. +func Validate(config clientcmdapi.Config) error { + validationErrors := make([]error, 0) + + if clientcmdapi.IsConfigEmpty(&config) { + return newErrConfigurationInvalid([]error{ErrEmptyConfig}) + } + + if len(config.CurrentContext) != 0 { + if _, exists := config.Contexts[config.CurrentContext]; !exists { + validationErrors = append(validationErrors, &errContextNotFound{config.CurrentContext}) + } + } + + for contextName, context := range config.Contexts { + validationErrors = append(validationErrors, validateContext(contextName, *context, config)...) + } + + for authInfoName, authInfo := range config.AuthInfos { + validationErrors = append(validationErrors, validateAuthInfo(authInfoName, *authInfo)...) + } + + for clusterName, clusterInfo := range config.Clusters { + validationErrors = append(validationErrors, validateClusterInfo(clusterName, *clusterInfo)...) + } + + return newErrConfigurationInvalid(validationErrors) +} + +// ConfirmUsable looks a particular context and determines if that particular part of the config is useable. There might still be errors in the config, +// but no errors in the sections requested or referenced. It does not return early so that it can find as many errors as possible. +func ConfirmUsable(config clientcmdapi.Config, passedContextName string) error { + validationErrors := make([]error, 0) + + if clientcmdapi.IsConfigEmpty(&config) { + return newErrConfigurationInvalid([]error{ErrEmptyConfig}) + } + + var contextName string + if len(passedContextName) != 0 { + contextName = passedContextName + } else { + contextName = config.CurrentContext + } + + if len(contextName) == 0 { + return ErrNoContext + } + + context, exists := config.Contexts[contextName] + if !exists { + validationErrors = append(validationErrors, &errContextNotFound{contextName}) + } + + if exists { + validationErrors = append(validationErrors, validateContext(contextName, *context, config)...) + validationErrors = append(validationErrors, validateAuthInfo(context.AuthInfo, *config.AuthInfos[context.AuthInfo])...) + validationErrors = append(validationErrors, validateClusterInfo(context.Cluster, *config.Clusters[context.Cluster])...) + } + + return newErrConfigurationInvalid(validationErrors) +} + +// validateClusterInfo looks for conflicts and errors in the cluster info +func validateClusterInfo(clusterName string, clusterInfo clientcmdapi.Cluster) []error { + validationErrors := make([]error, 0) + + emptyCluster := clientcmdapi.NewCluster() + if reflect.DeepEqual(*emptyCluster, clusterInfo) { + return []error{ErrEmptyCluster} + } + + if len(clusterInfo.Server) == 0 { + if len(clusterName) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("default cluster has no server defined")) + } else { + validationErrors = append(validationErrors, fmt.Errorf("no server found for cluster %q", clusterName)) + } + } + // Make sure CA data and CA file aren't both specified + if len(clusterInfo.CertificateAuthority) != 0 && len(clusterInfo.CertificateAuthorityData) != 0 { + validationErrors = append(validationErrors, fmt.Errorf("certificate-authority-data and certificate-authority are both specified for %v. certificate-authority-data will override.", clusterName)) + } + if len(clusterInfo.CertificateAuthority) != 0 { + clientCertCA, err := os.Open(clusterInfo.CertificateAuthority) + defer clientCertCA.Close() + if err != nil { + validationErrors = append(validationErrors, fmt.Errorf("unable to read certificate-authority %v for %v due to %v", clusterInfo.CertificateAuthority, clusterName, err)) + } + } + + return validationErrors +} + +// validateAuthInfo looks for conflicts and errors in the auth info +func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []error { + validationErrors := make([]error, 0) + + usingAuthPath := false + methods := make([]string, 0, 3) + if len(authInfo.Token) != 0 { + methods = append(methods, "token") + } + if len(authInfo.Username) != 0 || len(authInfo.Password) != 0 { + methods = append(methods, "basicAuth") + } + + if len(authInfo.ClientCertificate) != 0 || len(authInfo.ClientCertificateData) != 0 { + // Make sure cert data and file aren't both specified + if len(authInfo.ClientCertificate) != 0 && len(authInfo.ClientCertificateData) != 0 { + validationErrors = append(validationErrors, fmt.Errorf("client-cert-data and client-cert are both specified for %v. client-cert-data will override.", authInfoName)) + } + // Make sure key data and file aren't both specified + if len(authInfo.ClientKey) != 0 && len(authInfo.ClientKeyData) != 0 { + validationErrors = append(validationErrors, fmt.Errorf("client-key-data and client-key are both specified for %v; client-key-data will override", authInfoName)) + } + // Make sure a key is specified + if len(authInfo.ClientKey) == 0 && len(authInfo.ClientKeyData) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("client-key-data or client-key must be specified for %v to use the clientCert authentication method.", authInfoName)) + } + + if len(authInfo.ClientCertificate) != 0 { + clientCertFile, err := os.Open(authInfo.ClientCertificate) + defer clientCertFile.Close() + if err != nil { + validationErrors = append(validationErrors, fmt.Errorf("unable to read client-cert %v for %v due to %v", authInfo.ClientCertificate, authInfoName, err)) + } + } + if len(authInfo.ClientKey) != 0 { + clientKeyFile, err := os.Open(authInfo.ClientKey) + defer clientKeyFile.Close() + if err != nil { + validationErrors = append(validationErrors, fmt.Errorf("unable to read client-key %v for %v due to %v", authInfo.ClientKey, authInfoName, err)) + } + } + } + + if authInfo.Exec != nil { + if authInfo.AuthProvider != nil { + validationErrors = append(validationErrors, fmt.Errorf("authProvider cannot be provided in combination with an exec plugin for %s", authInfoName)) + } + if len(authInfo.Exec.Command) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("command must be specified for %v to use exec authentication plugin", authInfoName)) + } + if len(authInfo.Exec.APIVersion) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("apiVersion must be specified for %v to use exec authentication plugin", authInfoName)) + } + for _, v := range authInfo.Exec.Env { + if len(v.Name) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("env variable name must be specified for %v to use exec authentication plugin", authInfoName)) + } else if len(v.Value) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("env variable %s value must be specified for %v to use exec authentication plugin", v.Name, authInfoName)) + } + } + } + + // authPath also provides information for the client to identify the server, so allow multiple auth methods in that case + if (len(methods) > 1) && (!usingAuthPath) { + validationErrors = append(validationErrors, fmt.Errorf("more than one authentication method found for %v; found %v, only one is allowed", authInfoName, methods)) + } + + // ImpersonateGroups or ImpersonateUserExtra should be requested with a user + if (len(authInfo.ImpersonateGroups) > 0 || len(authInfo.ImpersonateUserExtra) > 0) && (len(authInfo.Impersonate) == 0) { + validationErrors = append(validationErrors, fmt.Errorf("requesting groups or user-extra for %v without impersonating a user", authInfoName)) + } + return validationErrors +} + +// validateContext looks for errors in the context. It is not transitive, so errors in the reference authInfo or cluster configs are not included in this return +func validateContext(contextName string, context clientcmdapi.Context, config clientcmdapi.Config) []error { + validationErrors := make([]error, 0) + + if len(contextName) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("empty context name for %#v is not allowed", context)) + } + + if len(context.AuthInfo) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("user was not specified for context %q", contextName)) + } else if _, exists := config.AuthInfos[context.AuthInfo]; !exists { + validationErrors = append(validationErrors, fmt.Errorf("user %q was not found for context %q", context.AuthInfo, contextName)) + } + + if len(context.Cluster) == 0 { + validationErrors = append(validationErrors, fmt.Errorf("cluster was not specified for context %q", contextName)) + } else if _, exists := config.Clusters[context.Cluster]; !exists { + validationErrors = append(validationErrors, fmt.Errorf("cluster %q was not found for context %q", context.Cluster, contextName)) + } + + if len(context.Namespace) != 0 { + if len(validation.IsDNS1123Label(context.Namespace)) != 0 { + validationErrors = append(validationErrors, fmt.Errorf("namespace %q for context %q does not conform to the kubernetes DNS_LABEL rules", context.Namespace, contextName)) + } + } + + return validationErrors +} From c0702b04927fb18693b168ddb3b12be40d845d5c Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 9 May 2019 15:05:51 -0700 Subject: [PATCH 2/4] Port to wrangler --- main.go | 5 +- pkg/agent/config/config.go | 2 +- pkg/agent/proxy/proxy.go | 2 +- pkg/agent/run.go | 2 +- pkg/agent/tunnel/tunnel.go | 2 +- pkg/apis/k3s.cattle.io/v1/doc.go | 21 +++ pkg/apis/k3s.cattle.io/v1/types.go | 9 + pkg/cli/agent/agent.go | 5 +- pkg/cli/server/server.go | 4 +- pkg/clientaccess/clientaccess.go | 277 +++++++++++++++++++++++++++++ pkg/codegen/cleanup/main.go | 4 +- pkg/codegen/main.go | 94 ++++++---- pkg/daemons/control/server.go | 2 +- pkg/daemons/control/tunnel.go | 4 +- pkg/datadir/datadir.go | 2 +- pkg/deploy/controller.go | 92 ++-------- pkg/node/controller.go | 25 +-- pkg/proxy/proxy_server.go | 65 +++++++ pkg/rootlessports/controller.go | 20 +-- pkg/server/context.go | 61 +++++++ pkg/server/router.go | 2 +- pkg/server/server.go | 157 ++++++++-------- pkg/server/types.go | 2 +- pkg/servicelb/controller.go | 88 +++++---- pkg/tls/storage.go | 28 ++- scripts/boilerplate.go.txt | 16 ++ 26 files changed, 716 insertions(+), 275 deletions(-) create mode 100644 pkg/apis/k3s.cattle.io/v1/doc.go create mode 100644 pkg/clientaccess/clientaccess.go create mode 100644 pkg/proxy/proxy_server.go create mode 100644 pkg/server/context.go create mode 100644 scripts/boilerplate.go.txt diff --git a/main.go b/main.go index 878b0a22aa..aba5def3e6 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,6 @@ -//go:generate go run types/codegen/cleanup/main.go -//go:generate go run types/codegen/main.go +//go:generate go run pkg/codegen/cleanup/main.go +//go:generate /bin/rm -rf pkg/generated +//go:generate go run pkg/codegen/main.go //go:generate go fmt pkg/deploy/zz_generated_bindata.go //go:generate go fmt pkg/static/zz_generated_bindata.go //go:generate go fmt pkg/openapi/zz_generated_bindata.go diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index 330d94fafd..a32bc5cf69 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -21,8 +21,8 @@ import ( "github.com/pkg/errors" "github.com/rancher/k3s/pkg/cli/cmds" + "github.com/rancher/k3s/pkg/clientaccess" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/norman/pkg/clientaccess" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/net" diff --git a/pkg/agent/proxy/proxy.go b/pkg/agent/proxy/proxy.go index b7a1b17a31..21d6dc91a9 100644 --- a/pkg/agent/proxy/proxy.go +++ b/pkg/agent/proxy/proxy.go @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/norman/pkg/proxy" + "github.com/rancher/k3s/pkg/proxy" "github.com/sirupsen/logrus" ) diff --git a/pkg/agent/run.go b/pkg/agent/run.go index 9e36cda0bf..cc18e3203d 100644 --- a/pkg/agent/run.go +++ b/pkg/agent/run.go @@ -16,9 +16,9 @@ import ( "github.com/rancher/k3s/pkg/agent/syssetup" "github.com/rancher/k3s/pkg/agent/tunnel" "github.com/rancher/k3s/pkg/cli/cmds" + "github.com/rancher/k3s/pkg/clientaccess" "github.com/rancher/k3s/pkg/daemons/agent" "github.com/rancher/k3s/pkg/rootless" - "github.com/rancher/norman/pkg/clientaccess" "github.com/sirupsen/logrus" ) diff --git a/pkg/agent/tunnel/tunnel.go b/pkg/agent/tunnel/tunnel.go index 2faf32af97..6ce3a9938c 100644 --- a/pkg/agent/tunnel/tunnel.go +++ b/pkg/agent/tunnel/tunnel.go @@ -13,7 +13,7 @@ import ( "github.com/gorilla/websocket" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/norman/pkg/remotedialer" + "github.com/rancher/remotedialer" "github.com/sirupsen/logrus" "k8s.io/client-go/tools/clientcmd" ) diff --git a/pkg/apis/k3s.cattle.io/v1/doc.go b/pkg/apis/k3s.cattle.io/v1/doc.go new file mode 100644 index 0000000000..1be22ca536 --- /dev/null +++ b/pkg/apis/k3s.cattle.io/v1/doc.go @@ -0,0 +1,21 @@ +/* +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 main. DO NOT EDIT. + +// +k8s:deepcopy-gen=package +// +groupName=k3s.cattle.io +package v1 diff --git a/pkg/apis/k3s.cattle.io/v1/types.go b/pkg/apis/k3s.cattle.io/v1/types.go index ee6e5cc6bb..87f3971d09 100644 --- a/pkg/apis/k3s.cattle.io/v1/types.go +++ b/pkg/apis/k3s.cattle.io/v1/types.go @@ -7,6 +7,9 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + type ListenerConfig struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -14,6 +17,9 @@ type ListenerConfig struct { Status dynamiclistener.ListenerStatus `json:"status,omitempty"` } +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + type Addon struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -31,6 +37,9 @@ type AddonStatus struct { GVKs []schema.GroupVersionKind `json:"gvks,omitempty"` } +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + type HelmChart struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/pkg/cli/agent/agent.go b/pkg/cli/agent/agent.go index 47da1e1e6b..5f45f8d349 100644 --- a/pkg/cli/agent/agent.go +++ b/pkg/cli/agent/agent.go @@ -8,10 +8,11 @@ import ( "strings" "time" + "github.com/rancher/wrangler/pkg/signals" + "github.com/rancher/k3s/pkg/agent" "github.com/rancher/k3s/pkg/cli/cmds" "github.com/rancher/k3s/pkg/datadir" - "github.com/rancher/norman/signal" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) @@ -67,7 +68,7 @@ func Run(ctx *cli.Context) error { cfg.DataDir = dataDir cfg.Labels = append(cfg.Labels, "node-role.kubernetes.io/worker=true") - contextCtx := signal.SigTermCancelContext(context.Background()) + contextCtx := signals.SetupSignalHandler(context.Background()) return agent.Run(contextCtx, cfg) } diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index 50288c4f4d..e8691f1d5a 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -19,7 +19,7 @@ import ( "github.com/rancher/k3s/pkg/datadir" "github.com/rancher/k3s/pkg/rootless" "github.com/rancher/k3s/pkg/server" - "github.com/rancher/norman/signal" + "github.com/rancher/wrangler/pkg/signals" "github.com/sirupsen/logrus" "github.com/urfave/cli" "k8s.io/apimachinery/pkg/util/net" @@ -145,7 +145,7 @@ func run(app *cli.Context, cfg *cmds.Server) error { notifySocket := os.Getenv("NOTIFY_SOCKET") os.Unsetenv("NOTIFY_SOCKET") - ctx := signal.SigTermCancelContext(context.Background()) + ctx := signals.SetupSignalHandler(context.Background()) certs, err := server.StartServer(ctx, &serverConfig) if err != nil { return err diff --git a/pkg/clientaccess/clientaccess.go b/pkg/clientaccess/clientaccess.go new file mode 100644 index 0000000000..8fcaf5ad44 --- /dev/null +++ b/pkg/clientaccess/clientaccess.go @@ -0,0 +1,277 @@ +package clientaccess + +import ( + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/hex" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + "strings" + + "github.com/pkg/errors" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +var ( + insecureClient = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + } +) + +type OverrideURLCallback func(config []byte) (*url.URL, error) + +type clientToken struct { + caHash string + username string + password string +} + +func AgentAccessInfoToTempKubeConfig(tempDir, server, token string) (string, error) { + f, err := ioutil.TempFile(tempDir, "tmp-") + if err != nil { + return "", err + } + if err := f.Close(); err != nil { + return "", err + } + err = accessInfoToKubeConfig(f.Name(), server, token) + if err != nil { + os.Remove(f.Name()) + } + return f.Name(), err +} + +func AgentAccessInfoToKubeConfig(destFile, server, token string) error { + return accessInfoToKubeConfig(destFile, server, token) +} + +type Info struct { + URL string `json:"url,omitempty"` + CACerts []byte `json:"cacerts,omitempty"` + username string + password string + Token string `json:"token,omitempty"` +} + +func (i *Info) WriteKubeConfig(destFile string) error { + return clientcmd.WriteToFile(*i.KubeConfig(), destFile) +} + +func (i *Info) KubeConfig() *clientcmdapi.Config { + config := clientcmdapi.NewConfig() + + cluster := clientcmdapi.NewCluster() + cluster.CertificateAuthorityData = i.CACerts + cluster.Server = i.URL + + authInfo := clientcmdapi.NewAuthInfo() + if i.password != "" { + authInfo.Username = i.username + authInfo.Password = i.password + } else if i.Token != "" { + if username, pass, ok := ParseUsernamePassword(i.Token); ok { + authInfo.Username = username + authInfo.Password = pass + } else { + authInfo.Token = i.Token + } + } + + context := clientcmdapi.NewContext() + context.AuthInfo = "default" + context.Cluster = "default" + + config.Clusters["default"] = cluster + config.AuthInfos["default"] = authInfo + config.Contexts["default"] = context + config.CurrentContext = "default" + + return config +} + +func ParseAndValidateToken(server, token string) (*Info, error) { + url, err := url.Parse(server) + if err != nil { + return nil, errors.Wrapf(err, "Invalid url, failed to parse %s", server) + } + + if url.Scheme != "https" { + return nil, fmt.Errorf("only https:// URLs are supported, invalid scheme: %s", server) + } + + for strings.HasSuffix(url.Path, "/") { + url.Path = url.Path[:len(url.Path)-1] + } + + parsedToken, err := parseToken(token) + if err != nil { + return nil, err + } + + cacerts, err := GetCACerts(*url) + if err != nil { + return nil, err + } + + if len(cacerts) > 0 && len(parsedToken.caHash) > 0 { + if ok, hash, newHash := validateCACerts(cacerts, parsedToken.caHash); !ok { + return nil, fmt.Errorf("token does not match the server %s != %s", hash, newHash) + } + } + + if err := validateToken(*url, cacerts, parsedToken.username, parsedToken.password); err != nil { + return nil, err + } + + return &Info{ + URL: url.String(), + CACerts: cacerts, + username: parsedToken.username, + password: parsedToken.password, + Token: token, + }, nil +} + +func accessInfoToKubeConfig(destFile, server, token string) error { + info, err := ParseAndValidateToken(server, token) + if err != nil { + return err + } + + return info.WriteKubeConfig(destFile) +} + +func validateToken(u url.URL, cacerts []byte, username, password string) error { + u.Path = "/apis" + _, err := get(u.String(), GetHTTPClient(cacerts), username, password) + if err != nil { + return errors.Wrap(err, "token is not valid") + } + return nil +} + +func validateCACerts(cacerts []byte, hash string) (bool, string, string) { + if len(cacerts) == 0 && hash == "" { + return true, "", "" + } + + digest := sha256.Sum256([]byte(cacerts)) + newHash := hex.EncodeToString(digest[:]) + return hash == newHash, hash, newHash +} + +func ParseUsernamePassword(token string) (string, string, bool) { + parsed, err := parseToken(token) + if err != nil { + return "", "", false + } + return parsed.username, parsed.password, true +} + +func parseToken(token string) (clientToken, error) { + var result clientToken + + if !strings.HasPrefix(token, "K10") { + return result, fmt.Errorf("token is not a valid token format") + } + + token = token[3:] + + parts := strings.SplitN(token, "::", 2) + token = parts[0] + if len(parts) > 1 { + result.caHash = parts[0] + token = parts[1] + } + + parts = strings.SplitN(token, ":", 2) + if len(parts) != 2 { + return result, fmt.Errorf("token credentials are the wrong format") + } + + result.username = parts[0] + result.password = parts[1] + + return result, nil +} + +func GetHTTPClient(cacerts []byte) *http.Client { + if len(cacerts) == 0 { + return http.DefaultClient + } + + pool := x509.NewCertPool() + pool.AppendCertsFromPEM(cacerts) + + return &http.Client{ + Transport: &http.Transport{ + DisableKeepAlives: true, + TLSClientConfig: &tls.Config{ + RootCAs: pool, + }, + }, + } +} + +func Get(path string, info *Info) ([]byte, error) { + u, err := url.Parse(info.URL) + if err != nil { + return nil, err + } + u.Path = path + return get(u.String(), GetHTTPClient(info.CACerts), info.username, info.password) +} + +func GetCACerts(u url.URL) ([]byte, error) { + u.Path = "/cacerts" + url := u.String() + + _, err := get(url, http.DefaultClient, "", "") + if err == nil { + return nil, nil + } + + cacerts, err := get(url, insecureClient, "", "") + if err != nil { + return nil, errors.Wrapf(err, "failed to get CA certs at %s", url) + } + + _, err = get(url, GetHTTPClient(cacerts), "", "") + if err != nil { + return nil, errors.Wrapf(err, "server %s is not trusted", url) + } + + return cacerts, nil +} + +func get(u string, client *http.Client, username, password string) ([]byte, error) { + req, err := http.NewRequest(http.MethodGet, u, nil) + if err != nil { + return nil, err + } + + if username != "" { + req.SetBasicAuth(username, password) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("%s: %s", u, resp.Status) + } + + return ioutil.ReadAll(resp.Body) +} diff --git a/pkg/codegen/cleanup/main.go b/pkg/codegen/cleanup/main.go index 7fb7d83868..57a1ca7d45 100644 --- a/pkg/codegen/cleanup/main.go +++ b/pkg/codegen/cleanup/main.go @@ -1,12 +1,12 @@ package main import ( - "github.com/rancher/norman/generator/cleanup" + "github.com/rancher/wrangler/pkg/cleanup" "github.com/sirupsen/logrus" ) func main() { - if err := cleanup.Cleanup("./types"); err != nil { + if err := cleanup.Cleanup("./pkg/apis"); err != nil { logrus.Fatal(err) } } diff --git a/pkg/codegen/main.go b/pkg/codegen/main.go index e33a7553a4..f1d8261657 100644 --- a/pkg/codegen/main.go +++ b/pkg/codegen/main.go @@ -1,9 +1,12 @@ package main import ( + "os" + bindata "github.com/jteeuwen/go-bindata" - v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" - "github.com/rancher/norman/generator" + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + controllergen "github.com/rancher/wrangler/pkg/controller-gen" + "github.com/rancher/wrangler/pkg/controller-gen/args" "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" @@ -16,6 +19,7 @@ var ( ) func main() { + os.Unsetenv("GOPATH") bc := &bindata.Config{ Input: []bindata.InputConfig{ { @@ -82,38 +86,56 @@ func main() { logrus.Fatal(err) } - if err := generator.DefaultGenerate(v1.Schemas, basePackage, false, nil); err != nil { - logrus.Fatal(err) - } - - if err := generator.ControllersForForeignTypes(basePackage, corev1.SchemeGroupVersion, []interface{}{ - corev1.ServiceAccount{}, - corev1.Endpoints{}, - corev1.Service{}, - corev1.Pod{}, - corev1.ConfigMap{}, - }, []interface{}{ - corev1.Node{}, - }); err != nil { - logrus.Fatal(err) - } - - if err := generator.ControllersForForeignTypes(basePackage, appsv1.SchemeGroupVersion, []interface{}{ - appsv1.DaemonSet{}, - appsv1.Deployment{}, - }, nil); err != nil { - logrus.Fatal(err) - } - - if err := generator.ControllersForForeignTypes(basePackage, batchv1.SchemeGroupVersion, []interface{}{ - batchv1.Job{}, - }, nil); err != nil { - logrus.Fatal(err) - } - - if err := generator.ControllersForForeignTypes(basePackage, rbacv1.SchemeGroupVersion, nil, []interface{}{ - rbacv1.ClusterRoleBinding{}, - }); err != nil { - logrus.Fatal(err) - } + controllergen.Run(args.Options{ + OutputPackage: "github.com/rancher/k3s/pkg/generated", + Boilerplate: "scripts/boilerplate.go.txt", + Groups: map[string]args.Group{ + "k3s.cattle.io": { + Types: []interface{}{ + v1.ListenerConfig{}, + v1.Addon{}, + v1.HelmChart{}, + }, + GenerateTypes: true, + }, + "": { + Types: []interface{}{ + corev1.ServiceAccount{}, + corev1.Endpoints{}, + corev1.Service{}, + corev1.Pod{}, + corev1.ConfigMap{}, + corev1.Node{}, + }, + InformersPackage: "k8s.io/client-go/informers", + ClientSetPackage: "k8s.io/client-go/kubernetes", + ListersPackage: "k8s.io/client-go/listers", + }, + "apps": { + Types: []interface{}{ + appsv1.Deployment{}, + appsv1.DaemonSet{}, + }, + InformersPackage: "k8s.io/client-go/informers", + ClientSetPackage: "k8s.io/client-go/kubernetes", + ListersPackage: "k8s.io/client-go/listers", + }, + "batch": { + Types: []interface{}{ + batchv1.Job{}, + }, + InformersPackage: "k8s.io/client-go/informers", + ClientSetPackage: "k8s.io/client-go/kubernetes", + ListersPackage: "k8s.io/client-go/listers", + }, + "rbac": { + Types: []interface{}{ + rbacv1.ClusterRoleBinding{}, + }, + InformersPackage: "k8s.io/client-go/informers", + ClientSetPackage: "k8s.io/client-go/kubernetes", + ListersPackage: "k8s.io/client-go/listers", + }, + }, + }) } diff --git a/pkg/daemons/control/server.go b/pkg/daemons/control/server.go index a3f349ec69..892d367122 100644 --- a/pkg/daemons/control/server.go +++ b/pkg/daemons/control/server.go @@ -23,8 +23,8 @@ import ( "strings" "time" + certutil "github.com/rancher/dynamiclistener/cert" "github.com/rancher/k3s/pkg/daemons/config" - certutil "github.com/rancher/norman/pkg/cert" "github.com/sirupsen/logrus" "k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/kubernetes/cmd/kube-apiserver/app" diff --git a/pkg/daemons/control/tunnel.go b/pkg/daemons/control/tunnel.go index e5020c0f3f..a304c4dd3d 100644 --- a/pkg/daemons/control/tunnel.go +++ b/pkg/daemons/control/tunnel.go @@ -6,8 +6,8 @@ import ( "net/http" "time" - "github.com/rancher/norman/pkg/kv" - "github.com/rancher/norman/pkg/remotedialer" + "github.com/rancher/remotedialer" + "github.com/rancher/wrangler/pkg/kv" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/kubernetes/cmd/kube-apiserver/app" diff --git a/pkg/datadir/datadir.go b/pkg/datadir/datadir.go index 7653a10cfc..0e80d3fb9c 100644 --- a/pkg/datadir/datadir.go +++ b/pkg/datadir/datadir.go @@ -4,7 +4,7 @@ import ( "os" "github.com/pkg/errors" - "github.com/rancher/norman/pkg/resolvehome" + "github.com/rancher/wrangler/pkg/resolvehome" ) const ( diff --git a/pkg/deploy/controller.go b/pkg/deploy/controller.go index 30ac2ad16d..6134e9d362 100644 --- a/pkg/deploy/controller.go +++ b/pkg/deploy/controller.go @@ -14,20 +14,16 @@ import ( "time" errors2 "github.com/pkg/errors" - - v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" - "github.com/rancher/norman" - "github.com/rancher/norman/objectclient" - "github.com/rancher/norman/pkg/objectset" - "github.com/rancher/norman/types" + v12 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + v1 "github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io/v1" + "github.com/rancher/wrangler/pkg/apply" + "github.com/rancher/wrangler/pkg/merr" + "github.com/rancher/wrangler/pkg/objectset" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" yamlDecoder "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/discovery" - "k8s.io/client-go/rest" ) const ( @@ -35,21 +31,15 @@ const ( startKey = "_start_" ) -func WatchFiles(ctx context.Context, bases ...string) error { - server := norman.GetServer(ctx) - addons := v1.ClientsFrom(ctx).Addon - +func WatchFiles(ctx context.Context, addons v1.AddonController, bases ...string) error { w := &watcher{ addonCache: addons.Cache(), addons: addons, bases: bases, - restConfig: *server.Runtime.LocalConfig, - discovery: server.K8sClient.Discovery(), - clients: map[schema.GroupVersionKind]*objectclient.ObjectClient{}, } addons.Enqueue("", startKey) - addons.Interface().AddHandler(ctx, "addon-start", func(key string, _ *v1.Addon) (runtime.Object, error) { + addons.OnChange(ctx, "addon-start", func(key string, _ *v12.Addon) (*v12.Addon, error) { if key == startKey { go w.start(ctx) } @@ -60,13 +50,10 @@ func WatchFiles(ctx context.Context, bases ...string) error { } type watcher struct { - addonCache v1.AddonClientCache + apply apply.Apply + addonCache v1.AddonCache addons v1.AddonClient bases []string - restConfig rest.Config - discovery discovery.DiscoveryInterface - clients map[schema.GroupVersionKind]*objectclient.ObjectClient - namespaced map[schema.GroupVersionKind]bool } func (w *watcher) start(ctx context.Context) { @@ -93,7 +80,7 @@ func (w *watcher) listFiles(force bool) error { } } - return types.NewErrors(errs...) + return merr.NewErrors(errs...) } func (w *watcher) listFilesIn(base string, force bool) error { @@ -122,7 +109,7 @@ func (w *watcher) listFilesIn(base string, force bool) error { } } - return types.NewErrors(errs...) + return merr.NewErrors(errs...) } func (w *watcher) deploy(path string, compareChecksum bool) error { @@ -148,24 +135,14 @@ func (w *watcher) deploy(path string, compareChecksum bool) error { return err } - clients, err := w.apply(addon, objectSet) - if err != nil { + if err := w.apply.WithOwner(&addon).Apply(objectSet); err != nil { return err } - if w.clients == nil { - w.clients = map[schema.GroupVersionKind]*objectclient.ObjectClient{} - } - addon.Spec.Source = path addon.Spec.Checksum = checksum addon.Status.GVKs = nil - for gvk, client := range clients { - addon.Status.GVKs = append(addon.Status.GVKs, gvk) - w.clients[gvk] = client - } - if addon.UID == "" { _, err := w.addons.Create(&addon) return err @@ -175,55 +152,16 @@ func (w *watcher) deploy(path string, compareChecksum bool) error { return err } -func (w *watcher) addon(name string) (v1.Addon, error) { +func (w *watcher) addon(name string) (v12.Addon, error) { addon, err := w.addonCache.Get(ns, name) if errors.IsNotFound(err) { - addon = v1.NewAddon(ns, name, v1.Addon{}) + addon = v12.NewAddon(ns, name, v12.Addon{}) } else if err != nil { - return v1.Addon{}, err + return v12.Addon{}, err } return *addon, nil } -func (w *watcher) apply(addon v1.Addon, set *objectset.ObjectSet) (map[schema.GroupVersionKind]*objectclient.ObjectClient, error) { - var ( - err error - ) - - op := objectset.NewProcessor(addon.Name) - op.AllowDiscovery(w.discovery, w.restConfig) - - ds := op.NewDesiredSet(nil, set) - - for _, gvk := range addon.Status.GVKs { - var ( - namespaced bool - ) - - client, ok := w.clients[gvk] - if ok { - namespaced = w.namespaced[gvk] - } else { - client, namespaced, err = objectset.NewDiscoveredClient(gvk, w.restConfig, w.discovery) - if err != nil { - return nil, err - } - if w.namespaced == nil { - w.namespaced = map[schema.GroupVersionKind]bool{} - } - w.namespaced[gvk] = namespaced - } - - ds.AddDiscoveredClient(gvk, client, namespaced) - } - - if err := ds.Apply(); err != nil { - return nil, err - } - - return ds.DiscoveredClients(), nil -} - func objectSet(content []byte) (*objectset.ObjectSet, error) { objs, err := yamlToObjects(bytes.NewBuffer(content)) if err != nil { diff --git a/pkg/node/controller.go b/pkg/node/controller.go index c3bf3e2428..eeb8633b58 100644 --- a/pkg/node/controller.go +++ b/pkg/node/controller.go @@ -5,38 +5,39 @@ import ( "strings" "github.com/pkg/errors" - coreclient "github.com/rancher/k3s/types/apis/core/v1" + coreclient "github.com/rancher/k3s/pkg/generated/controllers/core/v1" "github.com/sirupsen/logrus" core "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" ) -func Register(ctx context.Context) error { - clients := coreclient.ClientsFrom(ctx) +func Register(ctx context.Context, configMap coreclient.ConfigMapController, nodes coreclient.NodeController) error { h := &handler{ - configCache: clients.ConfigMap.Cache(), - configClient: clients.ConfigMap, + configCache: configMap.Cache(), + configClient: configMap, } - clients.Node.OnChange(ctx, "node", h.onChange) - clients.Node.OnRemove(ctx, "node", h.onRemove) + nodes.OnChange(ctx, "node", h.onChange) + nodes.OnRemove(ctx, "node", h.onRemove) return nil } type handler struct { - configCache coreclient.ConfigMapClientCache + configCache coreclient.ConfigMapCache configClient coreclient.ConfigMapClient } -func (h *handler) onChange(node *core.Node) (runtime.Object, error) { +func (h *handler) onChange(key string, node *core.Node) (*core.Node, error) { + if node == nil { + return nil, nil + } return h.updateHosts(node, false) } -func (h *handler) onRemove(node *core.Node) (runtime.Object, error) { +func (h *handler) onRemove(key string, node *core.Node) (*core.Node, error) { return h.updateHosts(node, true) } -func (h *handler) updateHosts(node *core.Node, removed bool) (runtime.Object, error) { +func (h *handler) updateHosts(node *core.Node, removed bool) (*core.Node, error) { var ( newHosts string nodeAddress string diff --git a/pkg/proxy/proxy_server.go b/pkg/proxy/proxy_server.go new file mode 100644 index 0000000000..3da29113b6 --- /dev/null +++ b/pkg/proxy/proxy_server.go @@ -0,0 +1,65 @@ +package proxy + +import ( + "crypto/tls" + "crypto/x509" + "net/http" + "net/url" + + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/proxy" + "k8s.io/client-go/rest" +) + +var ( + er = &errorResponder{} +) + +type errorResponder struct { +} + +func (e *errorResponder) Error(w http.ResponseWriter, req *http.Request, err error) { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) +} + +type SimpleProxy struct { + url *url.URL + transport http.RoundTripper + overrideHostHeader bool +} + +func NewSimpleProxy(host string, caData []byte, overrideHostHeader bool) (*SimpleProxy, error) { + hostURL, _, err := rest.DefaultServerURL(host, "", schema.GroupVersion{}, true) + if err != nil { + return nil, err + } + + ht := &http.Transport{} + if len(caData) > 0 { + certPool := x509.NewCertPool() + certPool.AppendCertsFromPEM(caData) + ht.TLSClientConfig = &tls.Config{ + RootCAs: certPool, + } + } + + return &SimpleProxy{ + url: hostURL, + transport: ht, + overrideHostHeader: overrideHostHeader, + }, nil +} + +func (s *SimpleProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + u := *s.url + u.Path = req.URL.Path + u.RawQuery = req.URL.RawQuery + req.URL.Scheme = "https" + req.URL.Host = req.Host + if s.overrideHostHeader { + req.Host = u.Host + } + httpProxy := proxy.NewUpgradeAwareHandler(&u, s.transport, false, false, er) + httpProxy.ServeHTTP(rw, req) +} diff --git a/pkg/rootlessports/controller.go b/pkg/rootlessports/controller.go index cd5eb2acc9..522f5dfe70 100644 --- a/pkg/rootlessports/controller.go +++ b/pkg/rootlessports/controller.go @@ -4,21 +4,20 @@ import ( "context" "time" + coreClients "github.com/rancher/k3s/pkg/generated/controllers/core/v1" "github.com/rancher/k3s/pkg/rootless" - coreClients "github.com/rancher/k3s/types/apis/core/v1" "github.com/rootless-containers/rootlesskit/pkg/api/client" "github.com/rootless-containers/rootlesskit/pkg/port" "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" ) var ( all = "_all_" ) -func Register(ctx context.Context, httpsPort int) error { +func Register(ctx context.Context, serviceController coreClients.ServiceController, httpsPort int) error { var ( err error rootlessClient client.Client @@ -28,7 +27,6 @@ func Register(ctx context.Context, httpsPort int) error { return nil } - coreClients := coreClients.ClientsFrom(ctx) for i := 0; i < 30; i++ { rootlessClient, err = client.New(rootless.Sock) if err == nil { @@ -44,26 +42,26 @@ func Register(ctx context.Context, httpsPort int) error { h := &handler{ rootlessClient: rootlessClient, - serviceClient: coreClients.Service, - serviceCache: coreClients.Service.Cache(), + serviceClient: serviceController, + serviceCache: serviceController.Cache(), httpsPort: httpsPort, ctx: ctx, } - coreClients.Service.Interface().Controller().AddHandler(ctx, "rootlessports", h.serviceChanged) - coreClients.Service.Enqueue("", all) + serviceController.OnChange(ctx, "rootlessports", h.serviceChanged) + serviceController.Enqueue("", all) return nil } type handler struct { rootlessClient client.Client - serviceClient coreClients.ServiceClient - serviceCache coreClients.ServiceClientCache + serviceClient coreClients.ServiceController + serviceCache coreClients.ServiceCache httpsPort int ctx context.Context } -func (h *handler) serviceChanged(key string, svc *v1.Service) (runtime.Object, error) { +func (h *handler) serviceChanged(key string, svc *v1.Service) (*v1.Service, error) { if key != all { h.serviceClient.Enqueue("", all) return svc, nil diff --git a/pkg/server/context.go b/pkg/server/context.go new file mode 100644 index 0000000000..e0a26318d6 --- /dev/null +++ b/pkg/server/context.go @@ -0,0 +1,61 @@ +package server + +import ( + "context" + + "github.com/rancher/k3s/pkg/generated/controllers/apps" + "github.com/rancher/k3s/pkg/generated/controllers/core" + "github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io" + "github.com/rancher/wrangler/pkg/apply" + "github.com/rancher/wrangler/pkg/crd" + "github.com/rancher/wrangler/pkg/start" + "k8s.io/client-go/rest" + "k8s.io/kubernetes/staging/src/k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/staging/src/k8s.io/client-go/tools/clientcmd" +) + +type Context struct { + K3s *k3s.Factory + Apps *apps.Factory + Core *core.Factory + K8s kubernetes.Interface + Apply apply.Apply +} + +func (c *Context) Start(ctx context.Context) error { + return start.All(ctx, 5, c.K3s, c.Apps, c.Core) +} + +func newContext(ctx context.Context, cfg string) (*Context, error) { + restConfig, err := clientcmd.BuildConfigFromFlags("", cfg) + if err != nil { + return nil, err + } + + if err := crds(ctx, restConfig); err != nil { + return nil, err + } + + k8s := kubernetes.NewForConfigOrDie(restConfig) + return &Context{ + K3s: k3s.NewFactoryFromConfigOrDie(restConfig), + K8s: k8s, + Apps: apps.NewFactoryFromConfigOrDie(restConfig), + Core: core.NewFactoryFromConfigOrDie(restConfig), + Apply: apply.New(k8s, apply.NewClientFactory(restConfig)), + }, nil +} + +func crds(ctx context.Context, config *rest.Config) error { + factory, err := crd.NewFactoryFromClient(config) + if err != nil { + return err + } + + factory.BatchCreateCRDs(ctx, crd.NamespacedTypes( + "ListenerConfig.k3s.cattle.io/v1", + "Addon.k3s.cattle.io/v1", + "HelmChart.k3s.cattle.io/v1")...) + + return factory.BatchWait() +} diff --git a/pkg/server/router.go b/pkg/server/router.go index 84c3a739aa..c5a630423b 100644 --- a/pkg/server/router.go +++ b/pkg/server/router.go @@ -15,9 +15,9 @@ import ( "strings" "github.com/gorilla/mux" + certutil "github.com/rancher/dynamiclistener/cert" "github.com/rancher/k3s/pkg/daemons/config" "github.com/rancher/k3s/pkg/openapi" - certutil "github.com/rancher/norman/pkg/cert" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/json" "k8s.io/kubernetes/pkg/master" diff --git a/pkg/server/server.go b/pkg/server/server.go index cde712b8a3..c010a29fd0 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -14,26 +14,19 @@ import ( "time" "github.com/pkg/errors" + "github.com/rancher/dynamiclistener" + "github.com/rancher/k3s/pkg/clientaccess" "github.com/rancher/k3s/pkg/daemons/config" "github.com/rancher/k3s/pkg/daemons/control" "github.com/rancher/k3s/pkg/datadir" "github.com/rancher/k3s/pkg/deploy" - "github.com/rancher/k3s/pkg/helm" "github.com/rancher/k3s/pkg/node" "github.com/rancher/k3s/pkg/rootlessports" "github.com/rancher/k3s/pkg/servicelb" "github.com/rancher/k3s/pkg/static" "github.com/rancher/k3s/pkg/tls" - appsv1 "github.com/rancher/k3s/types/apis/apps/v1" - batchv1 "github.com/rancher/k3s/types/apis/batch/v1" - corev1 "github.com/rancher/k3s/types/apis/core/v1" - v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" - rbacv1 "github.com/rancher/k3s/types/apis/rbac.authorization.k8s.io/v1" - "github.com/rancher/norman" - "github.com/rancher/norman/pkg/clientaccess" - "github.com/rancher/norman/pkg/dynamiclistener" - "github.com/rancher/norman/pkg/resolvehome" - "github.com/rancher/norman/types" + "github.com/rancher/wrangler/pkg/leader" + "github.com/rancher/wrangler/pkg/resolvehome" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/net" ) @@ -44,7 +37,6 @@ func resolveDataDir(dataDir string) (string, error) { } func StartServer(ctx context.Context, config *Config) (string, error) { - if err := setupDataDirAndChdir(&config.ControlConfig); err != nil { return "", err } @@ -57,7 +49,7 @@ func StartServer(ctx context.Context, config *Config) (string, error) { return "", errors.Wrap(err, "starting kubernetes") } - certs, err := startNorman(ctx, config) + certs, err := startWrangler(ctx, config) if err != nil { return "", errors.Wrap(err, "starting tls server") } @@ -76,7 +68,7 @@ func StartServer(ctx context.Context, config *Config) (string, error) { return certs, nil } -func startNorman(ctx context.Context, config *Config) (string, error) { +func startWrangler(ctx context.Context, config *Config) (string, error) { var ( err error tlsServer dynamiclistener.ServerInterface @@ -91,76 +83,90 @@ func startNorman(ctx context.Context, config *Config) (string, error) { return tlsServer.CACert() }) - normanConfig := &norman.Config{ - Name: "k3s", - KubeConfig: controlConfig.Runtime.KubeConfigSystem, - Clients: []norman.ClientFactory{ - v1.Factory, - appsv1.Factory, - corev1.Factory, - batchv1.Factory, - rbacv1.Factory, - }, - Schemas: []*types.Schemas{ - v1.Schemas, - }, - CRDs: map[*types.APIVersion][]string{ - &v1.APIVersion: { - v1.ListenerConfigGroupVersionKind.Kind, - v1.AddonGroupVersionKind.Kind, - v1.HelmChartGroupVersionKind.Kind, - }, - }, - IgnoredKubeConfigEnv: true, - GlobalSetup: func(ctx context.Context) (context.Context, error) { - tlsServer, err = tls.NewServer(ctx, v1.ClientsFrom(ctx).ListenerConfig, *tlsConfig) - return ctx, err - }, - DisableLeaderElection: true, - MasterControllers: []norman.ControllerRegister{ - node.Register, - helm.Register, - func(ctx context.Context) error { - return servicelb.Register(ctx, norman.GetServer(ctx).K8sClient, !config.DisableServiceLB, - config.Rootless) - }, - func(ctx context.Context) error { - dataDir := filepath.Join(controlConfig.DataDir, "static") - return static.Stage(dataDir) - }, - func(ctx context.Context) error { - dataDir := filepath.Join(controlConfig.DataDir, "manifests") - templateVars := map[string]string{"%{CLUSTER_DNS}%": controlConfig.ClusterDNS.String(), "%{CLUSTER_DOMAIN}%": controlConfig.ClusterDomain} - if err := deploy.Stage(dataDir, templateVars, controlConfig.Skips); err != nil { - return err - } - if err := deploy.WatchFiles(ctx, dataDir); err != nil { - return err - } - return nil - }, - func(ctx context.Context) error { - if !config.DisableServiceLB && config.Rootless { - return rootlessports.Register(ctx, config.TLSConfig.HTTPSPort) - } - return nil - }, - }, - } - - if _, _, err = normanConfig.Build(ctx, nil); err != nil { + sc, err := newContext(ctx, controlConfig.Runtime.KubeConfigSystem) + if err != nil { return "", err } - for { - certs, err := tlsServer.CACert() + if err := stageFiles(ctx, sc, controlConfig); err != nil { + return "", err + } + + tlsServer, err = tls.NewServer(ctx, sc.K3s.K3s().V1().ListenerConfig(), *tlsConfig) + if err != nil { + return "", err + } + + if err := sc.Start(ctx); err != nil { + return "", err + } + + certs := "" + for certs == "" { + certs, err = tlsServer.CACert() if err != nil { logrus.Infof("waiting to generate CA certs") time.Sleep(time.Second) continue } - return certs, nil } + + go leader.RunOrDie(ctx, "", "k3s", sc.K8s, func(ctx context.Context) { + if err := masterControllers(ctx, sc, config); err != nil { + panic(err) + } + if err := sc.Start(ctx); err != nil { + panic(err) + } + }) + + return certs, nil +} + +func masterControllers(ctx context.Context, sc *Context, config *Config) error { + if err := node.Register(ctx, sc.Core.Core().V1().ConfigMap(), sc.Core.Core().V1().Node()); err != nil { + return err + } + + //helm.Register + + if err := servicelb.Register(ctx, + sc.K8s, + sc.Apply, + sc.Apps.Apps().V1().DaemonSet(), + sc.Apps.Apps().V1().Deployment(), + sc.Core.Core().V1().Node(), + sc.Core.Core().V1().Pod(), + sc.Core.Core().V1().Service(), + sc.Core.Core().V1().Endpoints(), + !config.DisableServiceLB, config.Rootless); err != nil { + return err + } + + if !config.DisableServiceLB && config.Rootless { + return rootlessports.Register(ctx, sc.Core.Core().V1().Service(), config.TLSConfig.HTTPSPort) + } + + return nil +} + +func stageFiles(ctx context.Context, sc *Context, controlConfig *config.Control) error { + dataDir := filepath.Join(controlConfig.DataDir, "static") + if err := static.Stage(dataDir); err != nil { + return err + } + + dataDir = filepath.Join(controlConfig.DataDir, "manifests") + templateVars := map[string]string{ + "%{CLUSTER_DNS}%": controlConfig.ClusterDNS.String(), + "%{CLUSTER_DOMAIN}%": controlConfig.ClusterDomain, + } + + if err := deploy.Stage(dataDir, templateVars, controlConfig.Skips); err != nil { + return err + } + + return deploy.WatchFiles(ctx, sc.K3s.K3s().V1().Addon(), dataDir) } func HomeKubeConfig(write, rootless bool) (string, error) { @@ -198,7 +204,6 @@ func printTokens(certs, advertiseIP string, tlsConfig *dynamiclistener.UserConfi if len(nodeFile) > 0 { printToken(tlsConfig.HTTPSPort, advertiseIP, "To join node to cluster:", "agent") } - } func writeKubeConfig(certs string, tlsConfig *dynamiclistener.UserConfig, config *Config) { diff --git a/pkg/server/types.go b/pkg/server/types.go index 247bfe0e75..4bccf98fd8 100644 --- a/pkg/server/types.go +++ b/pkg/server/types.go @@ -1,8 +1,8 @@ package server import ( + "github.com/rancher/dynamiclistener" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/norman/pkg/dynamiclistener" ) type Config struct { diff --git a/pkg/servicelb/controller.go b/pkg/servicelb/controller.go index fc91f40f00..6c7fdaeb00 100644 --- a/pkg/servicelb/controller.go +++ b/pkg/servicelb/controller.go @@ -6,12 +6,15 @@ import ( "sort" "strconv" - appclient "github.com/rancher/k3s/types/apis/apps/v1" - coreclient "github.com/rancher/k3s/types/apis/core/v1" - "github.com/rancher/norman/condition" - "github.com/rancher/norman/pkg/changeset" - "github.com/rancher/norman/pkg/objectset" - "github.com/rancher/norman/types/slice" + "github.com/rancher/wrangler/pkg/slice" + + "github.com/rancher/wrangler/pkg/relatedresource" + + appclient "github.com/rancher/k3s/pkg/generated/controllers/apps/v1" + coreclient "github.com/rancher/k3s/pkg/generated/controllers/core/v1" + "github.com/rancher/wrangler/pkg/apply" + "github.com/rancher/wrangler/pkg/condition" + "github.com/rancher/wrangler/pkg/objectset" "github.com/sirupsen/logrus" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" @@ -37,31 +40,37 @@ var ( trueVal = true ) -func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled, rootless bool) error { - clients := coreclient.ClientsFrom(ctx) - appClients := appclient.ClientsFrom(ctx) - +func Register(ctx context.Context, + kubernetes kubernetes.Interface, + apply apply.Apply, + daemonSetController appclient.DaemonSetController, + deployments appclient.DeploymentController, + nodes coreclient.NodeController, + pods coreclient.PodController, + services coreclient.ServiceController, + endpoints coreclient.EndpointsController, + enabled, rootless bool) error { h := &handler{ rootless: rootless, enabled: enabled, - nodeCache: clients.Node.Cache(), - podCache: clients.Pod.Cache(), - deploymentCache: appClients.Deployment.Cache(), - processor: objectset.NewProcessor("svccontroller"). - Client(appClients.DaemonSet), - serviceCache: clients.Service.Cache(), + nodeCache: nodes.Cache(), + podCache: pods.Cache(), + deploymentCache: deployments.Cache(), + processor: apply.WithSetID("svccontroller"). + WithCacheTypes(daemonSetController), + serviceCache: services.Cache(), services: kubernetes.CoreV1(), daemonsets: kubernetes.AppsV1(), deployments: kubernetes.AppsV1(), } - clients.Service.OnChange(ctx, "svccontroller", h.onChangeService) - clients.Node.OnChange(ctx, "svccontroller", h.onChangeNode) - changeset.Watch(ctx, "svccontroller-watcher", + services.OnChange(ctx, "svccontroller", h.onChangeService) + nodes.OnChange(ctx, "svccontroller", h.onChangeNode) + relatedresource.Watch(ctx, "svccontroller-watcher", h.onResourceChange, - clients.Service, - clients.Pod, - clients.Endpoints) + services, + pods, + endpoints) return nil } @@ -69,19 +78,19 @@ func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled, roo type handler struct { rootless bool enabled bool - nodeCache coreclient.NodeClientCache - podCache coreclient.PodClientCache - deploymentCache appclient.DeploymentClientCache - processor *objectset.Processor - serviceCache coreclient.ServiceClientCache + nodeCache coreclient.NodeCache + podCache coreclient.PodCache + deploymentCache appclient.DeploymentCache + processor apply.Apply + serviceCache coreclient.ServiceCache services coregetter.ServicesGetter daemonsets v1getter.DaemonSetsGetter deployments v1getter.DeploymentsGetter } -func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) ([]changeset.Key, error) { +func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) ([]relatedresource.Key, error) { if ep, ok := obj.(*core.Endpoints); ok { - return []changeset.Key{ + return []relatedresource.Key{ { Name: ep.Name, Namespace: ep.Namespace, @@ -103,7 +112,7 @@ func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) ( return nil, nil } - return []changeset.Key{ + return []relatedresource.Key{ { Name: serviceName, Namespace: pod.Namespace, @@ -111,7 +120,11 @@ func (h *handler) onResourceChange(name, namespace string, obj runtime.Object) ( }, nil } -func (h *handler) onChangeService(svc *core.Service) (runtime.Object, error) { +func (h *handler) onChangeService(key string, svc *core.Service) (*core.Service, error) { + if svc == nil { + return nil, nil + } + if svc.Spec.Type != core.ServiceTypeLoadBalancer || svc.Spec.ClusterIP == "" || svc.Spec.ClusterIP == "None" { return svc, nil @@ -126,7 +139,10 @@ func (h *handler) onChangeService(svc *core.Service) (runtime.Object, error) { return nil, err } -func (h *handler) onChangeNode(node *core.Node) (runtime.Object, error) { +func (h *handler) onChangeNode(key string, node *core.Node) (*core.Node, error) { + if node == nil { + return nil, nil + } if _, ok := node.Labels[daemonsetNodeLabel]; !ok { return node, nil } @@ -195,7 +211,7 @@ func (h *handler) podIPs(pods []*core.Pod) ([]string, error) { continue } - node, err := h.nodeCache.Get("", pod.Spec.NodeName) + node, err := h.nodeCache.Get(pod.Spec.NodeName) if errors.IsNotFound(err) { continue } else if err != nil { @@ -227,7 +243,7 @@ func (h *handler) deployPod(svc *core.Service) error { } objs := objectset.NewObjectSet() if !h.enabled { - return h.processor.NewDesiredSet(svc, objs).Apply() + return h.processor.WithOwner(svc).Apply(objs) } ds, err := h.newDaemonSet(svc) @@ -237,7 +253,7 @@ func (h *handler) deployPod(svc *core.Service) error { if ds != nil { objs.Add(ds) } - return h.processor.NewDesiredSet(svc, objs).Apply() + return h.processor.WithOwner(svc).Apply(objs) } func (h *handler) newDaemonSet(svc *core.Service) (*apps.DaemonSet, error) { @@ -335,7 +351,7 @@ func (h *handler) newDaemonSet(svc *core.Service) (*apps.DaemonSet, error) { if err != nil { return nil, err } - nodesWithLabel, err := h.nodeCache.List("", selector) + nodesWithLabel, err := h.nodeCache.List(selector) if err != nil { return nil, err } diff --git a/pkg/tls/storage.go b/pkg/tls/storage.go index 95cad94f07..4a1407ab55 100644 --- a/pkg/tls/storage.go +++ b/pkg/tls/storage.go @@ -3,11 +3,11 @@ package tls import ( "context" - v1 "github.com/rancher/k3s/types/apis/k3s.cattle.io/v1" - "github.com/rancher/norman/pkg/dynamiclistener" + "github.com/rancher/dynamiclistener" + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + k3sclient "github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" ) const ( @@ -15,14 +15,21 @@ const ( name = "tls-config" ) -func NewServer(ctx context.Context, listenerClient v1.ListenerConfigClient, config dynamiclistener.UserConfig) (dynamiclistener.ServerInterface, error) { +func NewServer(ctx context.Context, listenerConfigs k3sclient.ListenerConfigController, config dynamiclistener.UserConfig) (dynamiclistener.ServerInterface, error) { storage := &listenerConfigStorage{ - client: listenerClient, - cache: listenerClient.Cache(), + client: listenerConfigs, + cache: listenerConfigs.Cache(), } server, err := dynamiclistener.NewServer(storage, config) - listenerClient.OnChange(ctx, "listen-config", func(obj *v1.ListenerConfig) (runtime.Object, error) { + if err != nil { + return nil, err + } + + listenerConfigs.OnChange(ctx, "listen-config", func(key string, obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { + if obj == nil { + return nil, nil + } return obj, server.Update(fromStorage(obj)) }) @@ -30,8 +37,8 @@ func NewServer(ctx context.Context, listenerClient v1.ListenerConfigClient, conf } type listenerConfigStorage struct { - cache v1.ListenerConfigClientCache - client v1.ListenerConfigClient + cache k3sclient.ListenerConfigCache + client k3sclient.ListenerConfigClient } func (l *listenerConfigStorage) Set(config *dynamiclistener.ListenerStatus) (*dynamiclistener.ListenerStatus, error) { @@ -65,6 +72,9 @@ func (l *listenerConfigStorage) Get() (*dynamiclistener.ListenerStatus, error) { if errors.IsNotFound(err) { obj, err = l.client.Get(ns, name, metav1.GetOptions{}) } + if errors.IsNotFound(err) { + return &dynamiclistener.ListenerStatus{}, nil + } return fromStorage(obj), err } diff --git a/scripts/boilerplate.go.txt b/scripts/boilerplate.go.txt new file mode 100644 index 0000000000..b7c650da47 --- /dev/null +++ b/scripts/boilerplate.go.txt @@ -0,0 +1,16 @@ +/* +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. +*/ + From d94a346a1eb8fe16cc64e3c476f3093e0b04557c Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Sat, 25 May 2019 23:42:09 -0700 Subject: [PATCH 3/4] Switch to wrangler-api and helm-controller --- manifests/traefik.yaml | 2 +- pkg/apis/k3s.cattle.io/v1/types.go | 25 ----------------- pkg/codegen/main.go | 43 ------------------------------ pkg/deploy/controller.go | 3 ++- pkg/node/controller.go | 2 +- pkg/rootlessports/controller.go | 2 +- pkg/server/context.go | 17 +++++++++--- pkg/server/server.go | 9 +++++-- pkg/servicelb/controller.go | 10 +++---- 9 files changed, 29 insertions(+), 84 deletions(-) diff --git a/manifests/traefik.yaml b/manifests/traefik.yaml index b1146a169a..fa2d56641f 100644 --- a/manifests/traefik.yaml +++ b/manifests/traefik.yaml @@ -1,4 +1,4 @@ -apiVersion: k3s.cattle.io/v1 +apiVersion: helm.cattle.io/v1 kind: HelmChart metadata: name: traefik diff --git a/pkg/apis/k3s.cattle.io/v1/types.go b/pkg/apis/k3s.cattle.io/v1/types.go index 87f3971d09..50353e7470 100644 --- a/pkg/apis/k3s.cattle.io/v1/types.go +++ b/pkg/apis/k3s.cattle.io/v1/types.go @@ -4,7 +4,6 @@ import ( "github.com/rancher/dynamiclistener" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/intstr" ) // +genclient @@ -36,27 +35,3 @@ type AddonSpec struct { type AddonStatus struct { GVKs []schema.GroupVersionKind `json:"gvks,omitempty"` } - -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -type HelmChart struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec HelmChartSpec `json:"spec,omitempty"` - Status HelmChartStatus `json:"status,omitempty"` -} - -type HelmChartSpec struct { - TargetNamespace string `json:"targetNamespace,omitempty"` - Chart string `json:"chart,omitempty"` - Version string `json:"version,omitempty"` - Repo string `json:"repo,omitempty"` - Set map[string]intstr.IntOrString `json:"set,omitempty"` - ValuesContent string `json:"valuesContent,omitempty"` -} - -type HelmChartStatus struct { - JobName string `json:"jobName,omitempty"` -} diff --git a/pkg/codegen/main.go b/pkg/codegen/main.go index f1d8261657..9c6b8a3edf 100644 --- a/pkg/codegen/main.go +++ b/pkg/codegen/main.go @@ -8,10 +8,6 @@ import ( controllergen "github.com/rancher/wrangler/pkg/controller-gen" "github.com/rancher/wrangler/pkg/controller-gen/args" "github.com/sirupsen/logrus" - appsv1 "k8s.io/api/apps/v1" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" ) var ( @@ -94,48 +90,9 @@ func main() { Types: []interface{}{ v1.ListenerConfig{}, v1.Addon{}, - v1.HelmChart{}, }, GenerateTypes: true, }, - "": { - Types: []interface{}{ - corev1.ServiceAccount{}, - corev1.Endpoints{}, - corev1.Service{}, - corev1.Pod{}, - corev1.ConfigMap{}, - corev1.Node{}, - }, - InformersPackage: "k8s.io/client-go/informers", - ClientSetPackage: "k8s.io/client-go/kubernetes", - ListersPackage: "k8s.io/client-go/listers", - }, - "apps": { - Types: []interface{}{ - appsv1.Deployment{}, - appsv1.DaemonSet{}, - }, - InformersPackage: "k8s.io/client-go/informers", - ClientSetPackage: "k8s.io/client-go/kubernetes", - ListersPackage: "k8s.io/client-go/listers", - }, - "batch": { - Types: []interface{}{ - batchv1.Job{}, - }, - InformersPackage: "k8s.io/client-go/informers", - ClientSetPackage: "k8s.io/client-go/kubernetes", - ListersPackage: "k8s.io/client-go/listers", - }, - "rbac": { - Types: []interface{}{ - rbacv1.ClusterRoleBinding{}, - }, - InformersPackage: "k8s.io/client-go/informers", - ClientSetPackage: "k8s.io/client-go/kubernetes", - ListersPackage: "k8s.io/client-go/listers", - }, }, }) } diff --git a/pkg/deploy/controller.go b/pkg/deploy/controller.go index 6134e9d362..261ab33de8 100644 --- a/pkg/deploy/controller.go +++ b/pkg/deploy/controller.go @@ -31,8 +31,9 @@ const ( startKey = "_start_" ) -func WatchFiles(ctx context.Context, addons v1.AddonController, bases ...string) error { +func WatchFiles(ctx context.Context, apply apply.Apply, addons v1.AddonController, bases ...string) error { w := &watcher{ + apply: apply, addonCache: addons.Cache(), addons: addons, bases: bases, diff --git a/pkg/node/controller.go b/pkg/node/controller.go index eeb8633b58..b4f00e48b6 100644 --- a/pkg/node/controller.go +++ b/pkg/node/controller.go @@ -5,7 +5,7 @@ import ( "strings" "github.com/pkg/errors" - coreclient "github.com/rancher/k3s/pkg/generated/controllers/core/v1" + coreclient "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" "github.com/sirupsen/logrus" core "k8s.io/api/core/v1" ) diff --git a/pkg/rootlessports/controller.go b/pkg/rootlessports/controller.go index 522f5dfe70..e5a4a7f7af 100644 --- a/pkg/rootlessports/controller.go +++ b/pkg/rootlessports/controller.go @@ -4,8 +4,8 @@ import ( "context" "time" - coreClients "github.com/rancher/k3s/pkg/generated/controllers/core/v1" "github.com/rancher/k3s/pkg/rootless" + coreClients "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" "github.com/rootless-containers/rootlesskit/pkg/api/client" "github.com/rootless-containers/rootlesskit/pkg/port" "github.com/sirupsen/logrus" diff --git a/pkg/server/context.go b/pkg/server/context.go index e0a26318d6..4f33b9aaca 100644 --- a/pkg/server/context.go +++ b/pkg/server/context.go @@ -3,9 +3,12 @@ package server import ( "context" - "github.com/rancher/k3s/pkg/generated/controllers/apps" - "github.com/rancher/k3s/pkg/generated/controllers/core" + "github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io" "github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io" + "github.com/rancher/wrangler-api/pkg/generated/controllers/apps" + "github.com/rancher/wrangler-api/pkg/generated/controllers/batch" + "github.com/rancher/wrangler-api/pkg/generated/controllers/core" + "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac" "github.com/rancher/wrangler/pkg/apply" "github.com/rancher/wrangler/pkg/crd" "github.com/rancher/wrangler/pkg/start" @@ -16,14 +19,17 @@ import ( type Context struct { K3s *k3s.Factory + Helm *helm.Factory + Batch *batch.Factory Apps *apps.Factory + Auth *rbac.Factory Core *core.Factory K8s kubernetes.Interface Apply apply.Apply } func (c *Context) Start(ctx context.Context) error { - return start.All(ctx, 5, c.K3s, c.Apps, c.Core) + return start.All(ctx, 5, c.K3s, c.Helm, c.Apps, c.Auth, c.Batch, c.Core) } func newContext(ctx context.Context, cfg string) (*Context, error) { @@ -39,8 +45,11 @@ func newContext(ctx context.Context, cfg string) (*Context, error) { k8s := kubernetes.NewForConfigOrDie(restConfig) return &Context{ K3s: k3s.NewFactoryFromConfigOrDie(restConfig), + Helm: helm.NewFactoryFromConfigOrDie(restConfig), K8s: k8s, + Auth: rbac.NewFactoryFromConfigOrDie(restConfig), Apps: apps.NewFactoryFromConfigOrDie(restConfig), + Batch: batch.NewFactoryFromConfigOrDie(restConfig), Core: core.NewFactoryFromConfigOrDie(restConfig), Apply: apply.New(k8s, apply.NewClientFactory(restConfig)), }, nil @@ -55,7 +64,7 @@ func crds(ctx context.Context, config *rest.Config) error { factory.BatchCreateCRDs(ctx, crd.NamespacedTypes( "ListenerConfig.k3s.cattle.io/v1", "Addon.k3s.cattle.io/v1", - "HelmChart.k3s.cattle.io/v1")...) + "HelmChart.helm.cattle.io/v1")...) return factory.BatchWait() } diff --git a/pkg/server/server.go b/pkg/server/server.go index c010a29fd0..09ddb41176 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -15,6 +15,7 @@ import ( "github.com/pkg/errors" "github.com/rancher/dynamiclistener" + "github.com/rancher/helm-controller/pkg/helm" "github.com/rancher/k3s/pkg/clientaccess" "github.com/rancher/k3s/pkg/daemons/config" "github.com/rancher/k3s/pkg/daemons/control" @@ -128,7 +129,11 @@ func masterControllers(ctx context.Context, sc *Context, config *Config) error { return err } - //helm.Register + helm.Register(ctx, sc.Apply, + sc.Helm.Helm().V1().HelmChart(), + sc.Batch.Batch().V1().Job(), + sc.Auth.Rbac().V1().ClusterRoleBinding(), + sc.Core.Core().V1().ServiceAccount()) if err := servicelb.Register(ctx, sc.K8s, @@ -166,7 +171,7 @@ func stageFiles(ctx context.Context, sc *Context, controlConfig *config.Control) return err } - return deploy.WatchFiles(ctx, sc.K3s.K3s().V1().Addon(), dataDir) + return deploy.WatchFiles(ctx, sc.Apply, sc.K3s.K3s().V1().Addon(), dataDir) } func HomeKubeConfig(write, rootless bool) (string, error) { diff --git a/pkg/servicelb/controller.go b/pkg/servicelb/controller.go index 6c7fdaeb00..11f9d91c93 100644 --- a/pkg/servicelb/controller.go +++ b/pkg/servicelb/controller.go @@ -6,15 +6,13 @@ import ( "sort" "strconv" - "github.com/rancher/wrangler/pkg/slice" - - "github.com/rancher/wrangler/pkg/relatedresource" - - appclient "github.com/rancher/k3s/pkg/generated/controllers/apps/v1" - coreclient "github.com/rancher/k3s/pkg/generated/controllers/core/v1" + appclient "github.com/rancher/wrangler-api/pkg/generated/controllers/apps/v1" + coreclient "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" "github.com/rancher/wrangler/pkg/apply" "github.com/rancher/wrangler/pkg/condition" "github.com/rancher/wrangler/pkg/objectset" + "github.com/rancher/wrangler/pkg/relatedresource" + "github.com/rancher/wrangler/pkg/slice" "github.com/sirupsen/logrus" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" From 7ee554013a5c0fd693084ab081767f26c750739a Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 9 May 2019 15:06:33 -0700 Subject: [PATCH 4/4] Update generated code --- .../k3s.cattle.io/v1/zz_generated_deepcopy.go | 184 +++++++++++++ .../v1/zz_generated_list_types.go | 59 +++++ .../k3s.cattle.io/v1/zz_generated_register.go | 58 +++++ .../k3s.cattle.io/zz_generated_register.go | 24 ++ pkg/deploy/zz_generated_bindata.go | 2 +- .../clientset/versioned/clientset.go | 90 +++++++ pkg/generated/clientset/versioned/doc.go | 20 ++ .../versioned/fake/clientset_generated.go | 77 ++++++ pkg/generated/clientset/versioned/fake/doc.go | 20 ++ .../clientset/versioned/fake/register.go | 56 ++++ .../clientset/versioned/scheme/doc.go | 20 ++ .../clientset/versioned/scheme/register.go | 56 ++++ .../versioned/typed/k3s.cattle.io/v1/addon.go | 191 ++++++++++++++ .../versioned/typed/k3s.cattle.io/v1/doc.go | 20 ++ .../typed/k3s.cattle.io/v1/fake/doc.go | 20 ++ .../typed/k3s.cattle.io/v1/fake/fake_addon.go | 140 ++++++++++ .../v1/fake/fake_k3s.cattle.io_client.go | 44 ++++ .../v1/fake/fake_listenerconfig.go | 140 ++++++++++ .../k3s.cattle.io/v1/generated_expansion.go | 23 ++ .../k3s.cattle.io/v1/k3s.cattle.io_client.go | 95 +++++++ .../typed/k3s.cattle.io/v1/listenerconfig.go | 191 ++++++++++++++ .../controllers/k3s.cattle.io/factory.go | 101 ++++++++ .../controllers/k3s.cattle.io/interface.go | 50 ++++ .../controllers/k3s.cattle.io/v1/addon.go | 242 ++++++++++++++++++ .../controllers/k3s.cattle.io/v1/interface.go | 53 ++++ .../k3s.cattle.io/v1/listenerconfig.go | 242 ++++++++++++++++++ .../informers/externalversions/factory.go | 180 +++++++++++++ .../informers/externalversions/generic.go | 64 +++++ .../internalinterfaces/factory_interfaces.go | 40 +++ .../k3s.cattle.io/interface.go | 46 ++++ .../k3s.cattle.io/v1/addon.go | 89 +++++++ .../k3s.cattle.io/v1/interface.go | 52 ++++ .../k3s.cattle.io/v1/listenerconfig.go | 89 +++++++ .../listers/k3s.cattle.io/v1/addon.go | 94 +++++++ .../k3s.cattle.io/v1/expansion_generated.go | 35 +++ .../k3s.cattle.io/v1/listenerconfig.go | 94 +++++++ 36 files changed, 3000 insertions(+), 1 deletion(-) create mode 100644 pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go create mode 100644 pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go create mode 100644 pkg/apis/k3s.cattle.io/v1/zz_generated_register.go create mode 100644 pkg/apis/k3s.cattle.io/zz_generated_register.go create mode 100644 pkg/generated/clientset/versioned/clientset.go create mode 100644 pkg/generated/clientset/versioned/doc.go create mode 100644 pkg/generated/clientset/versioned/fake/clientset_generated.go create mode 100644 pkg/generated/clientset/versioned/fake/doc.go create mode 100644 pkg/generated/clientset/versioned/fake/register.go create mode 100644 pkg/generated/clientset/versioned/scheme/doc.go create mode 100644 pkg/generated/clientset/versioned/scheme/register.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/addon.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/doc.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/doc.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_addon.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go create mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go create mode 100644 pkg/generated/controllers/k3s.cattle.io/factory.go create mode 100644 pkg/generated/controllers/k3s.cattle.io/interface.go create mode 100644 pkg/generated/controllers/k3s.cattle.io/v1/addon.go create mode 100644 pkg/generated/controllers/k3s.cattle.io/v1/interface.go create mode 100644 pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go create mode 100644 pkg/generated/informers/externalversions/factory.go create mode 100644 pkg/generated/informers/externalversions/generic.go create mode 100644 pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 pkg/generated/informers/externalversions/k3s.cattle.io/interface.go create mode 100644 pkg/generated/informers/externalversions/k3s.cattle.io/v1/addon.go create mode 100644 pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go create mode 100644 pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go create mode 100644 pkg/generated/listers/k3s.cattle.io/v1/addon.go create mode 100644 pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go create mode 100644 pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go new file mode 100644 index 0000000000..5a82bcfc2c --- /dev/null +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go @@ -0,0 +1,184 @@ +// +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 main. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Addon) DeepCopyInto(out *Addon) { + *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 Addon. +func (in *Addon) DeepCopy() *Addon { + if in == nil { + return nil + } + out := new(Addon) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Addon) 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 *AddonList) DeepCopyInto(out *AddonList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Addon, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonList. +func (in *AddonList) DeepCopy() *AddonList { + if in == nil { + return nil + } + out := new(AddonList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddonList) 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 *AddonSpec) DeepCopyInto(out *AddonSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonSpec. +func (in *AddonSpec) DeepCopy() *AddonSpec { + if in == nil { + return nil + } + out := new(AddonSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonStatus) DeepCopyInto(out *AddonStatus) { + *out = *in + if in.GVKs != nil { + in, out := &in.GVKs, &out.GVKs + *out = make([]schema.GroupVersionKind, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonStatus. +func (in *AddonStatus) DeepCopy() *AddonStatus { + if in == nil { + return nil + } + out := new(AddonStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerConfig) DeepCopyInto(out *ListenerConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfig. +func (in *ListenerConfig) DeepCopy() *ListenerConfig { + if in == nil { + return nil + } + out := new(ListenerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ListenerConfig) 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 *ListenerConfigList) DeepCopyInto(out *ListenerConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ListenerConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfigList. +func (in *ListenerConfigList) DeepCopy() *ListenerConfigList { + if in == nil { + return nil + } + out := new(ListenerConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ListenerConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go new file mode 100644 index 0000000000..cb33f020dd --- /dev/null +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go @@ -0,0 +1,59 @@ +/* +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 main. DO NOT EDIT. + +// +k8s:deepcopy-gen=package +// +groupName=k3s.cattle.io +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ListenerConfigList is a list of ListenerConfig resources +type ListenerConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []ListenerConfig `json:"items"` +} + +func NewListenerConfig(namespace, name string, obj ListenerConfig) *ListenerConfig { + obj.APIVersion, obj.Kind = SchemeGroupVersion.WithKind("ListenerConfig").ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddonList is a list of Addon resources +type AddonList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Addon `json:"items"` +} + +func NewAddon(namespace, name string, obj Addon) *Addon { + obj.APIVersion, obj.Kind = SchemeGroupVersion.WithKind("Addon").ToAPIVersionAndKind() + obj.Name = name + obj.Namespace = namespace + return &obj +} diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go new file mode 100644 index 0000000000..124c47af97 --- /dev/null +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go @@ -0,0 +1,58 @@ +/* +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 main. DO NOT EDIT. + +// +k8s:deepcopy-gen=package +// +groupName=k3s.cattle.io +package v1 + +import ( + k3s "github.com/rancher/k3s/pkg/apis/k3s.cattle.io" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: k3s.GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns back 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 = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Addon{}, + &AddonList{}, + &ListenerConfig{}, + &ListenerConfigList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/k3s.cattle.io/zz_generated_register.go b/pkg/apis/k3s.cattle.io/zz_generated_register.go new file mode 100644 index 0000000000..ffbf9ef6b4 --- /dev/null +++ b/pkg/apis/k3s.cattle.io/zz_generated_register.go @@ -0,0 +1,24 @@ +/* +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 main. DO NOT EDIT. + +package k3s + +const ( + // Package-wide consts from generator "zz_generated_register". + GroupName = "k3s.cattle.io" +) diff --git a/pkg/deploy/zz_generated_bindata.go b/pkg/deploy/zz_generated_bindata.go index e9876bb5b4..0fad490378 100644 --- a/pkg/deploy/zz_generated_bindata.go +++ b/pkg/deploy/zz_generated_bindata.go @@ -89,7 +89,7 @@ func corednsYaml() (*asset, error) { return a, nil } -var _traefikYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\xcc\x4d\x4b\xc4\x30\x10\xc6\xf1\x7b\x3e\xc5\xb0\xb0\xc7\x4d\x5c\x14\x0f\x73\x53\x29\x28\x82\x88\x6f\x57\x99\xa6\xa3\x0d\x79\x69\xc8\x4c\x05\x15\xbf\xbb\xb4\xf4\xb6\xc7\x99\xe7\xcf\x8f\x6a\x78\xe3\x26\x61\x2a\x08\xf1\x5c\xac\x27\xd5\xc4\x36\x4c\xee\xeb\x68\x62\x28\x03\xc2\x2d\xa7\x7c\x33\x52\x53\x93\x59\x69\x20\x25\x34\x00\x85\x32\x23\x68\x23\xfe\x08\x71\xbb\xa5\x92\x67\x84\x38\xf7\x7c\x90\x6f\x51\xce\x46\x2a\xfb\x25\xf7\x0b\x80\x30\xaa\x56\x41\xe7\xf6\xbf\xf7\xaf\xd7\xdd\xd3\x43\xf7\xd2\x3d\xbf\x5f\x3d\xde\xfd\xed\x9d\x28\x69\xf0\x6e\x0d\xc5\x6d\xf0\xe1\x68\x2f\x2f\xec\x99\xd5\xcf\x1f\x03\x20\xac\x8b\x05\xd0\x7a\xf2\x96\x0b\xf5\x89\x07\x84\x9d\xb6\x99\x77\xeb\x20\x92\x4e\xfe\xff\x01\x00\x00\xff\xff\xf0\x93\x36\xe7\xe3\x00\x00\x00") +var _traefikYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\xcc\x4d\x4b\xc7\x30\x0c\xc7\xf1\x7b\x5f\x45\xf8\xc3\x8e\x6b\x1d\x88\x87\xdc\x54\x06\x8a\x20\xe2\xd3\x55\xb2\x2e\xba\xb2\xb6\x2b\x4d\x26\xa8\xf8\xde\x65\x63\x37\x8f\xc9\xef\xcb\x87\x4a\x78\xe5\x2a\x61\xc9\x08\x13\xc7\x64\x3d\xa9\x46\xb6\x61\x71\x9f\x9d\x99\x43\x1e\x11\x6e\x38\xa6\xeb\x89\xaa\x9a\xc4\x4a\x23\x29\xa1\x01\xc8\x94\x18\x41\x2b\xf1\x7b\x98\x8f\x5b\x0a\x79\x46\x98\xd7\x81\x5b\xf9\x12\xe5\x64\xa4\xb0\xdf\x72\xbf\x01\x08\x93\x6a\x11\x74\xae\xf9\xb9\x7b\xb9\xea\x1f\xef\xfb\xe7\xfe\xe9\xed\xf2\xe1\xf6\xb7\x71\xa2\xa4\xc1\xbb\x3d\x14\x77\xc0\x6d\x67\x2f\xce\xed\x99\xd5\x8f\x6f\x03\x20\xac\x9b\x05\x50\x07\xf2\x96\x33\x0d\x91\x47\x84\x93\xd6\x95\x4f\xfb\x20\x12\xff\xfd\xff\x02\x00\x00\xff\xff\x29\xa0\xaa\xfe\xe4\x00\x00\x00") func traefikYamlBytes() ([]byte, error) { return bindataRead( diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go new file mode 100644 index 0000000000..4786bf5b7c --- /dev/null +++ b/pkg/generated/clientset/versioned/clientset.go @@ -0,0 +1,90 @@ +/* +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 main. DO NOT EDIT. + +package versioned + +import ( + k3sv1 "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + K3sV1() k3sv1.K3sV1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + k3sV1 *k3sv1.K3sV1Client +} + +// K3sV1 retrieves the K3sV1Client +func (c *Clientset) K3sV1() k3sv1.K3sV1Interface { + return c.k3sV1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.k3sV1, err = k3sv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.k3sV1 = k3sv1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.k3sV1 = k3sv1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/pkg/generated/clientset/versioned/doc.go b/pkg/generated/clientset/versioned/doc.go new file mode 100644 index 0000000000..78439a3c14 --- /dev/null +++ b/pkg/generated/clientset/versioned/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/pkg/generated/clientset/versioned/fake/clientset_generated.go b/pkg/generated/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 0000000000..5950e4e8ee --- /dev/null +++ b/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,77 @@ +/* +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 main. DO NOT EDIT. + +package fake + +import ( + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned" + k3sv1 "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + fakek3sv1 "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +var _ clientset.Interface = &Clientset{} + +// K3sV1 retrieves the K3sV1Client +func (c *Clientset) K3sV1() k3sv1.K3sV1Interface { + return &fakek3sv1.FakeK3sV1{Fake: &c.Fake} +} diff --git a/pkg/generated/clientset/versioned/fake/doc.go b/pkg/generated/clientset/versioned/fake/doc.go new file mode 100644 index 0000000000..8aaca0c7c5 --- /dev/null +++ b/pkg/generated/clientset/versioned/fake/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go new file mode 100644 index 0000000000..9cf6cdf008 --- /dev/null +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -0,0 +1,56 @@ +/* +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 main. DO NOT EDIT. + +package fake + +import ( + k3sv1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) +var parameterCodec = runtime.NewParameterCodec(scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + k3sv1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/pkg/generated/clientset/versioned/scheme/doc.go b/pkg/generated/clientset/versioned/scheme/doc.go new file mode 100644 index 0000000000..6bd144ec29 --- /dev/null +++ b/pkg/generated/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go new file mode 100644 index 0000000000..429832fa15 --- /dev/null +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -0,0 +1,56 @@ +/* +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 main. DO NOT EDIT. + +package scheme + +import ( + k3sv1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + k3sv1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/addon.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/addon.go new file mode 100644 index 0000000000..9077086067 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/addon.go @@ -0,0 +1,191 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + scheme "github.com/rancher/k3s/pkg/generated/clientset/versioned/scheme" + metav1 "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" +) + +// AddonsGetter has a method to return a AddonInterface. +// A group's client should implement this interface. +type AddonsGetter interface { + Addons(namespace string) AddonInterface +} + +// AddonInterface has methods to work with Addon resources. +type AddonInterface interface { + Create(*v1.Addon) (*v1.Addon, error) + Update(*v1.Addon) (*v1.Addon, error) + UpdateStatus(*v1.Addon) (*v1.Addon, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.Addon, error) + List(opts metav1.ListOptions) (*v1.AddonList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Addon, err error) + AddonExpansion +} + +// addons implements AddonInterface +type addons struct { + client rest.Interface + ns string +} + +// newAddons returns a Addons +func newAddons(c *K3sV1Client, namespace string) *addons { + return &addons{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the addon, and returns the corresponding addon object, and an error if there is any. +func (c *addons) Get(name string, options metav1.GetOptions) (result *v1.Addon, err error) { + result = &v1.Addon{} + err = c.client.Get(). + Namespace(c.ns). + Resource("addons"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Addons that match those selectors. +func (c *addons) List(opts metav1.ListOptions) (result *v1.AddonList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.AddonList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("addons"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested addons. +func (c *addons) Watch(opts metav1.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("addons"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a addon and creates it. Returns the server's representation of the addon, and an error, if there is any. +func (c *addons) Create(addon *v1.Addon) (result *v1.Addon, err error) { + result = &v1.Addon{} + err = c.client.Post(). + Namespace(c.ns). + Resource("addons"). + Body(addon). + Do(). + Into(result) + return +} + +// Update takes the representation of a addon and updates it. Returns the server's representation of the addon, and an error, if there is any. +func (c *addons) Update(addon *v1.Addon) (result *v1.Addon, err error) { + result = &v1.Addon{} + err = c.client.Put(). + Namespace(c.ns). + Resource("addons"). + Name(addon.Name). + Body(addon). + 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 *addons) UpdateStatus(addon *v1.Addon) (result *v1.Addon, err error) { + result = &v1.Addon{} + err = c.client.Put(). + Namespace(c.ns). + Resource("addons"). + Name(addon.Name). + SubResource("status"). + Body(addon). + Do(). + Into(result) + return +} + +// Delete takes name of the addon and deletes it. Returns an error if one occurs. +func (c *addons) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("addons"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *addons) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.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("addons"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched addon. +func (c *addons) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Addon, err error) { + result = &v1.Addon{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("addons"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/doc.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/doc.go new file mode 100644 index 0000000000..761c8c49d4 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/doc.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/doc.go new file mode 100644 index 0000000000..ccad4cbc1c --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/doc.go @@ -0,0 +1,20 @@ +/* +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 main. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_addon.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_addon.go new file mode 100644 index 0000000000..0d33a75292 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_addon.go @@ -0,0 +1,140 @@ +/* +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 main. DO NOT EDIT. + +package fake + +import ( + k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + 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" +) + +// FakeAddons implements AddonInterface +type FakeAddons struct { + Fake *FakeK3sV1 + ns string +} + +var addonsResource = schema.GroupVersionResource{Group: "k3s.cattle.io", Version: "v1", Resource: "addons"} + +var addonsKind = schema.GroupVersionKind{Group: "k3s.cattle.io", Version: "v1", Kind: "Addon"} + +// Get takes name of the addon, and returns the corresponding addon object, and an error if there is any. +func (c *FakeAddons) Get(name string, options v1.GetOptions) (result *k3scattleiov1.Addon, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(addonsResource, c.ns, name), &k3scattleiov1.Addon{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.Addon), err +} + +// List takes label and field selectors, and returns the list of Addons that match those selectors. +func (c *FakeAddons) List(opts v1.ListOptions) (result *k3scattleiov1.AddonList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(addonsResource, addonsKind, c.ns, opts), &k3scattleiov1.AddonList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &k3scattleiov1.AddonList{ListMeta: obj.(*k3scattleiov1.AddonList).ListMeta} + for _, item := range obj.(*k3scattleiov1.AddonList).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 addons. +func (c *FakeAddons) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(addonsResource, c.ns, opts)) + +} + +// Create takes the representation of a addon and creates it. Returns the server's representation of the addon, and an error, if there is any. +func (c *FakeAddons) Create(addon *k3scattleiov1.Addon) (result *k3scattleiov1.Addon, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(addonsResource, c.ns, addon), &k3scattleiov1.Addon{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.Addon), err +} + +// Update takes the representation of a addon and updates it. Returns the server's representation of the addon, and an error, if there is any. +func (c *FakeAddons) Update(addon *k3scattleiov1.Addon) (result *k3scattleiov1.Addon, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(addonsResource, c.ns, addon), &k3scattleiov1.Addon{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.Addon), 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 *FakeAddons) UpdateStatus(addon *k3scattleiov1.Addon) (*k3scattleiov1.Addon, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(addonsResource, "status", c.ns, addon), &k3scattleiov1.Addon{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.Addon), err +} + +// Delete takes name of the addon and deletes it. Returns an error if one occurs. +func (c *FakeAddons) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(addonsResource, c.ns, name), &k3scattleiov1.Addon{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeAddons) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(addonsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &k3scattleiov1.AddonList{}) + return err +} + +// Patch applies the patch and returns the patched addon. +func (c *FakeAddons) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *k3scattleiov1.Addon, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(addonsResource, c.ns, name, pt, data, subresources...), &k3scattleiov1.Addon{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.Addon), err +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go new file mode 100644 index 0000000000..5ac52eb8cd --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go @@ -0,0 +1,44 @@ +/* +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 main. DO NOT EDIT. + +package fake + +import ( + v1 "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeK3sV1 struct { + *testing.Fake +} + +func (c *FakeK3sV1) Addons(namespace string) v1.AddonInterface { + return &FakeAddons{c, namespace} +} + +func (c *FakeK3sV1) ListenerConfigs(namespace string) v1.ListenerConfigInterface { + return &FakeListenerConfigs{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeK3sV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go new file mode 100644 index 0000000000..98d6660b6b --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go @@ -0,0 +1,140 @@ +/* +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 main. DO NOT EDIT. + +package fake + +import ( + k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + 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" +) + +// FakeListenerConfigs implements ListenerConfigInterface +type FakeListenerConfigs struct { + Fake *FakeK3sV1 + ns string +} + +var listenerconfigsResource = schema.GroupVersionResource{Group: "k3s.cattle.io", Version: "v1", Resource: "listenerconfigs"} + +var listenerconfigsKind = schema.GroupVersionKind{Group: "k3s.cattle.io", Version: "v1", Kind: "ListenerConfig"} + +// Get takes name of the listenerConfig, and returns the corresponding listenerConfig object, and an error if there is any. +func (c *FakeListenerConfigs) Get(name string, options v1.GetOptions) (result *k3scattleiov1.ListenerConfig, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(listenerconfigsResource, c.ns, name), &k3scattleiov1.ListenerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.ListenerConfig), err +} + +// List takes label and field selectors, and returns the list of ListenerConfigs that match those selectors. +func (c *FakeListenerConfigs) List(opts v1.ListOptions) (result *k3scattleiov1.ListenerConfigList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(listenerconfigsResource, listenerconfigsKind, c.ns, opts), &k3scattleiov1.ListenerConfigList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &k3scattleiov1.ListenerConfigList{ListMeta: obj.(*k3scattleiov1.ListenerConfigList).ListMeta} + for _, item := range obj.(*k3scattleiov1.ListenerConfigList).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 listenerConfigs. +func (c *FakeListenerConfigs) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(listenerconfigsResource, c.ns, opts)) + +} + +// Create takes the representation of a listenerConfig and creates it. Returns the server's representation of the listenerConfig, and an error, if there is any. +func (c *FakeListenerConfigs) Create(listenerConfig *k3scattleiov1.ListenerConfig) (result *k3scattleiov1.ListenerConfig, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(listenerconfigsResource, c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.ListenerConfig), err +} + +// Update takes the representation of a listenerConfig and updates it. Returns the server's representation of the listenerConfig, and an error, if there is any. +func (c *FakeListenerConfigs) Update(listenerConfig *k3scattleiov1.ListenerConfig) (result *k3scattleiov1.ListenerConfig, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(listenerconfigsResource, c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.ListenerConfig), 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 *FakeListenerConfigs) UpdateStatus(listenerConfig *k3scattleiov1.ListenerConfig) (*k3scattleiov1.ListenerConfig, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(listenerconfigsResource, "status", c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.ListenerConfig), err +} + +// Delete takes name of the listenerConfig and deletes it. Returns an error if one occurs. +func (c *FakeListenerConfigs) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(listenerconfigsResource, c.ns, name), &k3scattleiov1.ListenerConfig{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeListenerConfigs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(listenerconfigsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &k3scattleiov1.ListenerConfigList{}) + return err +} + +// Patch applies the patch and returns the patched listenerConfig. +func (c *FakeListenerConfigs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *k3scattleiov1.ListenerConfig, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(listenerconfigsResource, c.ns, name, pt, data, subresources...), &k3scattleiov1.ListenerConfig{}) + + if obj == nil { + return nil, err + } + return obj.(*k3scattleiov1.ListenerConfig), err +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go new file mode 100644 index 0000000000..21cf76ac09 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go @@ -0,0 +1,23 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +type AddonExpansion interface{} + +type ListenerConfigExpansion interface{} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go new file mode 100644 index 0000000000..88aabade11 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go @@ -0,0 +1,95 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + "github.com/rancher/k3s/pkg/generated/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type K3sV1Interface interface { + RESTClient() rest.Interface + AddonsGetter + ListenerConfigsGetter +} + +// K3sV1Client is used to interact with features provided by the k3s.cattle.io group. +type K3sV1Client struct { + restClient rest.Interface +} + +func (c *K3sV1Client) Addons(namespace string) AddonInterface { + return newAddons(c, namespace) +} + +func (c *K3sV1Client) ListenerConfigs(namespace string) ListenerConfigInterface { + return newListenerConfigs(c, namespace) +} + +// NewForConfig creates a new K3sV1Client for the given config. +func NewForConfig(c *rest.Config) (*K3sV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &K3sV1Client{client}, nil +} + +// NewForConfigOrDie creates a new K3sV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *K3sV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new K3sV1Client for the given RESTClient. +func New(c rest.Interface) *K3sV1Client { + return &K3sV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + 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 *K3sV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go new file mode 100644 index 0000000000..45be544478 --- /dev/null +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go @@ -0,0 +1,191 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + scheme "github.com/rancher/k3s/pkg/generated/clientset/versioned/scheme" + metav1 "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" +) + +// ListenerConfigsGetter has a method to return a ListenerConfigInterface. +// A group's client should implement this interface. +type ListenerConfigsGetter interface { + ListenerConfigs(namespace string) ListenerConfigInterface +} + +// ListenerConfigInterface has methods to work with ListenerConfig resources. +type ListenerConfigInterface interface { + Create(*v1.ListenerConfig) (*v1.ListenerConfig, error) + Update(*v1.ListenerConfig) (*v1.ListenerConfig, error) + UpdateStatus(*v1.ListenerConfig) (*v1.ListenerConfig, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.ListenerConfig, error) + List(opts metav1.ListOptions) (*v1.ListenerConfigList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) + ListenerConfigExpansion +} + +// listenerConfigs implements ListenerConfigInterface +type listenerConfigs struct { + client rest.Interface + ns string +} + +// newListenerConfigs returns a ListenerConfigs +func newListenerConfigs(c *K3sV1Client, namespace string) *listenerConfigs { + return &listenerConfigs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the listenerConfig, and returns the corresponding listenerConfig object, and an error if there is any. +func (c *listenerConfigs) Get(name string, options metav1.GetOptions) (result *v1.ListenerConfig, err error) { + result = &v1.ListenerConfig{} + err = c.client.Get(). + Namespace(c.ns). + Resource("listenerconfigs"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ListenerConfigs that match those selectors. +func (c *listenerConfigs) List(opts metav1.ListOptions) (result *v1.ListenerConfigList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ListenerConfigList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("listenerconfigs"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested listenerConfigs. +func (c *listenerConfigs) Watch(opts metav1.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("listenerconfigs"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a listenerConfig and creates it. Returns the server's representation of the listenerConfig, and an error, if there is any. +func (c *listenerConfigs) Create(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { + result = &v1.ListenerConfig{} + err = c.client.Post(). + Namespace(c.ns). + Resource("listenerconfigs"). + Body(listenerConfig). + Do(). + Into(result) + return +} + +// Update takes the representation of a listenerConfig and updates it. Returns the server's representation of the listenerConfig, and an error, if there is any. +func (c *listenerConfigs) Update(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { + result = &v1.ListenerConfig{} + err = c.client.Put(). + Namespace(c.ns). + Resource("listenerconfigs"). + Name(listenerConfig.Name). + Body(listenerConfig). + 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 *listenerConfigs) UpdateStatus(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { + result = &v1.ListenerConfig{} + err = c.client.Put(). + Namespace(c.ns). + Resource("listenerconfigs"). + Name(listenerConfig.Name). + SubResource("status"). + Body(listenerConfig). + Do(). + Into(result) + return +} + +// Delete takes name of the listenerConfig and deletes it. Returns an error if one occurs. +func (c *listenerConfigs) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("listenerconfigs"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *listenerConfigs) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.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("listenerconfigs"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched listenerConfig. +func (c *listenerConfigs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) { + result = &v1.ListenerConfig{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("listenerconfigs"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/generated/controllers/k3s.cattle.io/factory.go b/pkg/generated/controllers/k3s.cattle.io/factory.go new file mode 100644 index 0000000000..7b96258fb0 --- /dev/null +++ b/pkg/generated/controllers/k3s.cattle.io/factory.go @@ -0,0 +1,101 @@ +/* +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 main. DO NOT EDIT. + +package k3s + +import ( + "context" + "time" + + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned" + informers "github.com/rancher/k3s/pkg/generated/informers/externalversions" + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" +) + +type Factory struct { + synced bool + informerFactory informers.SharedInformerFactory + clientset clientset.Interface + controllerManager *generic.ControllerManager + threadiness map[schema.GroupVersionKind]int +} + +func NewFactoryFromConfigOrDie(config *rest.Config) *Factory { + f, err := NewFactoryFromConfig(config) + if err != nil { + panic(err) + } + return f +} + +func NewFactoryFromConfig(config *rest.Config) (*Factory, error) { + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactory(cs, 2*time.Hour) + return NewFactory(cs, informerFactory), nil +} + +func NewFactoryFromConfigWithNamespace(config *rest.Config, namespace string) (*Factory, error) { + if namespace == "" { + return NewFactoryFromConfig(config) + } + + cs, err := clientset.NewForConfig(config) + if err != nil { + return nil, err + } + + informerFactory := informers.NewSharedInformerFactoryWithOptions(cs, 2*time.Hour, informers.WithNamespace(namespace)) + return NewFactory(cs, informerFactory), nil +} + +func NewFactory(clientset clientset.Interface, informerFactory informers.SharedInformerFactory) *Factory { + return &Factory{ + threadiness: map[schema.GroupVersionKind]int{}, + controllerManager: &generic.ControllerManager{}, + clientset: clientset, + informerFactory: informerFactory, + } +} + +func (c *Factory) SetThreadiness(gvk schema.GroupVersionKind, threadiness int) { + c.threadiness[gvk] = threadiness +} + +func (c *Factory) Sync(ctx context.Context) error { + c.informerFactory.Start(ctx.Done()) + c.informerFactory.WaitForCacheSync(ctx.Done()) + return nil +} + +func (c *Factory) Start(ctx context.Context, defaultThreadiness int) error { + if err := c.Sync(ctx); err != nil { + return err + } + + return c.controllerManager.Start(ctx, defaultThreadiness, c.threadiness) +} + +func (c *Factory) K3s() Interface { + return New(c.controllerManager, c.informerFactory.K3s(), c.clientset) +} diff --git a/pkg/generated/controllers/k3s.cattle.io/interface.go b/pkg/generated/controllers/k3s.cattle.io/interface.go new file mode 100644 index 0000000000..201695983c --- /dev/null +++ b/pkg/generated/controllers/k3s.cattle.io/interface.go @@ -0,0 +1,50 @@ +/* +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 main. DO NOT EDIT. + +package k3s + +import ( + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned" + v1 "github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io/v1" + informers "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io" + "github.com/rancher/wrangler/pkg/generic" +) + +type Interface interface { + V1() v1.Interface +} + +type group struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.Interface +} + +// New returns a new Interface. +func New(controllerManager *generic.ControllerManager, informers informers.Interface, + client clientset.Interface) Interface { + return &group{ + controllerManager: controllerManager, + informers: informers, + client: client, + } +} + +func (g *group) V1() v1.Interface { + return v1.New(g.controllerManager, g.client.K3sV1(), g.informers.V1()) +} diff --git a/pkg/generated/controllers/k3s.cattle.io/v1/addon.go b/pkg/generated/controllers/k3s.cattle.io/v1/addon.go new file mode 100644 index 0000000000..f3f4f23fcf --- /dev/null +++ b/pkg/generated/controllers/k3s.cattle.io/v1/addon.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + informers "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io/v1" + listers "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +type AddonHandler func(string, *v1.Addon) (*v1.Addon, error) + +type AddonController interface { + AddonClient + + OnChange(ctx context.Context, name string, sync AddonHandler) + OnRemove(ctx context.Context, name string, sync AddonHandler) + Enqueue(namespace, name string) + + Cache() AddonCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type AddonClient interface { + Create(*v1.Addon) (*v1.Addon, error) + Update(*v1.Addon) (*v1.Addon, error) + UpdateStatus(*v1.Addon) (*v1.Addon, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.Addon, error) + List(namespace string, opts metav1.ListOptions) (*v1.AddonList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Addon, err error) +} + +type AddonCache interface { + Get(namespace, name string) (*v1.Addon, error) + List(namespace string, selector labels.Selector) ([]*v1.Addon, error) + + AddIndexer(indexName string, indexer AddonIndexer) + GetByIndex(indexName, key string) ([]*v1.Addon, error) +} + +type AddonIndexer func(obj *v1.Addon) ([]string, error) + +type addonController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.AddonsGetter + informer informers.AddonInformer + gvk schema.GroupVersionKind +} + +func NewAddonController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.AddonsGetter, informer informers.AddonInformer) AddonController { + return &addonController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromAddonHandlerToHandler(sync AddonHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.Addon + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.Addon)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *addonController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.Addon)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateAddonOnChange(updater generic.Updater, handler AddonHandler) AddonHandler { + return func(key string, obj *v1.Addon) (*v1.Addon, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.Addon) + } + } + + return copyObj, err + } +} + +func (c *addonController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *addonController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *addonController) OnChange(ctx context.Context, name string, sync AddonHandler) { + c.AddGenericHandler(ctx, name, FromAddonHandlerToHandler(sync)) +} + +func (c *addonController) OnRemove(ctx context.Context, name string, sync AddonHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromAddonHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *addonController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *addonController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *addonController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *addonController) Cache() AddonCache { + return &addonCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *addonController) Create(obj *v1.Addon) (*v1.Addon, error) { + return c.clientGetter.Addons(obj.Namespace).Create(obj) +} + +func (c *addonController) Update(obj *v1.Addon) (*v1.Addon, error) { + return c.clientGetter.Addons(obj.Namespace).Update(obj) +} + +func (c *addonController) UpdateStatus(obj *v1.Addon) (*v1.Addon, error) { + return c.clientGetter.Addons(obj.Namespace).UpdateStatus(obj) +} + +func (c *addonController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.Addons(namespace).Delete(name, options) +} + +func (c *addonController) Get(namespace, name string, options metav1.GetOptions) (*v1.Addon, error) { + return c.clientGetter.Addons(namespace).Get(name, options) +} + +func (c *addonController) List(namespace string, opts metav1.ListOptions) (*v1.AddonList, error) { + return c.clientGetter.Addons(namespace).List(opts) +} + +func (c *addonController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.Addons(namespace).Watch(opts) +} + +func (c *addonController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Addon, err error) { + return c.clientGetter.Addons(namespace).Patch(name, pt, data, subresources...) +} + +type addonCache struct { + lister listers.AddonLister + indexer cache.Indexer +} + +func (c *addonCache) Get(namespace, name string) (*v1.Addon, error) { + return c.lister.Addons(namespace).Get(name) +} + +func (c *addonCache) List(namespace string, selector labels.Selector) ([]*v1.Addon, error) { + return c.lister.Addons(namespace).List(selector) +} + +func (c *addonCache) AddIndexer(indexName string, indexer AddonIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.Addon)) + }, + })) +} + +func (c *addonCache) GetByIndex(indexName, key string) (result []*v1.Addon, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.Addon)) + } + return result, nil +} diff --git a/pkg/generated/controllers/k3s.cattle.io/v1/interface.go b/pkg/generated/controllers/k3s.cattle.io/v1/interface.go new file mode 100644 index 0000000000..640037cab7 --- /dev/null +++ b/pkg/generated/controllers/k3s.cattle.io/v1/interface.go @@ -0,0 +1,53 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + informers "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io/v1" + "github.com/rancher/wrangler/pkg/generic" +) + +type Interface interface { + Addon() AddonController + ListenerConfig() ListenerConfigController +} + +func New(controllerManager *generic.ControllerManager, client clientset.K3sV1Interface, + informers informers.Interface) Interface { + return &version{ + controllerManager: controllerManager, + client: client, + informers: informers, + } +} + +type version struct { + controllerManager *generic.ControllerManager + informers informers.Interface + client clientset.K3sV1Interface +} + +func (c *version) Addon() AddonController { + return NewAddonController(v1.SchemeGroupVersion.WithKind("Addon"), c.controllerManager, c.client, c.informers.Addons()) +} +func (c *version) ListenerConfig() ListenerConfigController { + return NewListenerConfigController(v1.SchemeGroupVersion.WithKind("ListenerConfig"), c.controllerManager, c.client, c.informers.ListenerConfigs()) +} diff --git a/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go new file mode 100644 index 0000000000..c5359ff195 --- /dev/null +++ b/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go @@ -0,0 +1,242 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + "context" + + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" + informers "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io/v1" + listers "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" + "github.com/rancher/wrangler/pkg/generic" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +type ListenerConfigHandler func(string, *v1.ListenerConfig) (*v1.ListenerConfig, error) + +type ListenerConfigController interface { + ListenerConfigClient + + OnChange(ctx context.Context, name string, sync ListenerConfigHandler) + OnRemove(ctx context.Context, name string, sync ListenerConfigHandler) + Enqueue(namespace, name string) + + Cache() ListenerConfigCache + + Informer() cache.SharedIndexInformer + GroupVersionKind() schema.GroupVersionKind + + AddGenericHandler(ctx context.Context, name string, handler generic.Handler) + AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) + Updater() generic.Updater +} + +type ListenerConfigClient interface { + Create(*v1.ListenerConfig) (*v1.ListenerConfig, error) + Update(*v1.ListenerConfig) (*v1.ListenerConfig, error) + UpdateStatus(*v1.ListenerConfig) (*v1.ListenerConfig, error) + Delete(namespace, name string, options *metav1.DeleteOptions) error + Get(namespace, name string, options metav1.GetOptions) (*v1.ListenerConfig, error) + List(namespace string, opts metav1.ListOptions) (*v1.ListenerConfigList, error) + Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) + Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) +} + +type ListenerConfigCache interface { + Get(namespace, name string) (*v1.ListenerConfig, error) + List(namespace string, selector labels.Selector) ([]*v1.ListenerConfig, error) + + AddIndexer(indexName string, indexer ListenerConfigIndexer) + GetByIndex(indexName, key string) ([]*v1.ListenerConfig, error) +} + +type ListenerConfigIndexer func(obj *v1.ListenerConfig) ([]string, error) + +type listenerConfigController struct { + controllerManager *generic.ControllerManager + clientGetter clientset.ListenerConfigsGetter + informer informers.ListenerConfigInformer + gvk schema.GroupVersionKind +} + +func NewListenerConfigController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ListenerConfigsGetter, informer informers.ListenerConfigInformer) ListenerConfigController { + return &listenerConfigController{ + controllerManager: controllerManager, + clientGetter: clientGetter, + informer: informer, + gvk: gvk, + } +} + +func FromListenerConfigHandlerToHandler(sync ListenerConfigHandler) generic.Handler { + return func(key string, obj runtime.Object) (ret runtime.Object, err error) { + var v *v1.ListenerConfig + if obj == nil { + v, err = sync(key, nil) + } else { + v, err = sync(key, obj.(*v1.ListenerConfig)) + } + if v == nil { + return nil, err + } + return v, err + } +} + +func (c *listenerConfigController) Updater() generic.Updater { + return func(obj runtime.Object) (runtime.Object, error) { + newObj, err := c.Update(obj.(*v1.ListenerConfig)) + if newObj == nil { + return nil, err + } + return newObj, err + } +} + +func UpdateListenerConfigOnChange(updater generic.Updater, handler ListenerConfigHandler) ListenerConfigHandler { + return func(key string, obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { + if obj == nil { + return handler(key, nil) + } + + copyObj := obj.DeepCopy() + newObj, err := handler(key, copyObj) + if newObj != nil { + copyObj = newObj + } + if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { + newObj, err := updater(copyObj) + if newObj != nil && err == nil { + copyObj = newObj.(*v1.ListenerConfig) + } + } + + return copyObj, err + } +} + +func (c *listenerConfigController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) +} + +func (c *listenerConfigController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) + c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) +} + +func (c *listenerConfigController) OnChange(ctx context.Context, name string, sync ListenerConfigHandler) { + c.AddGenericHandler(ctx, name, FromListenerConfigHandlerToHandler(sync)) +} + +func (c *listenerConfigController) OnRemove(ctx context.Context, name string, sync ListenerConfigHandler) { + removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromListenerConfigHandlerToHandler(sync)) + c.AddGenericHandler(ctx, name, removeHandler) +} + +func (c *listenerConfigController) Enqueue(namespace, name string) { + c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) +} + +func (c *listenerConfigController) Informer() cache.SharedIndexInformer { + return c.informer.Informer() +} + +func (c *listenerConfigController) GroupVersionKind() schema.GroupVersionKind { + return c.gvk +} + +func (c *listenerConfigController) Cache() ListenerConfigCache { + return &listenerConfigCache{ + lister: c.informer.Lister(), + indexer: c.informer.Informer().GetIndexer(), + } +} + +func (c *listenerConfigController) Create(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { + return c.clientGetter.ListenerConfigs(obj.Namespace).Create(obj) +} + +func (c *listenerConfigController) Update(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { + return c.clientGetter.ListenerConfigs(obj.Namespace).Update(obj) +} + +func (c *listenerConfigController) UpdateStatus(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { + return c.clientGetter.ListenerConfigs(obj.Namespace).UpdateStatus(obj) +} + +func (c *listenerConfigController) Delete(namespace, name string, options *metav1.DeleteOptions) error { + return c.clientGetter.ListenerConfigs(namespace).Delete(name, options) +} + +func (c *listenerConfigController) Get(namespace, name string, options metav1.GetOptions) (*v1.ListenerConfig, error) { + return c.clientGetter.ListenerConfigs(namespace).Get(name, options) +} + +func (c *listenerConfigController) List(namespace string, opts metav1.ListOptions) (*v1.ListenerConfigList, error) { + return c.clientGetter.ListenerConfigs(namespace).List(opts) +} + +func (c *listenerConfigController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { + return c.clientGetter.ListenerConfigs(namespace).Watch(opts) +} + +func (c *listenerConfigController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) { + return c.clientGetter.ListenerConfigs(namespace).Patch(name, pt, data, subresources...) +} + +type listenerConfigCache struct { + lister listers.ListenerConfigLister + indexer cache.Indexer +} + +func (c *listenerConfigCache) Get(namespace, name string) (*v1.ListenerConfig, error) { + return c.lister.ListenerConfigs(namespace).Get(name) +} + +func (c *listenerConfigCache) List(namespace string, selector labels.Selector) ([]*v1.ListenerConfig, error) { + return c.lister.ListenerConfigs(namespace).List(selector) +} + +func (c *listenerConfigCache) AddIndexer(indexName string, indexer ListenerConfigIndexer) { + utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ + indexName: func(obj interface{}) (strings []string, e error) { + return indexer(obj.(*v1.ListenerConfig)) + }, + })) +} + +func (c *listenerConfigCache) GetByIndex(indexName, key string) (result []*v1.ListenerConfig, err error) { + objs, err := c.indexer.ByIndex(indexName, key) + if err != nil { + return nil, err + } + for _, obj := range objs { + result = append(result, obj.(*v1.ListenerConfig)) + } + return result, nil +} diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go new file mode 100644 index 0000000000..2b1d5c3f9f --- /dev/null +++ b/pkg/generated/informers/externalversions/factory.go @@ -0,0 +1,180 @@ +/* +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 main. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/rancher/k3s/pkg/generated/clientset/versioned" + internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" + k3scattleio "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + K3s() k3scattleio.Interface +} + +func (f *sharedInformerFactory) K3s() k3scattleio.Interface { + return k3scattleio.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go new file mode 100644 index 0000000000..93d0c7a5a5 --- /dev/null +++ b/pkg/generated/informers/externalversions/generic.go @@ -0,0 +1,64 @@ +/* +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 main. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=k3s.cattle.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("addons"): + return &genericInformer{resource: resource.GroupResource(), informer: f.K3s().V1().Addons().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("listenerconfigs"): + return &genericInformer{resource: resource.GroupResource(), informer: f.K3s().V1().ListenerConfigs().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 0000000000..70fe8bf9b4 --- /dev/null +++ b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,40 @@ +/* +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 main. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/rancher/k3s/pkg/generated/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/interface.go b/pkg/generated/informers/externalversions/k3s.cattle.io/interface.go new file mode 100644 index 0000000000..8bf844775c --- /dev/null +++ b/pkg/generated/informers/externalversions/k3s.cattle.io/interface.go @@ -0,0 +1,46 @@ +/* +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 main. DO NOT EDIT. + +package k3s + +import ( + internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io/v1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.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} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/addon.go b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/addon.go new file mode 100644 index 0000000000..375c0f27f7 --- /dev/null +++ b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/addon.go @@ -0,0 +1,89 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + time "time" + + k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + versioned "github.com/rancher/k3s/pkg/generated/clientset/versioned" + internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" + metav1 "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" +) + +// AddonInformer provides access to a shared informer and lister for +// Addons. +type AddonInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.AddonLister +} + +type addonInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewAddonInformer constructs a new informer for Addon 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 NewAddonInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredAddonInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredAddonInformer constructs a new informer for Addon 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 NewFilteredAddonInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.K3sV1().Addons(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.K3sV1().Addons(namespace).Watch(options) + }, + }, + &k3scattleiov1.Addon{}, + resyncPeriod, + indexers, + ) +} + +func (f *addonInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredAddonInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *addonInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&k3scattleiov1.Addon{}, f.defaultInformer) +} + +func (f *addonInformer) Lister() v1.AddonLister { + return v1.NewAddonLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go new file mode 100644 index 0000000000..5c896477ea --- /dev/null +++ b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go @@ -0,0 +1,52 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Addons returns a AddonInformer. + Addons() AddonInformer + // ListenerConfigs returns a ListenerConfigInformer. + ListenerConfigs() ListenerConfigInformer +} + +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} +} + +// Addons returns a AddonInformer. +func (v *version) Addons() AddonInformer { + return &addonInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ListenerConfigs returns a ListenerConfigInformer. +func (v *version) ListenerConfigs() ListenerConfigInformer { + return &listenerConfigInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go new file mode 100644 index 0000000000..b1d1a38d21 --- /dev/null +++ b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go @@ -0,0 +1,89 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + time "time" + + k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + versioned "github.com/rancher/k3s/pkg/generated/clientset/versioned" + internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" + metav1 "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" +) + +// ListenerConfigInformer provides access to a shared informer and lister for +// ListenerConfigs. +type ListenerConfigInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ListenerConfigLister +} + +type listenerConfigInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewListenerConfigInformer constructs a new informer for ListenerConfig 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 NewListenerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredListenerConfigInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredListenerConfigInformer constructs a new informer for ListenerConfig 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 NewFilteredListenerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.K3sV1().ListenerConfigs(namespace).List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.K3sV1().ListenerConfigs(namespace).Watch(options) + }, + }, + &k3scattleiov1.ListenerConfig{}, + resyncPeriod, + indexers, + ) +} + +func (f *listenerConfigInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredListenerConfigInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *listenerConfigInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&k3scattleiov1.ListenerConfig{}, f.defaultInformer) +} + +func (f *listenerConfigInformer) Lister() v1.ListenerConfigLister { + return v1.NewListenerConfigLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/listers/k3s.cattle.io/v1/addon.go b/pkg/generated/listers/k3s.cattle.io/v1/addon.go new file mode 100644 index 0000000000..32031a11ce --- /dev/null +++ b/pkg/generated/listers/k3s.cattle.io/v1/addon.go @@ -0,0 +1,94 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// AddonLister helps list Addons. +type AddonLister interface { + // List lists all Addons in the indexer. + List(selector labels.Selector) (ret []*v1.Addon, err error) + // Addons returns an object that can list and get Addons. + Addons(namespace string) AddonNamespaceLister + AddonListerExpansion +} + +// addonLister implements the AddonLister interface. +type addonLister struct { + indexer cache.Indexer +} + +// NewAddonLister returns a new AddonLister. +func NewAddonLister(indexer cache.Indexer) AddonLister { + return &addonLister{indexer: indexer} +} + +// List lists all Addons in the indexer. +func (s *addonLister) List(selector labels.Selector) (ret []*v1.Addon, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Addon)) + }) + return ret, err +} + +// Addons returns an object that can list and get Addons. +func (s *addonLister) Addons(namespace string) AddonNamespaceLister { + return addonNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// AddonNamespaceLister helps list and get Addons. +type AddonNamespaceLister interface { + // List lists all Addons in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.Addon, err error) + // Get retrieves the Addon from the indexer for a given namespace and name. + Get(name string) (*v1.Addon, error) + AddonNamespaceListerExpansion +} + +// addonNamespaceLister implements the AddonNamespaceLister +// interface. +type addonNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Addons in the indexer for a given namespace. +func (s addonNamespaceLister) List(selector labels.Selector) (ret []*v1.Addon, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.Addon)) + }) + return ret, err +} + +// Get retrieves the Addon from the indexer for a given namespace and name. +func (s addonNamespaceLister) Get(name string) (*v1.Addon, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("addon"), name) + } + return obj.(*v1.Addon), nil +} diff --git a/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go b/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go new file mode 100644 index 0000000000..604e04b64a --- /dev/null +++ b/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go @@ -0,0 +1,35 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +// AddonListerExpansion allows custom methods to be added to +// AddonLister. +type AddonListerExpansion interface{} + +// AddonNamespaceListerExpansion allows custom methods to be added to +// AddonNamespaceLister. +type AddonNamespaceListerExpansion interface{} + +// ListenerConfigListerExpansion allows custom methods to be added to +// ListenerConfigLister. +type ListenerConfigListerExpansion interface{} + +// ListenerConfigNamespaceListerExpansion allows custom methods to be added to +// ListenerConfigNamespaceLister. +type ListenerConfigNamespaceListerExpansion interface{} diff --git a/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go new file mode 100644 index 0000000000..3c596beaac --- /dev/null +++ b/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go @@ -0,0 +1,94 @@ +/* +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 main. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ListenerConfigLister helps list ListenerConfigs. +type ListenerConfigLister interface { + // List lists all ListenerConfigs in the indexer. + List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) + // ListenerConfigs returns an object that can list and get ListenerConfigs. + ListenerConfigs(namespace string) ListenerConfigNamespaceLister + ListenerConfigListerExpansion +} + +// listenerConfigLister implements the ListenerConfigLister interface. +type listenerConfigLister struct { + indexer cache.Indexer +} + +// NewListenerConfigLister returns a new ListenerConfigLister. +func NewListenerConfigLister(indexer cache.Indexer) ListenerConfigLister { + return &listenerConfigLister{indexer: indexer} +} + +// List lists all ListenerConfigs in the indexer. +func (s *listenerConfigLister) List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ListenerConfig)) + }) + return ret, err +} + +// ListenerConfigs returns an object that can list and get ListenerConfigs. +func (s *listenerConfigLister) ListenerConfigs(namespace string) ListenerConfigNamespaceLister { + return listenerConfigNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ListenerConfigNamespaceLister helps list and get ListenerConfigs. +type ListenerConfigNamespaceLister interface { + // List lists all ListenerConfigs in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) + // Get retrieves the ListenerConfig from the indexer for a given namespace and name. + Get(name string) (*v1.ListenerConfig, error) + ListenerConfigNamespaceListerExpansion +} + +// listenerConfigNamespaceLister implements the ListenerConfigNamespaceLister +// interface. +type listenerConfigNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ListenerConfigs in the indexer for a given namespace. +func (s listenerConfigNamespaceLister) List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ListenerConfig)) + }) + return ret, err +} + +// Get retrieves the ListenerConfig from the indexer for a given namespace and name. +func (s listenerConfigNamespaceLister) Get(name string) (*v1.ListenerConfig, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("listenerconfig"), name) + } + return obj.(*v1.ListenerConfig), nil +}