├── .gitignore ├── Gopkg.lock ├── Gopkg.toml ├── README.md ├── controller.go ├── crd └── myresource.yaml ├── example └── example-myresource.yaml ├── handler.go ├── main.go └── pkg ├── apis └── myresource │ ├── register.go │ └── v1 │ ├── doc.go │ ├── register.go │ ├── types.go │ └── zz_generated.deepcopy.go └── client ├── clientset └── versioned │ ├── clientset.go │ ├── doc.go │ ├── fake │ ├── clientset_generated.go │ ├── doc.go │ └── register.go │ ├── scheme │ ├── doc.go │ └── register.go │ └── typed │ └── myresource │ └── v1 │ ├── doc.go │ ├── fake │ ├── doc.go │ ├── fake_myresource.go │ └── fake_myresource_client.go │ ├── generated_expansion.go │ ├── myresource.go │ └── myresource_client.go ├── informers └── externalversions │ ├── factory.go │ ├── generic.go │ ├── internalinterfaces │ └── factory_interfaces.go │ └── myresource │ ├── interface.go │ └── v1 │ ├── interface.go │ └── myresource.go └── listers └── myresource └── v1 ├── expansion_generated.go └── myresource.go /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | name = "github.com/PuerkitoBio/purell" 6 | packages = ["."] 7 | revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4" 8 | version = "v1.1.0" 9 | 10 | [[projects]] 11 | branch = "master" 12 | name = "github.com/PuerkitoBio/urlesc" 13 | packages = ["."] 14 | revision = "de5bf2ad457846296e2031421a34e2568e304e35" 15 | 16 | [[projects]] 17 | name = "github.com/Sirupsen/logrus" 18 | packages = ["."] 19 | revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" 20 | version = "v1.0.5" 21 | 22 | [[projects]] 23 | name = "github.com/davecgh/go-spew" 24 | packages = ["spew"] 25 | revision = "346938d642f2ec3594ed81d874461961cd0faa76" 26 | version = "v1.1.0" 27 | 28 | [[projects]] 29 | name = "github.com/emicklei/go-restful" 30 | packages = [ 31 | ".", 32 | "log" 33 | ] 34 | revision = "26b41036311f2da8242db402557a0dbd09dc83da" 35 | version = "v2.6.0" 36 | 37 | [[projects]] 38 | name = "github.com/ghodss/yaml" 39 | packages = ["."] 40 | revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" 41 | version = "v1.0.0" 42 | 43 | [[projects]] 44 | branch = "master" 45 | name = "github.com/go-openapi/jsonpointer" 46 | packages = ["."] 47 | revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2" 48 | 49 | [[projects]] 50 | branch = "master" 51 | name = "github.com/go-openapi/jsonreference" 52 | packages = ["."] 53 | revision = "3fb327e6747da3043567ee86abd02bb6376b6be2" 54 | 55 | [[projects]] 56 | branch = "master" 57 | name = "github.com/go-openapi/spec" 58 | packages = ["."] 59 | revision = "bcff419492eeeb01f76e77d2ebc714dc97b607f5" 60 | 61 | [[projects]] 62 | branch = "master" 63 | name = "github.com/go-openapi/swag" 64 | packages = ["."] 65 | revision = "811b1089cde9dad18d4d0c2d09fbdbf28dbd27a5" 66 | 67 | [[projects]] 68 | name = "github.com/gogo/protobuf" 69 | packages = [ 70 | "gogoproto", 71 | "plugin/compare", 72 | "plugin/defaultcheck", 73 | "plugin/description", 74 | "plugin/embedcheck", 75 | "plugin/enumstringer", 76 | "plugin/equal", 77 | "plugin/face", 78 | "plugin/gostring", 79 | "plugin/marshalto", 80 | "plugin/oneofcheck", 81 | "plugin/populate", 82 | "plugin/size", 83 | "plugin/stringer", 84 | "plugin/testgen", 85 | "plugin/union", 86 | "plugin/unmarshal", 87 | "proto", 88 | "protoc-gen-gogo/descriptor", 89 | "protoc-gen-gogo/generator", 90 | "protoc-gen-gogo/grpc", 91 | "protoc-gen-gogo/plugin", 92 | "sortkeys", 93 | "vanity", 94 | "vanity/command" 95 | ] 96 | revision = "1adfc126b41513cc696b209667c8656ea7aac67c" 97 | version = "v1.0.0" 98 | 99 | [[projects]] 100 | branch = "master" 101 | name = "github.com/golang/glog" 102 | packages = ["."] 103 | revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" 104 | 105 | [[projects]] 106 | name = "github.com/golang/protobuf" 107 | packages = [ 108 | "proto", 109 | "ptypes", 110 | "ptypes/any", 111 | "ptypes/duration", 112 | "ptypes/timestamp" 113 | ] 114 | revision = "925541529c1fa6821df4e44ce2723319eb2be768" 115 | version = "v1.0.0" 116 | 117 | [[projects]] 118 | branch = "master" 119 | name = "github.com/google/gofuzz" 120 | packages = ["."] 121 | revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" 122 | 123 | [[projects]] 124 | name = "github.com/googleapis/gnostic" 125 | packages = [ 126 | "OpenAPIv2", 127 | "compiler", 128 | "extensions" 129 | ] 130 | revision = "ee43cbb60db7bd22502942cccbc39059117352ab" 131 | version = "v0.1.0" 132 | 133 | [[projects]] 134 | branch = "master" 135 | name = "github.com/hashicorp/golang-lru" 136 | packages = [ 137 | ".", 138 | "simplelru" 139 | ] 140 | revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3" 141 | 142 | [[projects]] 143 | branch = "master" 144 | name = "github.com/howeyc/gopass" 145 | packages = ["."] 146 | revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8" 147 | 148 | [[projects]] 149 | name = "github.com/imdario/mergo" 150 | packages = ["."] 151 | revision = "9d5f1277e9a8ed20c3684bda8fde67c05628518c" 152 | version = "v0.3.4" 153 | 154 | [[projects]] 155 | name = "github.com/json-iterator/go" 156 | packages = ["."] 157 | revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4" 158 | version = "1.1.3" 159 | 160 | [[projects]] 161 | branch = "master" 162 | name = "github.com/mailru/easyjson" 163 | packages = [ 164 | "buffer", 165 | "jlexer", 166 | "jwriter" 167 | ] 168 | revision = "8b799c424f57fa123fc63a99d6383bc6e4c02578" 169 | 170 | [[projects]] 171 | name = "github.com/modern-go/concurrent" 172 | packages = ["."] 173 | revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" 174 | version = "1.0.3" 175 | 176 | [[projects]] 177 | name = "github.com/modern-go/reflect2" 178 | packages = ["."] 179 | revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f" 180 | version = "1.0.0" 181 | 182 | [[projects]] 183 | name = "github.com/spf13/pflag" 184 | packages = ["."] 185 | revision = "583c0c0531f06d5278b7d917446061adc344b5cd" 186 | version = "v1.0.1" 187 | 188 | [[projects]] 189 | branch = "master" 190 | name = "golang.org/x/crypto" 191 | packages = ["ssh/terminal"] 192 | revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e" 193 | 194 | [[projects]] 195 | branch = "master" 196 | name = "golang.org/x/net" 197 | packages = [ 198 | "context", 199 | "http2", 200 | "http2/hpack", 201 | "idna", 202 | "lex/httplex" 203 | ] 204 | revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41" 205 | 206 | [[projects]] 207 | branch = "master" 208 | name = "golang.org/x/sys" 209 | packages = [ 210 | "unix", 211 | "windows" 212 | ] 213 | revision = "2281fa97ef7b0c26324634d5a22f04babdac8713" 214 | 215 | [[projects]] 216 | name = "golang.org/x/text" 217 | packages = [ 218 | "collate", 219 | "collate/build", 220 | "internal/colltab", 221 | "internal/gen", 222 | "internal/tag", 223 | "internal/triegen", 224 | "internal/ucd", 225 | "language", 226 | "secure/bidirule", 227 | "transform", 228 | "unicode/bidi", 229 | "unicode/cldr", 230 | "unicode/norm", 231 | "unicode/rangetable", 232 | "width" 233 | ] 234 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" 235 | version = "v0.3.0" 236 | 237 | [[projects]] 238 | branch = "master" 239 | name = "golang.org/x/time" 240 | packages = ["rate"] 241 | revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" 242 | 243 | [[projects]] 244 | branch = "master" 245 | name = "golang.org/x/tools" 246 | packages = [ 247 | "go/ast/astutil", 248 | "imports" 249 | ] 250 | revision = "d9caac373771d868e508d835ebc3294a9a611c50" 251 | 252 | [[projects]] 253 | name = "gopkg.in/inf.v0" 254 | packages = ["."] 255 | revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" 256 | version = "v0.9.1" 257 | 258 | [[projects]] 259 | name = "gopkg.in/yaml.v2" 260 | packages = ["."] 261 | revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" 262 | version = "v2.2.1" 263 | 264 | [[projects]] 265 | branch = "master" 266 | name = "k8s.io/api" 267 | packages = [ 268 | "admissionregistration/v1alpha1", 269 | "admissionregistration/v1beta1", 270 | "apps/v1", 271 | "apps/v1beta1", 272 | "apps/v1beta2", 273 | "authentication/v1", 274 | "authentication/v1beta1", 275 | "authorization/v1", 276 | "authorization/v1beta1", 277 | "autoscaling/v1", 278 | "autoscaling/v2beta1", 279 | "batch/v1", 280 | "batch/v1beta1", 281 | "batch/v2alpha1", 282 | "certificates/v1beta1", 283 | "core/v1", 284 | "events/v1beta1", 285 | "extensions/v1beta1", 286 | "networking/v1", 287 | "policy/v1beta1", 288 | "rbac/v1", 289 | "rbac/v1alpha1", 290 | "rbac/v1beta1", 291 | "scheduling/v1alpha1", 292 | "settings/v1alpha1", 293 | "storage/v1", 294 | "storage/v1alpha1", 295 | "storage/v1beta1" 296 | ] 297 | revision = "6fb8575d8ac324ad9f9605dec64b7a4b8a632e79" 298 | 299 | [[projects]] 300 | branch = "master" 301 | name = "k8s.io/apimachinery" 302 | packages = [ 303 | "pkg/api/errors", 304 | "pkg/api/meta", 305 | "pkg/api/resource", 306 | "pkg/apis/meta/internalversion", 307 | "pkg/apis/meta/v1", 308 | "pkg/apis/meta/v1/unstructured", 309 | "pkg/apis/meta/v1beta1", 310 | "pkg/conversion", 311 | "pkg/conversion/queryparams", 312 | "pkg/fields", 313 | "pkg/labels", 314 | "pkg/runtime", 315 | "pkg/runtime/schema", 316 | "pkg/runtime/serializer", 317 | "pkg/runtime/serializer/json", 318 | "pkg/runtime/serializer/protobuf", 319 | "pkg/runtime/serializer/recognizer", 320 | "pkg/runtime/serializer/streaming", 321 | "pkg/runtime/serializer/versioning", 322 | "pkg/selection", 323 | "pkg/types", 324 | "pkg/util/cache", 325 | "pkg/util/clock", 326 | "pkg/util/diff", 327 | "pkg/util/errors", 328 | "pkg/util/framer", 329 | "pkg/util/intstr", 330 | "pkg/util/json", 331 | "pkg/util/net", 332 | "pkg/util/runtime", 333 | "pkg/util/sets", 334 | "pkg/util/validation", 335 | "pkg/util/validation/field", 336 | "pkg/util/wait", 337 | "pkg/util/yaml", 338 | "pkg/version", 339 | "pkg/watch", 340 | "third_party/forked/golang/reflect" 341 | ] 342 | revision = "ba81bc69c72dde92d5f1fefa2fa6d82aa83a6676" 343 | 344 | [[projects]] 345 | name = "k8s.io/client-go" 346 | packages = [ 347 | "discovery", 348 | "kubernetes", 349 | "kubernetes/scheme", 350 | "kubernetes/typed/admissionregistration/v1alpha1", 351 | "kubernetes/typed/admissionregistration/v1beta1", 352 | "kubernetes/typed/apps/v1", 353 | "kubernetes/typed/apps/v1beta1", 354 | "kubernetes/typed/apps/v1beta2", 355 | "kubernetes/typed/authentication/v1", 356 | "kubernetes/typed/authentication/v1beta1", 357 | "kubernetes/typed/authorization/v1", 358 | "kubernetes/typed/authorization/v1beta1", 359 | "kubernetes/typed/autoscaling/v1", 360 | "kubernetes/typed/autoscaling/v2beta1", 361 | "kubernetes/typed/batch/v1", 362 | "kubernetes/typed/batch/v1beta1", 363 | "kubernetes/typed/batch/v2alpha1", 364 | "kubernetes/typed/certificates/v1beta1", 365 | "kubernetes/typed/core/v1", 366 | "kubernetes/typed/events/v1beta1", 367 | "kubernetes/typed/extensions/v1beta1", 368 | "kubernetes/typed/networking/v1", 369 | "kubernetes/typed/policy/v1beta1", 370 | "kubernetes/typed/rbac/v1", 371 | "kubernetes/typed/rbac/v1alpha1", 372 | "kubernetes/typed/rbac/v1beta1", 373 | "kubernetes/typed/scheduling/v1alpha1", 374 | "kubernetes/typed/settings/v1alpha1", 375 | "kubernetes/typed/storage/v1", 376 | "kubernetes/typed/storage/v1alpha1", 377 | "kubernetes/typed/storage/v1beta1", 378 | "pkg/apis/clientauthentication", 379 | "pkg/apis/clientauthentication/v1alpha1", 380 | "pkg/version", 381 | "plugin/pkg/client/auth/exec", 382 | "rest", 383 | "rest/watch", 384 | "testing", 385 | "tools/auth", 386 | "tools/cache", 387 | "tools/clientcmd", 388 | "tools/clientcmd/api", 389 | "tools/clientcmd/api/latest", 390 | "tools/clientcmd/api/v1", 391 | "tools/metrics", 392 | "tools/pager", 393 | "tools/reference", 394 | "transport", 395 | "util/buffer", 396 | "util/cert", 397 | "util/flowcontrol", 398 | "util/homedir", 399 | "util/integer", 400 | "util/retry", 401 | "util/workqueue" 402 | ] 403 | revision = "23781f4d6632d88e869066eaebb743857aa1ef9b" 404 | version = "v7.0.0" 405 | 406 | [[projects]] 407 | branch = "master" 408 | name = "k8s.io/code-generator" 409 | packages = [ 410 | "cmd/client-gen/args", 411 | "cmd/client-gen/generators", 412 | "cmd/client-gen/generators/fake", 413 | "cmd/client-gen/generators/scheme", 414 | "cmd/client-gen/generators/util", 415 | "cmd/client-gen/path", 416 | "cmd/client-gen/types", 417 | "cmd/conversion-gen/args", 418 | "cmd/conversion-gen/generators", 419 | "cmd/deepcopy-gen/args", 420 | "cmd/defaulter-gen/args", 421 | "cmd/go-to-protobuf/protobuf", 422 | "cmd/informer-gen/args", 423 | "cmd/informer-gen/generators", 424 | "cmd/lister-gen/args", 425 | "cmd/lister-gen/generators", 426 | "cmd/openapi-gen/args", 427 | "pkg/util", 428 | "third_party/forked/golang/reflect" 429 | ] 430 | revision = "692f126559b2e6f2033edd97ed24174439fb3de6" 431 | 432 | [[projects]] 433 | branch = "master" 434 | name = "k8s.io/gengo" 435 | packages = [ 436 | "args", 437 | "examples/deepcopy-gen/generators", 438 | "examples/defaulter-gen/generators", 439 | "examples/import-boss/generators", 440 | "examples/set-gen/generators", 441 | "examples/set-gen/sets", 442 | "generator", 443 | "namer", 444 | "parser", 445 | "types" 446 | ] 447 | revision = "01a732e01d00cb9a81bb0ca050d3e6d2b947927b" 448 | 449 | [[projects]] 450 | branch = "master" 451 | name = "k8s.io/kube-openapi" 452 | packages = [ 453 | "pkg/common", 454 | "pkg/generators" 455 | ] 456 | revision = "f442ecb314a3679150c272e2b9713d8deed5955d" 457 | 458 | [solve-meta] 459 | analyzer-name = "dep" 460 | analyzer-version = 1 461 | inputs-digest = "f8bd8294010388ad4ee8f54d6a4024eeaf73b4fcf6bf9d174c089c3e3c1a344e" 462 | solver-name = "gps-cdcl" 463 | solver-version = 1 464 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | name = "github.com/Sirupsen/logrus" 30 | version = "1.0.5" 31 | 32 | [[constraint]] 33 | name = "github.com/davecgh/go-spew" 34 | version = "1.1.0" 35 | 36 | [[constraint]] 37 | name = "github.com/ghodss/yaml" 38 | version = "1.0.0" 39 | 40 | [[constraint]] 41 | name = "github.com/gogo/protobuf" 42 | version = "1.0.0" 43 | 44 | [[constraint]] 45 | branch = "master" 46 | name = "github.com/golang/glog" 47 | 48 | [[constraint]] 49 | name = "github.com/golang/protobuf" 50 | version = "1.0.0" 51 | 52 | [[constraint]] 53 | branch = "master" 54 | name = "github.com/google/gofuzz" 55 | 56 | [[constraint]] 57 | name = "github.com/googleapis/gnostic" 58 | version = "0.1.0" 59 | 60 | [[constraint]] 61 | branch = "master" 62 | name = "github.com/hashicorp/golang-lru" 63 | 64 | [[constraint]] 65 | name = "github.com/json-iterator/go" 66 | version = "1.1.3" 67 | 68 | [[constraint]] 69 | name = "github.com/modern-go/concurrent" 70 | version = "1.0.3" 71 | 72 | [[constraint]] 73 | name = "github.com/modern-go/reflect2" 74 | version = "1.0.0" 75 | 76 | [[constraint]] 77 | name = "github.com/spf13/pflag" 78 | version = "1.0.1" 79 | 80 | [[constraint]] 81 | branch = "master" 82 | name = "golang.org/x/crypto" 83 | 84 | [[constraint]] 85 | branch = "master" 86 | name = "golang.org/x/net" 87 | 88 | [[constraint]] 89 | branch = "master" 90 | name = "golang.org/x/sys" 91 | 92 | [[constraint]] 93 | name = "golang.org/x/text" 94 | version = "0.3.0" 95 | 96 | [[constraint]] 97 | branch = "master" 98 | name = "golang.org/x/time" 99 | 100 | [[constraint]] 101 | name = "gopkg.in/inf.v0" 102 | version = "0.9.1" 103 | 104 | [[constraint]] 105 | name = "gopkg.in/yaml.v2" 106 | version = "2.2.1" 107 | 108 | [[constraint]] 109 | branch = "master" 110 | name = "k8s.io/api" 111 | 112 | [[constraint]] 113 | branch = "master" 114 | name = "k8s.io/apimachinery" 115 | 116 | [[constraint]] 117 | name = "k8s.io/client-go" 118 | version = "7.0.0" 119 | 120 | [[constraint]] 121 | branch = "master" 122 | name = "k8s.io/code-generator" 123 | 124 | [[constraint]] 125 | branch = "master" 126 | name = "k8s.io/gengo" 127 | 128 | [[constraint]] 129 | branch = "master" 130 | name = "k8s.io/kube-openapi" 131 | 132 | [prune] 133 | go-tests = true 134 | unused-packages = true 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Custom Controller - Custom Resource Handling 2 | 3 | **Note**: the source code is _verbosely_ commented, so the source is meant to be read and to teach 4 | 5 | ## What is this? 6 | 7 | An example of a custom Kubernetes controller that's only purpose is to watch for the creation, updating, or deletion of all custom resource of type `MyResource` (in the all namespaces). This was created as an exercise to understand how Kubernetes controllers work and interact with the cluster and resources. 8 | 9 | ## Running 10 | 11 | ``` 12 | $ git clone https://github.com/trstringer/k8s-controller-custom-resource 13 | $ cd k8s-controller-custom-resource 14 | $ go run *.go 15 | ``` 16 | 17 | ## Inspecting resources in the handler 18 | 19 | You are welcome to dump the resources themselves in handler but logging would be extremely verbose (and not interactive). I recommend you use a debugger... 20 | 21 | ``` 22 | $ dlv debug 23 | (dlv) b main.ObjectCreated 24 | (dlv) c 25 | ``` 26 | 27 | You can then trigger an event by creating a deployment of nginx... 28 | 29 | ``` 30 | $ kubectl apply -f example/example-myresource.yaml 31 | ``` 32 | 33 | The breakpoint should be hit and you can analyze in the debugger the object... 34 | 35 | ``` 36 | (dlv) p obj 37 | ``` 38 | -------------------------------------------------------------------------------- /controller.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | log "github.com/Sirupsen/logrus" 8 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 9 | "k8s.io/apimachinery/pkg/util/wait" 10 | "k8s.io/client-go/kubernetes" 11 | "k8s.io/client-go/tools/cache" 12 | "k8s.io/client-go/util/workqueue" 13 | ) 14 | 15 | // Controller struct defines how a controller should encapsulate 16 | // logging, client connectivity, informing (list and watching) 17 | // queueing, and handling of resource changes 18 | type Controller struct { 19 | logger *log.Entry 20 | clientset kubernetes.Interface 21 | queue workqueue.RateLimitingInterface 22 | informer cache.SharedIndexInformer 23 | handler Handler 24 | } 25 | 26 | // Run is the main path of execution for the controller loop 27 | func (c *Controller) Run(stopCh <-chan struct{}) { 28 | // handle a panic with logging and exiting 29 | defer utilruntime.HandleCrash() 30 | // ignore new items in the queue but when all goroutines 31 | // have completed existing items then shutdown 32 | defer c.queue.ShutDown() 33 | 34 | c.logger.Info("Controller.Run: initiating") 35 | 36 | // run the informer to start listing and watching resources 37 | go c.informer.Run(stopCh) 38 | 39 | // do the initial synchronization (one time) to populate resources 40 | if !cache.WaitForCacheSync(stopCh, c.HasSynced) { 41 | utilruntime.HandleError(fmt.Errorf("Error syncing cache")) 42 | return 43 | } 44 | c.logger.Info("Controller.Run: cache sync complete") 45 | 46 | // run the runWorker method every second with a stop channel 47 | wait.Until(c.runWorker, time.Second, stopCh) 48 | } 49 | 50 | // HasSynced allows us to satisfy the Controller interface 51 | // by wiring up the informer's HasSynced method to it 52 | func (c *Controller) HasSynced() bool { 53 | return c.informer.HasSynced() 54 | } 55 | 56 | // runWorker executes the loop to process new items added to the queue 57 | func (c *Controller) runWorker() { 58 | log.Info("Controller.runWorker: starting") 59 | 60 | // invoke processNextItem to fetch and consume the next change 61 | // to a watched or listed resource 62 | for c.processNextItem() { 63 | log.Info("Controller.runWorker: processing next item") 64 | } 65 | 66 | log.Info("Controller.runWorker: completed") 67 | } 68 | 69 | // processNextItem retrieves each queued item and takes the 70 | // necessary handler action based off of if the item was 71 | // created or deleted 72 | func (c *Controller) processNextItem() bool { 73 | log.Info("Controller.processNextItem: start") 74 | 75 | // fetch the next item (blocking) from the queue to process or 76 | // if a shutdown is requested then return out of this to stop 77 | // processing 78 | key, quit := c.queue.Get() 79 | 80 | // stop the worker loop from running as this indicates we 81 | // have sent a shutdown message that the queue has indicated 82 | // from the Get method 83 | if quit { 84 | return false 85 | } 86 | 87 | defer c.queue.Done(key) 88 | 89 | // assert the string out of the key (format `namespace/name`) 90 | keyRaw := key.(string) 91 | 92 | // take the string key and get the object out of the indexer 93 | // 94 | // item will contain the complex object for the resource and 95 | // exists is a bool that'll indicate whether or not the 96 | // resource was created (true) or deleted (false) 97 | // 98 | // if there is an error in getting the key from the index 99 | // then we want to retry this particular queue key a certain 100 | // number of times (5 here) before we forget the queue key 101 | // and throw an error 102 | item, exists, err := c.informer.GetIndexer().GetByKey(keyRaw) 103 | if err != nil { 104 | if c.queue.NumRequeues(key) < 5 { 105 | c.logger.Errorf("Controller.processNextItem: Failed processing item with key %s with error %v, retrying", key, err) 106 | c.queue.AddRateLimited(key) 107 | } else { 108 | c.logger.Errorf("Controller.processNextItem: Failed processing item with key %s with error %v, no more retries", key, err) 109 | c.queue.Forget(key) 110 | utilruntime.HandleError(err) 111 | } 112 | } 113 | 114 | // if the item doesn't exist then it was deleted and we need to fire off the handler's 115 | // ObjectDeleted method. but if the object does exist that indicates that the object 116 | // was created (or updated) so run the ObjectCreated method 117 | // 118 | // after both instances, we want to forget the key from the queue, as this indicates 119 | // a code path of successful queue key processing 120 | if !exists { 121 | c.logger.Infof("Controller.processNextItem: object deleted detected: %s", keyRaw) 122 | c.handler.ObjectDeleted(item) 123 | c.queue.Forget(key) 124 | } else { 125 | c.logger.Infof("Controller.processNextItem: object created detected: %s", keyRaw) 126 | c.handler.ObjectCreated(item) 127 | c.queue.Forget(key) 128 | } 129 | 130 | // keep the worker loop running by returning true 131 | return true 132 | } 133 | -------------------------------------------------------------------------------- /crd/myresource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: myresources.trstringer.com 5 | spec: 6 | group: trstringer.com 7 | version: v1 8 | names: 9 | kind: MyResource 10 | plural: myresources 11 | scope: Namespaced 12 | -------------------------------------------------------------------------------- /example/example-myresource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: trstringer.com/v1 2 | kind: MyResource 3 | metadata: 4 | name: example-myresource 5 | spec: 6 | message: hello world 7 | someValue: 13 8 | -------------------------------------------------------------------------------- /handler.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | log "github.com/Sirupsen/logrus" 5 | ) 6 | 7 | // Handler interface contains the methods that are required 8 | type Handler interface { 9 | Init() error 10 | ObjectCreated(obj interface{}) 11 | ObjectDeleted(obj interface{}) 12 | ObjectUpdated(objOld, objNew interface{}) 13 | } 14 | 15 | // TestHandler is a sample implementation of Handler 16 | type TestHandler struct{} 17 | 18 | // Init handles any handler initialization 19 | func (t *TestHandler) Init() error { 20 | log.Info("TestHandler.Init") 21 | return nil 22 | } 23 | 24 | // ObjectCreated is called when an object is created 25 | func (t *TestHandler) ObjectCreated(obj interface{}) { 26 | log.Info("TestHandler.ObjectCreated") 27 | } 28 | 29 | // ObjectDeleted is called when an object is deleted 30 | func (t *TestHandler) ObjectDeleted(obj interface{}) { 31 | log.Info("TestHandler.ObjectDeleted") 32 | } 33 | 34 | // ObjectUpdated is called when an object is updated 35 | func (t *TestHandler) ObjectUpdated(objOld, objNew interface{}) { 36 | log.Info("TestHandler.ObjectUpdated") 37 | } 38 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "os/signal" 6 | "syscall" 7 | 8 | log "github.com/Sirupsen/logrus" 9 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | "k8s.io/client-go/kubernetes" 11 | "k8s.io/client-go/tools/cache" 12 | "k8s.io/client-go/tools/clientcmd" 13 | "k8s.io/client-go/util/workqueue" 14 | 15 | myresourceclientset "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned" 16 | myresourceinformer_v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/myresource/v1" 17 | ) 18 | 19 | // retrieve the Kubernetes cluster client from outside of the cluster 20 | func getKubernetesClient() (kubernetes.Interface, myresourceclientset.Interface) { 21 | // construct the path to resolve to `~/.kube/config` 22 | kubeConfigPath := os.Getenv("HOME") + "/.kube/config" 23 | 24 | // create the config from the path 25 | config, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath) 26 | if err != nil { 27 | log.Fatalf("getClusterConfig: %v", err) 28 | } 29 | 30 | // generate the client based off of the config 31 | client, err := kubernetes.NewForConfig(config) 32 | if err != nil { 33 | log.Fatalf("getClusterConfig: %v", err) 34 | } 35 | 36 | myresourceClient, err := myresourceclientset.NewForConfig(config) 37 | if err != nil { 38 | log.Fatalf("getClusterConfig: %v", err) 39 | } 40 | 41 | log.Info("Successfully constructed k8s client") 42 | return client, myresourceClient 43 | } 44 | 45 | // main code path 46 | func main() { 47 | // get the Kubernetes client for connectivity 48 | client, myresourceClient := getKubernetesClient() 49 | 50 | // retrieve our custom resource informer which was generated from 51 | // the code generator and pass it the custom resource client, specifying 52 | // we should be looking through all namespaces for listing and watching 53 | informer := myresourceinformer_v1.NewMyResourceInformer( 54 | myresourceClient, 55 | meta_v1.NamespaceAll, 56 | 0, 57 | cache.Indexers{}, 58 | ) 59 | 60 | // create a new queue so that when the informer gets a resource that is either 61 | // a result of listing or watching, we can add an idenfitying key to the queue 62 | // so that it can be handled in the handler 63 | queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) 64 | 65 | // add event handlers to handle the three types of events for resources: 66 | // - adding new resources 67 | // - updating existing resources 68 | // - deleting resources 69 | informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ 70 | AddFunc: func(obj interface{}) { 71 | // convert the resource object into a key (in this case 72 | // we are just doing it in the format of 'namespace/name') 73 | key, err := cache.MetaNamespaceKeyFunc(obj) 74 | log.Infof("Add myresource: %s", key) 75 | if err == nil { 76 | // add the key to the queue for the handler to get 77 | queue.Add(key) 78 | } 79 | }, 80 | UpdateFunc: func(oldObj, newObj interface{}) { 81 | key, err := cache.MetaNamespaceKeyFunc(newObj) 82 | log.Infof("Update myresource: %s", key) 83 | if err == nil { 84 | queue.Add(key) 85 | } 86 | }, 87 | DeleteFunc: func(obj interface{}) { 88 | // DeletionHandlingMetaNamsespaceKeyFunc is a helper function that allows 89 | // us to check the DeletedFinalStateUnknown existence in the event that 90 | // a resource was deleted but it is still contained in the index 91 | // 92 | // this then in turn calls MetaNamespaceKeyFunc 93 | key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) 94 | log.Infof("Delete myresource: %s", key) 95 | if err == nil { 96 | queue.Add(key) 97 | } 98 | }, 99 | }) 100 | 101 | // construct the Controller object which has all of the necessary components to 102 | // handle logging, connections, informing (listing and watching), the queue, 103 | // and the handler 104 | controller := Controller{ 105 | logger: log.NewEntry(log.New()), 106 | clientset: client, 107 | informer: informer, 108 | queue: queue, 109 | handler: &TestHandler{}, 110 | } 111 | 112 | // use a channel to synchronize the finalization for a graceful shutdown 113 | stopCh := make(chan struct{}) 114 | defer close(stopCh) 115 | 116 | // run the controller loop to process items 117 | go controller.Run(stopCh) 118 | 119 | // use a channel to handle OS signals to terminate and gracefully shut 120 | // down processing 121 | sigTerm := make(chan os.Signal, 1) 122 | signal.Notify(sigTerm, syscall.SIGTERM) 123 | signal.Notify(sigTerm, syscall.SIGINT) 124 | <-sigTerm 125 | } 126 | -------------------------------------------------------------------------------- /pkg/apis/myresource/register.go: -------------------------------------------------------------------------------- 1 | package myresource 2 | 3 | const GroupName = "trstringer.com" 4 | -------------------------------------------------------------------------------- /pkg/apis/myresource/v1/doc.go: -------------------------------------------------------------------------------- 1 | // +k8s:deepcopy-gen=package 2 | // +groupName=trstringer.com 3 | 4 | package v1 5 | -------------------------------------------------------------------------------- /pkg/apis/myresource/v1/register.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 | "k8s.io/apimachinery/pkg/runtime" 6 | "k8s.io/apimachinery/pkg/runtime/schema" 7 | 8 | "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource" 9 | ) 10 | 11 | // GroupVersion is the identifier for the API which includes 12 | // the name of the group and the version of the API 13 | var SchemeGroupVersion = schema.GroupVersion{ 14 | Group: myresource.GroupName, 15 | Version: "v1", 16 | } 17 | 18 | // create a SchemeBuilder which uses functions to add types to 19 | // the scheme 20 | // more comments here 21 | var ( 22 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 23 | AddToScheme = SchemeBuilder.AddToScheme 24 | ) 25 | 26 | func Resource(resource string) schema.GroupResource { 27 | return SchemeGroupVersion.WithResource(resource).GroupResource() 28 | } 29 | 30 | // addKnownTypes adds our types to the API scheme by registering 31 | // MyResource and MyResourceList 32 | func addKnownTypes(scheme *runtime.Scheme) error { 33 | scheme.AddKnownTypes( 34 | SchemeGroupVersion, 35 | &MyResource{}, 36 | &MyResourceList{}, 37 | ) 38 | 39 | // register the type in the scheme 40 | meta_v1.AddToGroupVersion(scheme, SchemeGroupVersion) 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /pkg/apis/myresource/v1/types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 | ) 6 | 7 | // +genclient 8 | // +genclient:noStatus 9 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 10 | 11 | // MyResource describes a MyResource resource 12 | type MyResource struct { 13 | // TypeMeta is the metadata for the resource, like kind and apiversion 14 | meta_v1.TypeMeta `json:",inline"` 15 | // ObjectMeta contains the metadata for the particular object, including 16 | // things like... 17 | // - name 18 | // - namespace 19 | // - self link 20 | // - labels 21 | // - ... etc ... 22 | meta_v1.ObjectMeta `json:"metadata,omitempty"` 23 | 24 | // Spec is the custom resource spec 25 | Spec MyResourceSpec `json:"spec"` 26 | } 27 | 28 | // MyResourceSpec is the spec for a MyResource resource 29 | type MyResourceSpec struct { 30 | // Message and SomeValue are example custom spec fields 31 | // 32 | // this is where you would put your custom resource data 33 | Message string `json:"message"` 34 | SomeValue *int32 `json:"someValue"` 35 | } 36 | 37 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 38 | 39 | // MyResourceList is a list of MyResource resources 40 | type MyResourceList struct { 41 | meta_v1.TypeMeta `json:",inline"` 42 | meta_v1.ListMeta `json:"metadata"` 43 | 44 | Items []MyResource `json:"items"` 45 | } 46 | -------------------------------------------------------------------------------- /pkg/apis/myresource/v1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | Copyright The Kubernetes Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // Code generated by deepcopy-gen. DO NOT EDIT. 20 | 21 | package v1 22 | 23 | import ( 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 28 | func (in *MyResource) DeepCopyInto(out *MyResource) { 29 | *out = *in 30 | out.TypeMeta = in.TypeMeta 31 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 32 | in.Spec.DeepCopyInto(&out.Spec) 33 | return 34 | } 35 | 36 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyResource. 37 | func (in *MyResource) DeepCopy() *MyResource { 38 | if in == nil { 39 | return nil 40 | } 41 | out := new(MyResource) 42 | in.DeepCopyInto(out) 43 | return out 44 | } 45 | 46 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 47 | func (in *MyResource) DeepCopyObject() runtime.Object { 48 | if c := in.DeepCopy(); c != nil { 49 | return c 50 | } 51 | return nil 52 | } 53 | 54 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 55 | func (in *MyResourceList) DeepCopyInto(out *MyResourceList) { 56 | *out = *in 57 | out.TypeMeta = in.TypeMeta 58 | out.ListMeta = in.ListMeta 59 | if in.Items != nil { 60 | in, out := &in.Items, &out.Items 61 | *out = make([]MyResource, len(*in)) 62 | for i := range *in { 63 | (*in)[i].DeepCopyInto(&(*out)[i]) 64 | } 65 | } 66 | return 67 | } 68 | 69 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyResourceList. 70 | func (in *MyResourceList) DeepCopy() *MyResourceList { 71 | if in == nil { 72 | return nil 73 | } 74 | out := new(MyResourceList) 75 | in.DeepCopyInto(out) 76 | return out 77 | } 78 | 79 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 80 | func (in *MyResourceList) DeepCopyObject() runtime.Object { 81 | if c := in.DeepCopy(); c != nil { 82 | return c 83 | } 84 | return nil 85 | } 86 | 87 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 88 | func (in *MyResourceSpec) DeepCopyInto(out *MyResourceSpec) { 89 | *out = *in 90 | if in.SomeValue != nil { 91 | in, out := &in.SomeValue, &out.SomeValue 92 | if *in == nil { 93 | *out = nil 94 | } else { 95 | *out = new(int32) 96 | **out = **in 97 | } 98 | } 99 | return 100 | } 101 | 102 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyResourceSpec. 103 | func (in *MyResourceSpec) DeepCopy() *MyResourceSpec { 104 | if in == nil { 105 | return nil 106 | } 107 | out := new(MyResourceSpec) 108 | in.DeepCopyInto(out) 109 | return out 110 | } 111 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package versioned 20 | 21 | import ( 22 | trstringerv1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/typed/myresource/v1" 23 | discovery "k8s.io/client-go/discovery" 24 | rest "k8s.io/client-go/rest" 25 | flowcontrol "k8s.io/client-go/util/flowcontrol" 26 | ) 27 | 28 | type Interface interface { 29 | Discovery() discovery.DiscoveryInterface 30 | TrstringerV1() trstringerv1.TrstringerV1Interface 31 | // Deprecated: please explicitly pick a version if possible. 32 | Trstringer() trstringerv1.TrstringerV1Interface 33 | } 34 | 35 | // Clientset contains the clients for groups. Each group has exactly one 36 | // version included in a Clientset. 37 | type Clientset struct { 38 | *discovery.DiscoveryClient 39 | trstringerV1 *trstringerv1.TrstringerV1Client 40 | } 41 | 42 | // TrstringerV1 retrieves the TrstringerV1Client 43 | func (c *Clientset) TrstringerV1() trstringerv1.TrstringerV1Interface { 44 | return c.trstringerV1 45 | } 46 | 47 | // Deprecated: Trstringer retrieves the default version of TrstringerClient. 48 | // Please explicitly pick a version. 49 | func (c *Clientset) Trstringer() trstringerv1.TrstringerV1Interface { 50 | return c.trstringerV1 51 | } 52 | 53 | // Discovery retrieves the DiscoveryClient 54 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 55 | if c == nil { 56 | return nil 57 | } 58 | return c.DiscoveryClient 59 | } 60 | 61 | // NewForConfig creates a new Clientset for the given config. 62 | func NewForConfig(c *rest.Config) (*Clientset, error) { 63 | configShallowCopy := *c 64 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 65 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 66 | } 67 | var cs Clientset 68 | var err error 69 | cs.trstringerV1, err = trstringerv1.NewForConfig(&configShallowCopy) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return &cs, nil 79 | } 80 | 81 | // NewForConfigOrDie creates a new Clientset for the given config and 82 | // panics if there is an error in the config. 83 | func NewForConfigOrDie(c *rest.Config) *Clientset { 84 | var cs Clientset 85 | cs.trstringerV1 = trstringerv1.NewForConfigOrDie(c) 86 | 87 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 88 | return &cs 89 | } 90 | 91 | // New creates a new Clientset for the given RESTClient. 92 | func New(c rest.Interface) *Clientset { 93 | var cs Clientset 94 | cs.trstringerV1 = trstringerv1.New(c) 95 | 96 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 97 | return &cs 98 | } 99 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated clientset. 20 | package versioned 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | clientset "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned" 23 | trstringerv1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/typed/myresource/v1" 24 | faketrstringerv1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/typed/myresource/v1/fake" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/apimachinery/pkg/watch" 27 | "k8s.io/client-go/discovery" 28 | fakediscovery "k8s.io/client-go/discovery/fake" 29 | "k8s.io/client-go/testing" 30 | ) 31 | 32 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 33 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 34 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 35 | // for a real clientset and is mostly useful in simple unit tests. 36 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 37 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 38 | for _, obj := range objects { 39 | if err := o.Add(obj); err != nil { 40 | panic(err) 41 | } 42 | } 43 | 44 | fakePtr := testing.Fake{} 45 | fakePtr.AddReactor("*", "*", testing.ObjectReaction(o)) 46 | fakePtr.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 47 | gvr := action.GetResource() 48 | ns := action.GetNamespace() 49 | watch, err := o.Watch(gvr, ns) 50 | if err != nil { 51 | return false, nil, err 52 | } 53 | return true, watch, nil 54 | }) 55 | 56 | return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}} 57 | } 58 | 59 | // Clientset implements clientset.Interface. Meant to be embedded into a 60 | // struct to get a default implementation. This makes faking out just the method 61 | // you want to test easier. 62 | type Clientset struct { 63 | testing.Fake 64 | discovery *fakediscovery.FakeDiscovery 65 | } 66 | 67 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 68 | return c.discovery 69 | } 70 | 71 | var _ clientset.Interface = &Clientset{} 72 | 73 | // TrstringerV1 retrieves the TrstringerV1Client 74 | func (c *Clientset) TrstringerV1() trstringerv1.TrstringerV1Interface { 75 | return &faketrstringerv1.FakeTrstringerV1{Fake: &c.Fake} 76 | } 77 | 78 | // Trstringer retrieves the TrstringerV1Client 79 | func (c *Clientset) Trstringer() trstringerv1.TrstringerV1Interface { 80 | return &faketrstringerv1.FakeTrstringerV1{Fake: &c.Fake} 81 | } 82 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated fake clientset. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | trstringerv1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | ) 28 | 29 | var scheme = runtime.NewScheme() 30 | var codecs = serializer.NewCodecFactory(scheme) 31 | var parameterCodec = runtime.NewParameterCodec(scheme) 32 | 33 | func init() { 34 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 35 | AddToScheme(scheme) 36 | } 37 | 38 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 39 | // of clientsets, like in: 40 | // 41 | // import ( 42 | // "k8s.io/client-go/kubernetes" 43 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 44 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 45 | // ) 46 | // 47 | // kclientset, _ := kubernetes.NewForConfig(c) 48 | // aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 49 | // 50 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 51 | // correctly. 52 | func AddToScheme(scheme *runtime.Scheme) { 53 | trstringerv1.AddToScheme(scheme) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package contains the scheme of the automatically generated clientset. 20 | package scheme 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package scheme 20 | 21 | import ( 22 | trstringerv1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | ) 28 | 29 | var Scheme = runtime.NewScheme() 30 | var Codecs = serializer.NewCodecFactory(Scheme) 31 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 32 | 33 | func init() { 34 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 35 | AddToScheme(Scheme) 36 | } 37 | 38 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 39 | // of clientsets, like in: 40 | // 41 | // import ( 42 | // "k8s.io/client-go/kubernetes" 43 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 44 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 45 | // ) 46 | // 47 | // kclientset, _ := kubernetes.NewForConfig(c) 48 | // aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 49 | // 50 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 51 | // correctly. 52 | func AddToScheme(scheme *runtime.Scheme) { 53 | trstringerv1.AddToScheme(scheme) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated typed clients. 20 | package v1 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // Package fake has the automatically generated clients. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/fake/fake_myresource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | myresource_v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | labels "k8s.io/apimachinery/pkg/labels" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | types "k8s.io/apimachinery/pkg/types" 27 | watch "k8s.io/apimachinery/pkg/watch" 28 | testing "k8s.io/client-go/testing" 29 | ) 30 | 31 | // FakeMyResources implements MyResourceInterface 32 | type FakeMyResources struct { 33 | Fake *FakeTrstringerV1 34 | ns string 35 | } 36 | 37 | var myresourcesResource = schema.GroupVersionResource{Group: "trstringer.com", Version: "v1", Resource: "myresources"} 38 | 39 | var myresourcesKind = schema.GroupVersionKind{Group: "trstringer.com", Version: "v1", Kind: "MyResource"} 40 | 41 | // Get takes name of the myResource, and returns the corresponding myResource object, and an error if there is any. 42 | func (c *FakeMyResources) Get(name string, options v1.GetOptions) (result *myresource_v1.MyResource, err error) { 43 | obj, err := c.Fake. 44 | Invokes(testing.NewGetAction(myresourcesResource, c.ns, name), &myresource_v1.MyResource{}) 45 | 46 | if obj == nil { 47 | return nil, err 48 | } 49 | return obj.(*myresource_v1.MyResource), err 50 | } 51 | 52 | // List takes label and field selectors, and returns the list of MyResources that match those selectors. 53 | func (c *FakeMyResources) List(opts v1.ListOptions) (result *myresource_v1.MyResourceList, err error) { 54 | obj, err := c.Fake. 55 | Invokes(testing.NewListAction(myresourcesResource, myresourcesKind, c.ns, opts), &myresource_v1.MyResourceList{}) 56 | 57 | if obj == nil { 58 | return nil, err 59 | } 60 | 61 | label, _, _ := testing.ExtractFromListOptions(opts) 62 | if label == nil { 63 | label = labels.Everything() 64 | } 65 | list := &myresource_v1.MyResourceList{} 66 | for _, item := range obj.(*myresource_v1.MyResourceList).Items { 67 | if label.Matches(labels.Set(item.Labels)) { 68 | list.Items = append(list.Items, item) 69 | } 70 | } 71 | return list, err 72 | } 73 | 74 | // Watch returns a watch.Interface that watches the requested myResources. 75 | func (c *FakeMyResources) Watch(opts v1.ListOptions) (watch.Interface, error) { 76 | return c.Fake. 77 | InvokesWatch(testing.NewWatchAction(myresourcesResource, c.ns, opts)) 78 | 79 | } 80 | 81 | // Create takes the representation of a myResource and creates it. Returns the server's representation of the myResource, and an error, if there is any. 82 | func (c *FakeMyResources) Create(myResource *myresource_v1.MyResource) (result *myresource_v1.MyResource, err error) { 83 | obj, err := c.Fake. 84 | Invokes(testing.NewCreateAction(myresourcesResource, c.ns, myResource), &myresource_v1.MyResource{}) 85 | 86 | if obj == nil { 87 | return nil, err 88 | } 89 | return obj.(*myresource_v1.MyResource), err 90 | } 91 | 92 | // Update takes the representation of a myResource and updates it. Returns the server's representation of the myResource, and an error, if there is any. 93 | func (c *FakeMyResources) Update(myResource *myresource_v1.MyResource) (result *myresource_v1.MyResource, err error) { 94 | obj, err := c.Fake. 95 | Invokes(testing.NewUpdateAction(myresourcesResource, c.ns, myResource), &myresource_v1.MyResource{}) 96 | 97 | if obj == nil { 98 | return nil, err 99 | } 100 | return obj.(*myresource_v1.MyResource), err 101 | } 102 | 103 | // Delete takes name of the myResource and deletes it. Returns an error if one occurs. 104 | func (c *FakeMyResources) Delete(name string, options *v1.DeleteOptions) error { 105 | _, err := c.Fake. 106 | Invokes(testing.NewDeleteAction(myresourcesResource, c.ns, name), &myresource_v1.MyResource{}) 107 | 108 | return err 109 | } 110 | 111 | // DeleteCollection deletes a collection of objects. 112 | func (c *FakeMyResources) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 113 | action := testing.NewDeleteCollectionAction(myresourcesResource, c.ns, listOptions) 114 | 115 | _, err := c.Fake.Invokes(action, &myresource_v1.MyResourceList{}) 116 | return err 117 | } 118 | 119 | // Patch applies the patch and returns the patched myResource. 120 | func (c *FakeMyResources) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *myresource_v1.MyResource, err error) { 121 | obj, err := c.Fake. 122 | Invokes(testing.NewPatchSubresourceAction(myresourcesResource, c.ns, name, data, subresources...), &myresource_v1.MyResource{}) 123 | 124 | if obj == nil { 125 | return nil, err 126 | } 127 | return obj.(*myresource_v1.MyResource), err 128 | } 129 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/fake/fake_myresource_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/typed/myresource/v1" 23 | rest "k8s.io/client-go/rest" 24 | testing "k8s.io/client-go/testing" 25 | ) 26 | 27 | type FakeTrstringerV1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeTrstringerV1) MyResources(namespace string) v1.MyResourceInterface { 32 | return &FakeMyResources{c, namespace} 33 | } 34 | 35 | // RESTClient returns a RESTClient that is used to communicate 36 | // with API server by this client implementation. 37 | func (c *FakeTrstringerV1) RESTClient() rest.Interface { 38 | var ret *rest.RESTClient 39 | return ret 40 | } 41 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | type MyResourceExpansion interface{} 22 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/myresource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | scheme "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/scheme" 24 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | types "k8s.io/apimachinery/pkg/types" 26 | watch "k8s.io/apimachinery/pkg/watch" 27 | rest "k8s.io/client-go/rest" 28 | ) 29 | 30 | // MyResourcesGetter has a method to return a MyResourceInterface. 31 | // A group's client should implement this interface. 32 | type MyResourcesGetter interface { 33 | MyResources(namespace string) MyResourceInterface 34 | } 35 | 36 | // MyResourceInterface has methods to work with MyResource resources. 37 | type MyResourceInterface interface { 38 | Create(*v1.MyResource) (*v1.MyResource, error) 39 | Update(*v1.MyResource) (*v1.MyResource, error) 40 | Delete(name string, options *meta_v1.DeleteOptions) error 41 | DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error 42 | Get(name string, options meta_v1.GetOptions) (*v1.MyResource, error) 43 | List(opts meta_v1.ListOptions) (*v1.MyResourceList, error) 44 | Watch(opts meta_v1.ListOptions) (watch.Interface, error) 45 | Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.MyResource, err error) 46 | MyResourceExpansion 47 | } 48 | 49 | // myResources implements MyResourceInterface 50 | type myResources struct { 51 | client rest.Interface 52 | ns string 53 | } 54 | 55 | // newMyResources returns a MyResources 56 | func newMyResources(c *TrstringerV1Client, namespace string) *myResources { 57 | return &myResources{ 58 | client: c.RESTClient(), 59 | ns: namespace, 60 | } 61 | } 62 | 63 | // Get takes name of the myResource, and returns the corresponding myResource object, and an error if there is any. 64 | func (c *myResources) Get(name string, options meta_v1.GetOptions) (result *v1.MyResource, err error) { 65 | result = &v1.MyResource{} 66 | err = c.client.Get(). 67 | Namespace(c.ns). 68 | Resource("myresources"). 69 | Name(name). 70 | VersionedParams(&options, scheme.ParameterCodec). 71 | Do(). 72 | Into(result) 73 | return 74 | } 75 | 76 | // List takes label and field selectors, and returns the list of MyResources that match those selectors. 77 | func (c *myResources) List(opts meta_v1.ListOptions) (result *v1.MyResourceList, err error) { 78 | result = &v1.MyResourceList{} 79 | err = c.client.Get(). 80 | Namespace(c.ns). 81 | Resource("myresources"). 82 | VersionedParams(&opts, scheme.ParameterCodec). 83 | Do(). 84 | Into(result) 85 | return 86 | } 87 | 88 | // Watch returns a watch.Interface that watches the requested myResources. 89 | func (c *myResources) Watch(opts meta_v1.ListOptions) (watch.Interface, error) { 90 | opts.Watch = true 91 | return c.client.Get(). 92 | Namespace(c.ns). 93 | Resource("myresources"). 94 | VersionedParams(&opts, scheme.ParameterCodec). 95 | Watch() 96 | } 97 | 98 | // Create takes the representation of a myResource and creates it. Returns the server's representation of the myResource, and an error, if there is any. 99 | func (c *myResources) Create(myResource *v1.MyResource) (result *v1.MyResource, err error) { 100 | result = &v1.MyResource{} 101 | err = c.client.Post(). 102 | Namespace(c.ns). 103 | Resource("myresources"). 104 | Body(myResource). 105 | Do(). 106 | Into(result) 107 | return 108 | } 109 | 110 | // Update takes the representation of a myResource and updates it. Returns the server's representation of the myResource, and an error, if there is any. 111 | func (c *myResources) Update(myResource *v1.MyResource) (result *v1.MyResource, err error) { 112 | result = &v1.MyResource{} 113 | err = c.client.Put(). 114 | Namespace(c.ns). 115 | Resource("myresources"). 116 | Name(myResource.Name). 117 | Body(myResource). 118 | Do(). 119 | Into(result) 120 | return 121 | } 122 | 123 | // Delete takes name of the myResource and deletes it. Returns an error if one occurs. 124 | func (c *myResources) Delete(name string, options *meta_v1.DeleteOptions) error { 125 | return c.client.Delete(). 126 | Namespace(c.ns). 127 | Resource("myresources"). 128 | Name(name). 129 | Body(options). 130 | Do(). 131 | Error() 132 | } 133 | 134 | // DeleteCollection deletes a collection of objects. 135 | func (c *myResources) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error { 136 | return c.client.Delete(). 137 | Namespace(c.ns). 138 | Resource("myresources"). 139 | VersionedParams(&listOptions, scheme.ParameterCodec). 140 | Body(options). 141 | Do(). 142 | Error() 143 | } 144 | 145 | // Patch applies the patch and returns the patched myResource. 146 | func (c *myResources) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.MyResource, err error) { 147 | result = &v1.MyResource{} 148 | err = c.client.Patch(pt). 149 | Namespace(c.ns). 150 | Resource("myresources"). 151 | SubResource(subresources...). 152 | Name(name). 153 | Body(data). 154 | Do(). 155 | Into(result) 156 | return 157 | } 158 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/myresource/v1/myresource_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned/scheme" 24 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 25 | rest "k8s.io/client-go/rest" 26 | ) 27 | 28 | type TrstringerV1Interface interface { 29 | RESTClient() rest.Interface 30 | MyResourcesGetter 31 | } 32 | 33 | // TrstringerV1Client is used to interact with features provided by the trstringer.com group. 34 | type TrstringerV1Client struct { 35 | restClient rest.Interface 36 | } 37 | 38 | func (c *TrstringerV1Client) MyResources(namespace string) MyResourceInterface { 39 | return newMyResources(c, namespace) 40 | } 41 | 42 | // NewForConfig creates a new TrstringerV1Client for the given config. 43 | func NewForConfig(c *rest.Config) (*TrstringerV1Client, error) { 44 | config := *c 45 | if err := setConfigDefaults(&config); err != nil { 46 | return nil, err 47 | } 48 | client, err := rest.RESTClientFor(&config) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return &TrstringerV1Client{client}, nil 53 | } 54 | 55 | // NewForConfigOrDie creates a new TrstringerV1Client for the given config and 56 | // panics if there is an error in the config. 57 | func NewForConfigOrDie(c *rest.Config) *TrstringerV1Client { 58 | client, err := NewForConfig(c) 59 | if err != nil { 60 | panic(err) 61 | } 62 | return client 63 | } 64 | 65 | // New creates a new TrstringerV1Client for the given RESTClient. 66 | func New(c rest.Interface) *TrstringerV1Client { 67 | return &TrstringerV1Client{c} 68 | } 69 | 70 | func setConfigDefaults(config *rest.Config) error { 71 | gv := v1.SchemeGroupVersion 72 | config.GroupVersion = &gv 73 | config.APIPath = "/apis" 74 | config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} 75 | 76 | if config.UserAgent == "" { 77 | config.UserAgent = rest.DefaultKubernetesUserAgent() 78 | } 79 | 80 | return nil 81 | } 82 | 83 | // RESTClient returns a RESTClient that is used to communicate 84 | // with API server by this client implementation. 85 | func (c *TrstringerV1Client) RESTClient() rest.Interface { 86 | if c == nil { 87 | return nil 88 | } 89 | return c.restClient 90 | } 91 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/factory.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | reflect "reflect" 23 | sync "sync" 24 | time "time" 25 | 26 | versioned "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned" 27 | internalinterfaces "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/internalinterfaces" 28 | myresource "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/myresource" 29 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | runtime "k8s.io/apimachinery/pkg/runtime" 31 | schema "k8s.io/apimachinery/pkg/runtime/schema" 32 | cache "k8s.io/client-go/tools/cache" 33 | ) 34 | 35 | // SharedInformerOption defines the functional option type for SharedInformerFactory. 36 | type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory 37 | 38 | type sharedInformerFactory struct { 39 | client versioned.Interface 40 | namespace string 41 | tweakListOptions internalinterfaces.TweakListOptionsFunc 42 | lock sync.Mutex 43 | defaultResync time.Duration 44 | customResync map[reflect.Type]time.Duration 45 | 46 | informers map[reflect.Type]cache.SharedIndexInformer 47 | // startedInformers is used for tracking which informers have been started. 48 | // This allows Start() to be called multiple times safely. 49 | startedInformers map[reflect.Type]bool 50 | } 51 | 52 | // WithCustomResyncConfig sets a custom resync period for the specified informer types. 53 | func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { 54 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 55 | for k, v := range resyncConfig { 56 | factory.customResync[reflect.TypeOf(k)] = v 57 | } 58 | return factory 59 | } 60 | } 61 | 62 | // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. 63 | func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { 64 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 65 | factory.tweakListOptions = tweakListOptions 66 | return factory 67 | } 68 | } 69 | 70 | // WithNamespace limits the SharedInformerFactory to the specified namespace. 71 | func WithNamespace(namespace string) SharedInformerOption { 72 | return func(factory *sharedInformerFactory) *sharedInformerFactory { 73 | factory.namespace = namespace 74 | return factory 75 | } 76 | } 77 | 78 | // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. 79 | func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { 80 | return NewSharedInformerFactoryWithOptions(client, defaultResync) 81 | } 82 | 83 | // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. 84 | // Listers obtained via this SharedInformerFactory will be subject to the same filters 85 | // as specified here. 86 | // Deprecated: Please use NewSharedInformerFactoryWithOptions instead 87 | func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { 88 | return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) 89 | } 90 | 91 | // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. 92 | func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { 93 | factory := &sharedInformerFactory{ 94 | client: client, 95 | namespace: v1.NamespaceAll, 96 | defaultResync: defaultResync, 97 | informers: make(map[reflect.Type]cache.SharedIndexInformer), 98 | startedInformers: make(map[reflect.Type]bool), 99 | customResync: make(map[reflect.Type]time.Duration), 100 | } 101 | 102 | // Apply all options 103 | for _, opt := range options { 104 | factory = opt(factory) 105 | } 106 | 107 | return factory 108 | } 109 | 110 | // Start initializes all requested informers. 111 | func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { 112 | f.lock.Lock() 113 | defer f.lock.Unlock() 114 | 115 | for informerType, informer := range f.informers { 116 | if !f.startedInformers[informerType] { 117 | go informer.Run(stopCh) 118 | f.startedInformers[informerType] = true 119 | } 120 | } 121 | } 122 | 123 | // WaitForCacheSync waits for all started informers' cache were synced. 124 | func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { 125 | informers := func() map[reflect.Type]cache.SharedIndexInformer { 126 | f.lock.Lock() 127 | defer f.lock.Unlock() 128 | 129 | informers := map[reflect.Type]cache.SharedIndexInformer{} 130 | for informerType, informer := range f.informers { 131 | if f.startedInformers[informerType] { 132 | informers[informerType] = informer 133 | } 134 | } 135 | return informers 136 | }() 137 | 138 | res := map[reflect.Type]bool{} 139 | for informType, informer := range informers { 140 | res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) 141 | } 142 | return res 143 | } 144 | 145 | // InternalInformerFor returns the SharedIndexInformer for obj using an internal 146 | // client. 147 | func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { 148 | f.lock.Lock() 149 | defer f.lock.Unlock() 150 | 151 | informerType := reflect.TypeOf(obj) 152 | informer, exists := f.informers[informerType] 153 | if exists { 154 | return informer 155 | } 156 | 157 | resyncPeriod, exists := f.customResync[informerType] 158 | if !exists { 159 | resyncPeriod = f.defaultResync 160 | } 161 | 162 | informer = newFunc(f.client, resyncPeriod) 163 | f.informers[informerType] = informer 164 | 165 | return informer 166 | } 167 | 168 | // SharedInformerFactory provides shared informers for resources in all known 169 | // API group versions. 170 | type SharedInformerFactory interface { 171 | internalinterfaces.SharedInformerFactory 172 | ForResource(resource schema.GroupVersionResource) (GenericInformer, error) 173 | WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool 174 | 175 | Trstringer() myresource.Interface 176 | } 177 | 178 | func (f *sharedInformerFactory) Trstringer() myresource.Interface { 179 | return myresource.New(f, f.namespace, f.tweakListOptions) 180 | } 181 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | "fmt" 23 | 24 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=trstringer.com, Version=v1 56 | case v1.SchemeGroupVersion.WithResource("myresources"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Trstringer().V1().MyResources().Informer()}, nil 58 | 59 | } 60 | 61 | return nil, fmt.Errorf("no informer found for %v", resource) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package internalinterfaces 20 | 21 | import ( 22 | time "time" 23 | 24 | versioned "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned" 25 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | runtime "k8s.io/apimachinery/pkg/runtime" 27 | cache "k8s.io/client-go/tools/cache" 28 | ) 29 | 30 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 31 | 32 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 33 | type SharedInformerFactory interface { 34 | Start(stopCh <-chan struct{}) 35 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 36 | } 37 | 38 | type TweakListOptionsFunc func(*v1.ListOptions) 39 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/myresource/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package trstringer 20 | 21 | import ( 22 | internalinterfaces "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/internalinterfaces" 23 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/myresource/v1" 24 | ) 25 | 26 | // Interface provides access to each of this group's versions. 27 | type Interface interface { 28 | // V1 provides access to shared informers for resources in V1. 29 | V1() v1.Interface 30 | } 31 | 32 | type group struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // V1 returns a new v1.Interface. 44 | func (g *group) V1() v1.Interface { 45 | return v1.New(g.factory, g.namespace, g.tweakListOptions) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/myresource/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | internalinterfaces "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to all the informers in this group version. 26 | type Interface interface { 27 | // MyResources returns a MyResourceInformer. 28 | MyResources() MyResourceInformer 29 | } 30 | 31 | type version struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // MyResources returns a MyResourceInformer. 43 | func (v *version) MyResources() MyResourceInformer { 44 | return &myResourceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 45 | } 46 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/myresource/v1/myresource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | time "time" 23 | 24 | myresource_v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 25 | versioned "github.com/trstringer/k8s-controller-custom-resource/pkg/client/clientset/versioned" 26 | internalinterfaces "github.com/trstringer/k8s-controller-custom-resource/pkg/client/informers/externalversions/internalinterfaces" 27 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/client/listers/myresource/v1" 28 | meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | runtime "k8s.io/apimachinery/pkg/runtime" 30 | watch "k8s.io/apimachinery/pkg/watch" 31 | cache "k8s.io/client-go/tools/cache" 32 | ) 33 | 34 | // MyResourceInformer provides access to a shared informer and lister for 35 | // MyResources. 36 | type MyResourceInformer interface { 37 | Informer() cache.SharedIndexInformer 38 | Lister() v1.MyResourceLister 39 | } 40 | 41 | type myResourceInformer struct { 42 | factory internalinterfaces.SharedInformerFactory 43 | tweakListOptions internalinterfaces.TweakListOptionsFunc 44 | namespace string 45 | } 46 | 47 | // NewMyResourceInformer constructs a new informer for MyResource type. 48 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 49 | // one. This reduces memory footprint and number of connections to the server. 50 | func NewMyResourceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 51 | return NewFilteredMyResourceInformer(client, namespace, resyncPeriod, indexers, nil) 52 | } 53 | 54 | // NewFilteredMyResourceInformer constructs a new informer for MyResource type. 55 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 56 | // one. This reduces memory footprint and number of connections to the server. 57 | func NewFilteredMyResourceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 58 | return cache.NewSharedIndexInformer( 59 | &cache.ListWatch{ 60 | ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) { 61 | if tweakListOptions != nil { 62 | tweakListOptions(&options) 63 | } 64 | return client.TrstringerV1().MyResources(namespace).List(options) 65 | }, 66 | WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) { 67 | if tweakListOptions != nil { 68 | tweakListOptions(&options) 69 | } 70 | return client.TrstringerV1().MyResources(namespace).Watch(options) 71 | }, 72 | }, 73 | &myresource_v1.MyResource{}, 74 | resyncPeriod, 75 | indexers, 76 | ) 77 | } 78 | 79 | func (f *myResourceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 80 | return NewFilteredMyResourceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 81 | } 82 | 83 | func (f *myResourceInformer) Informer() cache.SharedIndexInformer { 84 | return f.factory.InformerFor(&myresource_v1.MyResource{}, f.defaultInformer) 85 | } 86 | 87 | func (f *myResourceInformer) Lister() v1.MyResourceLister { 88 | return v1.NewMyResourceLister(f.Informer().GetIndexer()) 89 | } 90 | -------------------------------------------------------------------------------- /pkg/client/listers/myresource/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | // MyResourceListerExpansion allows custom methods to be added to 22 | // MyResourceLister. 23 | type MyResourceListerExpansion interface{} 24 | 25 | // MyResourceNamespaceListerExpansion allows custom methods to be added to 26 | // MyResourceNamespaceLister. 27 | type MyResourceNamespaceListerExpansion interface{} 28 | -------------------------------------------------------------------------------- /pkg/client/listers/myresource/v1/myresource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | v1 "github.com/trstringer/k8s-controller-custom-resource/pkg/apis/myresource/v1" 23 | "k8s.io/apimachinery/pkg/api/errors" 24 | "k8s.io/apimachinery/pkg/labels" 25 | "k8s.io/client-go/tools/cache" 26 | ) 27 | 28 | // MyResourceLister helps list MyResources. 29 | type MyResourceLister interface { 30 | // List lists all MyResources in the indexer. 31 | List(selector labels.Selector) (ret []*v1.MyResource, err error) 32 | // MyResources returns an object that can list and get MyResources. 33 | MyResources(namespace string) MyResourceNamespaceLister 34 | MyResourceListerExpansion 35 | } 36 | 37 | // myResourceLister implements the MyResourceLister interface. 38 | type myResourceLister struct { 39 | indexer cache.Indexer 40 | } 41 | 42 | // NewMyResourceLister returns a new MyResourceLister. 43 | func NewMyResourceLister(indexer cache.Indexer) MyResourceLister { 44 | return &myResourceLister{indexer: indexer} 45 | } 46 | 47 | // List lists all MyResources in the indexer. 48 | func (s *myResourceLister) List(selector labels.Selector) (ret []*v1.MyResource, err error) { 49 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 50 | ret = append(ret, m.(*v1.MyResource)) 51 | }) 52 | return ret, err 53 | } 54 | 55 | // MyResources returns an object that can list and get MyResources. 56 | func (s *myResourceLister) MyResources(namespace string) MyResourceNamespaceLister { 57 | return myResourceNamespaceLister{indexer: s.indexer, namespace: namespace} 58 | } 59 | 60 | // MyResourceNamespaceLister helps list and get MyResources. 61 | type MyResourceNamespaceLister interface { 62 | // List lists all MyResources in the indexer for a given namespace. 63 | List(selector labels.Selector) (ret []*v1.MyResource, err error) 64 | // Get retrieves the MyResource from the indexer for a given namespace and name. 65 | Get(name string) (*v1.MyResource, error) 66 | MyResourceNamespaceListerExpansion 67 | } 68 | 69 | // myResourceNamespaceLister implements the MyResourceNamespaceLister 70 | // interface. 71 | type myResourceNamespaceLister struct { 72 | indexer cache.Indexer 73 | namespace string 74 | } 75 | 76 | // List lists all MyResources in the indexer for a given namespace. 77 | func (s myResourceNamespaceLister) List(selector labels.Selector) (ret []*v1.MyResource, err error) { 78 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 79 | ret = append(ret, m.(*v1.MyResource)) 80 | }) 81 | return ret, err 82 | } 83 | 84 | // Get retrieves the MyResource from the indexer for a given namespace and name. 85 | func (s myResourceNamespaceLister) Get(name string) (*v1.MyResource, error) { 86 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 87 | if err != nil { 88 | return nil, err 89 | } 90 | if !exists { 91 | return nil, errors.NewNotFound(v1.Resource("myresource"), name) 92 | } 93 | return obj.(*v1.MyResource), nil 94 | } 95 | --------------------------------------------------------------------------------