├── .dockerignore ├── .gitignore ├── .header ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── Makefile ├── README.md ├── build ├── Dockerfile └── bin │ ├── entrypoint │ └── user_setup ├── cmd └── manager │ └── main.go ├── deploy ├── cluster_role.yaml ├── cluster_role_binding.yaml ├── crds │ └── maegus_v1beta1_proxier_crd.yaml ├── operator.yaml ├── proxier.yaml └── service_account.yaml ├── examples ├── busybox.yaml ├── echo.yaml └── proxier.yaml ├── go.mod ├── go.sum ├── hack ├── docker-image-exists.sh ├── make-release.sh └── update-gofmt.sh ├── images ├── proxier-architecture.png └── proxier-banner.png ├── pkg ├── apis │ ├── addto_scheme_maegus_v1beta1.go │ ├── apis.go │ └── maegus │ │ └── v1beta1 │ │ ├── annotations.go │ │ ├── doc.go │ │ ├── labels.go │ │ ├── proxier_types.go │ │ ├── register.go │ │ ├── zz_generated.deepcopy.go │ │ ├── zz_generated.defaults.go │ │ └── zz_generated.openapi.go ├── client │ ├── informers │ │ └── externalversions │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ ├── internalinterfaces │ │ │ └── factory_interfaces.go │ │ │ └── maegus │ │ │ ├── interface.go │ │ │ └── v1beta1 │ │ │ ├── interface.go │ │ │ └── proxier.go │ ├── listers │ │ └── maegus │ │ │ └── v1beta1 │ │ │ ├── expansion_generated.go │ │ │ └── proxier.go │ └── versioned │ │ ├── clientset.go │ │ ├── doc.go │ │ ├── fake │ │ ├── clientset_generated.go │ │ ├── doc.go │ │ └── register.go │ │ ├── scheme │ │ ├── doc.go │ │ └── register.go │ │ └── typed │ │ └── maegus │ │ └── v1beta1 │ │ ├── doc.go │ │ ├── fake │ │ ├── doc.go │ │ ├── fake_maegus_client.go │ │ └── fake_proxier.go │ │ ├── generated_expansion.go │ │ ├── maegus_client.go │ │ └── proxier.go └── controller │ ├── add_proxier.go │ ├── controller.go │ └── proxier │ ├── deployment.go │ ├── label.go │ ├── label_test.go │ ├── nginx │ └── nginx.go │ ├── proxier_controller.go │ ├── servers.go │ ├── servers_test.go │ └── utils.go ├── test ├── e2e │ ├── const.go │ ├── main_test.go │ └── proxier_test.go ├── fixtures │ ├── echo-v1.yaml │ └── echo-v2.yaml └── framework │ ├── cluster_role.go │ ├── cluster_role_binding.go │ ├── context.go │ ├── crd.go │ ├── deployment.go │ ├── framework.go │ ├── helpers.go │ ├── namespace.go │ ├── pod.go │ ├── proxier.go │ ├── role_binding.go │ ├── service.go │ └── service_account.go └── version └── version.go /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | .DS_Store 3 | .gitignore 4 | README.md 5 | test/ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Temporary Build Files 2 | build/_output 3 | build/_test 4 | # Created by https://www.gitignore.io/api/go,vim,emacs,visualstudiocode 5 | ### Emacs ### 6 | # -*- mode: gitignore; -*- 7 | *~ 8 | \#*\# 9 | /.emacs.desktop 10 | /.emacs.desktop.lock 11 | *.elc 12 | auto-save-list 13 | tramp 14 | .\#* 15 | # Org-mode 16 | .org-id-locations 17 | *_archive 18 | # flymake-mode 19 | *_flymake.* 20 | # eshell files 21 | /eshell/history 22 | /eshell/lastdir 23 | # elpa packages 24 | /elpa/ 25 | # reftex files 26 | *.rel 27 | # AUCTeX auto folder 28 | /auto/ 29 | # cask packages 30 | .cask/ 31 | dist/ 32 | # Flycheck 33 | flycheck_*.el 34 | # server auth directory 35 | /server/ 36 | # projectiles files 37 | .projectile 38 | projectile-bookmarks.eld 39 | # directory configuration 40 | .dir-locals.el 41 | # saveplace 42 | places 43 | # url cache 44 | url/cache/ 45 | # cedet 46 | ede-projects.el 47 | # smex 48 | smex-items 49 | # company-statistics 50 | company-statistics-cache.el 51 | # anaconda-mode 52 | anaconda-mode/ 53 | ### Go ### 54 | # Binaries for programs and plugins 55 | *.exe 56 | *.exe~ 57 | *.dll 58 | *.so 59 | *.dylib 60 | # Test binary, build with 'go test -c' 61 | *.test 62 | # Output of the go coverage tool, specifically when used with LiteIDE 63 | *.out 64 | ### Vim ### 65 | # swap 66 | .sw[a-p] 67 | .*.sw[a-p] 68 | # session 69 | Session.vim 70 | # temporary 71 | .netrwhist 72 | # auto-generated tag files 73 | tags 74 | ### VisualStudioCode ### 75 | .vscode/* 76 | .history 77 | # End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode 78 | vendor/ 79 | 80 | .DS_Store 81 | .envrc 82 | -------------------------------------------------------------------------------- /.header: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draveness/proxier/35097528b53c110db89dfa918bee2164bf49f05d/.header -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:7822ce8f5713343d4fe56fe04f39b999213a4318c08dbe7d5eb1743fbbcf9e6e" 6 | name = "cloud.google.com/go" 7 | packages = ["compute/metadata"] 8 | pruneopts = "NT" 9 | revision = "fcb9a2d5f791d07be64506ab54434de65989d370" 10 | version = "v0.37.4" 11 | 12 | [[projects]] 13 | digest = "1:0a111edd8693fd977f42a0c4f199a0efb13c20aec9da99ad8830c7bb6a87e8d6" 14 | name = "github.com/PuerkitoBio/purell" 15 | packages = ["."] 16 | pruneopts = "NT" 17 | revision = "44968752391892e1b0d0b821ee79e9a85fa13049" 18 | version = "v1.1.1" 19 | 20 | [[projects]] 21 | branch = "master" 22 | digest = "1:8098cd40cd09879efbf12e33bcd51ead4a66006ac802cd563a66c4f3373b9727" 23 | name = "github.com/PuerkitoBio/urlesc" 24 | packages = ["."] 25 | pruneopts = "NT" 26 | revision = "de5bf2ad457846296e2031421a34e2568e304e35" 27 | 28 | [[projects]] 29 | digest = "1:680b63a131506e668818d630d3ca36123ff290afa0afc9f4be21940adca3f27d" 30 | name = "github.com/appscode/jsonpatch" 31 | packages = ["."] 32 | pruneopts = "NT" 33 | revision = "7c0e3b262f30165a8ec3d0b4c6059fd92703bfb2" 34 | version = "1.0.0" 35 | 36 | [[projects]] 37 | digest = "1:c819830f4f5ef85874a90ac3cbcc96cd322c715f5c96fbe4722eacd3dafbaa07" 38 | name = "github.com/beorn7/perks" 39 | packages = ["quantile"] 40 | pruneopts = "NT" 41 | revision = "4b2b341e8d7715fae06375aa633dbb6e91b3fb46" 42 | version = "v1.0.0" 43 | 44 | [[projects]] 45 | digest = "1:0c4193043b1a33c7f9ba4ea42b8af2c09bb3d51970212d42e4dac8aa217b4ca5" 46 | name = "github.com/coreos/prometheus-operator" 47 | packages = [ 48 | "pkg/apis/monitoring", 49 | "pkg/apis/monitoring/v1", 50 | "pkg/client/versioned/scheme", 51 | "pkg/client/versioned/typed/monitoring/v1", 52 | ] 53 | pruneopts = "NT" 54 | revision = "7a25bf6b6bb2347dacb235659b73bc210117acc7" 55 | version = "v0.29.0" 56 | 57 | [[projects]] 58 | digest = "1:4b8b5811da6970495e04d1f4e98bb89518cc3cfc3b3f456bdb876ed7b6c74049" 59 | name = "github.com/davecgh/go-spew" 60 | packages = ["spew"] 61 | pruneopts = "NT" 62 | revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" 63 | version = "v1.1.1" 64 | 65 | [[projects]] 66 | digest = "1:1302bdd23af4264a095d48c2c28660a8ecf2e02454ce172cef5cb946029a1383" 67 | name = "github.com/emicklei/go-restful" 68 | packages = [ 69 | ".", 70 | "log", 71 | ] 72 | pruneopts = "NT" 73 | revision = "b9bbc5664f49b6deec52393bd68f39830687a347" 74 | version = "v2.9.3" 75 | 76 | [[projects]] 77 | digest = "1:820227d03dc661d34f837f3704626d2837dbfbf9f0ec8fdf1f58e683dc5f56fc" 78 | name = "github.com/evanphx/json-patch" 79 | packages = ["."] 80 | pruneopts = "NT" 81 | revision = "72bf35d0ff611848c1dc9df0f976c81192392fa5" 82 | version = "v4.1.0" 83 | 84 | [[projects]] 85 | digest = "1:81466b4218bf6adddac2572a30ac733a9255919bc2f470b4827a317bd4ee1756" 86 | name = "github.com/ghodss/yaml" 87 | packages = ["."] 88 | pruneopts = "NT" 89 | revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" 90 | version = "v1.0.0" 91 | 92 | [[projects]] 93 | digest = "1:d421af4c4fe51d399667d573982d663fe1fa67020a88d3ae43466ebfe8e2b5c9" 94 | name = "github.com/go-logr/logr" 95 | packages = ["."] 96 | pruneopts = "NT" 97 | revision = "9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e" 98 | version = "v0.1.0" 99 | 100 | [[projects]] 101 | digest = "1:340497a512995aa69c0add901d79a2096b3449d35a44a6f1f1115091a9f8c687" 102 | name = "github.com/go-logr/zapr" 103 | packages = ["."] 104 | pruneopts = "NT" 105 | revision = "03f06a783fbb7dfaf3f629c7825480e43a7105e6" 106 | version = "v0.1.1" 107 | 108 | [[projects]] 109 | digest = "1:260f7ebefc63024c8dfe2c9f1a2935a89fa4213637a1f522f592f80c001cc441" 110 | name = "github.com/go-openapi/jsonpointer" 111 | packages = ["."] 112 | pruneopts = "NT" 113 | revision = "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" 114 | version = "v0.19.0" 115 | 116 | [[projects]] 117 | digest = "1:98abd61947ff5c7c6fcfec5473d02a4821ed3a2dd99a4fbfdb7925b0dd745546" 118 | name = "github.com/go-openapi/jsonreference" 119 | packages = ["."] 120 | pruneopts = "NT" 121 | revision = "8483a886a90412cd6858df4ea3483dce9c8e35a3" 122 | version = "v0.19.0" 123 | 124 | [[projects]] 125 | branch = "master" 126 | digest = "1:ac672f42180ef887536774396f5a79b4f426b6338f46bbe17a6ef8da9adc24ea" 127 | name = "github.com/go-openapi/spec" 128 | packages = ["."] 129 | pruneopts = "NT" 130 | revision = "9d9763c0ce87242cb4611b52b8601987f01eb4ed" 131 | 132 | [[projects]] 133 | digest = "1:076ebf43e6e70f18ef9d079a685ede59a0f4dc9247256c209cf57407f959cef9" 134 | name = "github.com/go-openapi/swag" 135 | packages = ["."] 136 | pruneopts = "NT" 137 | revision = "b3e2804c8535ee0d1b89320afd98474d5b8e9e3b" 138 | version = "v0.19.0" 139 | 140 | [[projects]] 141 | digest = "1:53151cc4366e3945282d4b783fd41f35222cabbc75601e68d8133648c63498d1" 142 | name = "github.com/gobuffalo/envy" 143 | packages = ["."] 144 | pruneopts = "NT" 145 | revision = "043cb4b8af871b49563291e32c66bb84378a60ac" 146 | version = "v1.7.0" 147 | 148 | [[projects]] 149 | digest = "1:0b39706cfa32c1ba9e14435b5844d04aef81b60f44b6077e61e0607d56692603" 150 | name = "github.com/gogo/protobuf" 151 | packages = [ 152 | "proto", 153 | "sortkeys", 154 | ] 155 | pruneopts = "NT" 156 | revision = "ba06b47c162d49f2af050fb4c75bcbc86a159d5c" 157 | version = "v1.2.1" 158 | 159 | [[projects]] 160 | branch = "master" 161 | digest = "1:e2b86e41f3d669fc36b50d31d32d22c8ac656c75aa5ea89717ce7177e134ff2a" 162 | name = "github.com/golang/glog" 163 | packages = ["."] 164 | pruneopts = "NT" 165 | revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" 166 | 167 | [[projects]] 168 | branch = "master" 169 | digest = "1:20b774dcfdf0fff3148432beb828c52404f3eb3d70b7ce71ae0356ed6cbc2bae" 170 | name = "github.com/golang/groupcache" 171 | packages = ["lru"] 172 | pruneopts = "NT" 173 | revision = "5b532d6fd5efaf7fa130d4e859a2fde0fc3a9e1b" 174 | 175 | [[projects]] 176 | digest = "1:d7212166c4b7f30a20fb3de70ab7e36564900b2e36360ffd31958b5af8fed025" 177 | name = "github.com/golang/protobuf" 178 | packages = [ 179 | "proto", 180 | "ptypes", 181 | "ptypes/any", 182 | "ptypes/duration", 183 | "ptypes/timestamp", 184 | ] 185 | pruneopts = "NT" 186 | revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30" 187 | version = "v1.3.1" 188 | 189 | [[projects]] 190 | digest = "1:05f95ffdfcf651bdb0f05b40b69e7f5663047f8da75c72d58728acb59b5cc107" 191 | name = "github.com/google/btree" 192 | packages = ["."] 193 | pruneopts = "NT" 194 | revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" 195 | version = "v1.0.0" 196 | 197 | [[projects]] 198 | digest = "1:52c5834e2bebac9030c97cc0798ac11c3aa8a39f098aeb419f142533da6cd3cc" 199 | name = "github.com/google/gofuzz" 200 | packages = ["."] 201 | pruneopts = "NT" 202 | revision = "f140a6486e521aad38f5917de355cbf147cc0496" 203 | version = "v1.0.0" 204 | 205 | [[projects]] 206 | digest = "1:ab3ec1fe3e39bac4b3ab63390767766622be35b7cab03f47f787f9ec60522a53" 207 | name = "github.com/google/uuid" 208 | packages = ["."] 209 | pruneopts = "NT" 210 | revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4" 211 | version = "v1.1.1" 212 | 213 | [[projects]] 214 | digest = "1:289332c13b80edfefc88397cce5266c16845dcf204fa2f6ac7e464ee4c7f6e96" 215 | name = "github.com/googleapis/gnostic" 216 | packages = [ 217 | "OpenAPIv2", 218 | "compiler", 219 | "extensions", 220 | ] 221 | pruneopts = "NT" 222 | revision = "7c663266750e7d82587642f65e60bc4083f1f84e" 223 | version = "v0.2.0" 224 | 225 | [[projects]] 226 | branch = "master" 227 | digest = "1:bb7bd892abcb75ef819ce2efab9d54d22b7e38dc05ffac55428bb0578b52912b" 228 | name = "github.com/gregjones/httpcache" 229 | packages = [ 230 | ".", 231 | "diskcache", 232 | ] 233 | pruneopts = "NT" 234 | revision = "3befbb6ad0cc97d4c25d851e9528915809e1a22f" 235 | 236 | [[projects]] 237 | digest = "1:52094d0f8bdf831d1a2401e9b6fee5795fdc0b2a2d1f8bb1980834c289e79129" 238 | name = "github.com/hashicorp/golang-lru" 239 | packages = [ 240 | ".", 241 | "simplelru", 242 | ] 243 | pruneopts = "NT" 244 | revision = "7087cb70de9f7a8bc0a10c375cb0d2280a8edf9c" 245 | version = "v0.5.1" 246 | 247 | [[projects]] 248 | digest = "1:aaa38889f11896ee3644d77e17dc7764cc47f5f3d3b488268df2af2b52541c5f" 249 | name = "github.com/imdario/mergo" 250 | packages = ["."] 251 | pruneopts = "NT" 252 | revision = "7c29201646fa3de8506f701213473dd407f19646" 253 | version = "v0.3.7" 254 | 255 | [[projects]] 256 | digest = "1:f5b9328966ccea0970b1d15075698eff0ddb3e75889560aad2e9f76b289b536a" 257 | name = "github.com/joho/godotenv" 258 | packages = ["."] 259 | pruneopts = "NT" 260 | revision = "23d116af351c84513e1946b527c88823e476be13" 261 | version = "v1.3.0" 262 | 263 | [[projects]] 264 | digest = "1:0fbdc0dfdabfa16d50dd7151b7efe3189ffb0df68fa9866dc35240bfea39ad92" 265 | name = "github.com/json-iterator/go" 266 | packages = ["."] 267 | pruneopts = "NT" 268 | revision = "0ff49de124c6f76f8494e194af75bde0f1a49a29" 269 | version = "v1.1.6" 270 | 271 | [[projects]] 272 | branch = "master" 273 | digest = "1:782fb677791a7fe7b5b8e637bcf695efb13950ce09e3e8e3b1cf21c57649be7c" 274 | name = "github.com/mailru/easyjson" 275 | packages = [ 276 | "buffer", 277 | "jlexer", 278 | "jwriter", 279 | ] 280 | pruneopts = "NT" 281 | revision = "1ea4449da9834f4d333f1cc461c374aea217d249" 282 | 283 | [[projects]] 284 | digest = "1:56dbf15e091bf7926cb33a57cb6bdfc658fc6d3498d2f76f10a97ce7856f1fde" 285 | name = "github.com/markbates/inflect" 286 | packages = ["."] 287 | pruneopts = "NT" 288 | revision = "24b83195037b3bc61fcda2d28b7b0518bce293b6" 289 | version = "v1.0.4" 290 | 291 | [[projects]] 292 | digest = "1:ea1db000388d88b31db7531c83016bef0d6db0d908a07794bfc36aca16fbf935" 293 | name = "github.com/matttproud/golang_protobuf_extensions" 294 | packages = ["pbutil"] 295 | pruneopts = "NT" 296 | revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" 297 | version = "v1.0.1" 298 | 299 | [[projects]] 300 | digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f" 301 | name = "github.com/modern-go/concurrent" 302 | packages = ["."] 303 | pruneopts = "NT" 304 | revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" 305 | version = "1.0.3" 306 | 307 | [[projects]] 308 | digest = "1:c6aca19413b13dc59c220ad7430329e2ec454cc310bc6d8de2c7e2b93c18a0f6" 309 | name = "github.com/modern-go/reflect2" 310 | packages = ["."] 311 | pruneopts = "NT" 312 | revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" 313 | version = "1.0.1" 314 | 315 | [[projects]] 316 | digest = "1:80e823a6d07ef4c89de3b668546939d331ef024a675df821e85ffbc5ab35b98a" 317 | name = "github.com/operator-framework/operator-sdk" 318 | packages = [ 319 | "pkg/k8sutil", 320 | "pkg/leader", 321 | "pkg/log/zap", 322 | "pkg/metrics", 323 | "version", 324 | ] 325 | pruneopts = "NT" 326 | revision = "ff80b17737a6a0aade663e4827e8af3ab5a21170" 327 | version = "v0.10.0" 328 | 329 | [[projects]] 330 | digest = "1:93b1d84c5fa6d1ea52f4114c37714cddd84d5b78f151b62bb101128dd51399bf" 331 | name = "github.com/pborman/uuid" 332 | packages = ["."] 333 | pruneopts = "NT" 334 | revision = "adf5a7427709b9deb95d29d3fa8a2bf9cfd388f1" 335 | version = "v1.2" 336 | 337 | [[projects]] 338 | branch = "master" 339 | digest = "1:bf2ac97824a7221eb16b096aecc1c390d4c8a4e49524386aaa2e2dd215cbfb31" 340 | name = "github.com/petar/GoLLRB" 341 | packages = ["llrb"] 342 | pruneopts = "NT" 343 | revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" 344 | 345 | [[projects]] 346 | digest = "1:e4e9e026b8e4c5630205cd0208efb491b40ad40552e57f7a646bb8a46896077b" 347 | name = "github.com/peterbourgon/diskv" 348 | packages = ["."] 349 | pruneopts = "NT" 350 | revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" 351 | version = "v2.0.1" 352 | 353 | [[projects]] 354 | digest = "1:14715f705ff5dfe0ffd6571d7d201dd8e921030f8070321a79380d8ca4ec1a24" 355 | name = "github.com/pkg/errors" 356 | packages = ["."] 357 | pruneopts = "NT" 358 | revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" 359 | version = "v0.8.1" 360 | 361 | [[projects]] 362 | digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" 363 | name = "github.com/pmezard/go-difflib" 364 | packages = ["difflib"] 365 | pruneopts = "NT" 366 | revision = "792786c7400a136282c1664665ae0a8db921c6c2" 367 | version = "v1.0.0" 368 | 369 | [[projects]] 370 | digest = "1:ec2a29e3bd141038ae5c3d3a4f57db0c341fcc1d98055a607aedd683aed124ee" 371 | name = "github.com/prometheus/client_golang" 372 | packages = [ 373 | "prometheus", 374 | "prometheus/internal", 375 | "prometheus/promhttp", 376 | ] 377 | pruneopts = "NT" 378 | revision = "505eaef017263e299324067d40ca2c48f6a2cf50" 379 | version = "v0.9.2" 380 | 381 | [[projects]] 382 | branch = "master" 383 | digest = "1:c2cc5049e927e2749c0d5163c9f8d924880d83e84befa732b9aad0b6be227bed" 384 | name = "github.com/prometheus/client_model" 385 | packages = ["go"] 386 | pruneopts = "NT" 387 | revision = "fd36f4220a901265f90734c3183c5f0c91daa0b8" 388 | 389 | [[projects]] 390 | digest = "1:f173d6232eefd6f25afe9c603aed065c80adb7e4c9cbc30f534db8792fcebdba" 391 | name = "github.com/prometheus/common" 392 | packages = [ 393 | "expfmt", 394 | "internal/bitbucket.org/ww/goautoneg", 395 | "model", 396 | ] 397 | pruneopts = "NT" 398 | revision = "a82f4c12f983cc2649298185f296632953e50d3e" 399 | version = "v0.3.0" 400 | 401 | [[projects]] 402 | branch = "master" 403 | digest = "1:75f1b9f32d4d204eac68f3427bc4642453fb4fe20f1596ec058757f01dc16e7b" 404 | name = "github.com/prometheus/procfs" 405 | packages = ["."] 406 | pruneopts = "NT" 407 | revision = "8368d24ba045f26503eb745b624d930cbe214c79" 408 | 409 | [[projects]] 410 | digest = "1:a4644e85e1f29f9825a4e61dcdd8244fe7c4db02eead3f508d5a5bdf7924dbbd" 411 | name = "github.com/rogpeppe/go-internal" 412 | packages = [ 413 | "modfile", 414 | "module", 415 | "semver", 416 | ] 417 | pruneopts = "NT" 418 | revision = "438578804ca6f31be148c27683afc419ce47c06e" 419 | version = "v1.3.0" 420 | 421 | [[projects]] 422 | digest = "1:49b6e0d199dc20969bf7c9d14647313e1dd1b102178fad4ca999d8a9584edfab" 423 | name = "github.com/spf13/afero" 424 | packages = [ 425 | ".", 426 | "mem", 427 | ] 428 | pruneopts = "NT" 429 | revision = "588a75ec4f32903aa5e39a2619ba6a4631e28424" 430 | version = "v1.2.2" 431 | 432 | [[projects]] 433 | digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779" 434 | name = "github.com/spf13/pflag" 435 | packages = ["."] 436 | pruneopts = "NT" 437 | revision = "298182f68c66c05229eb03ac171abe6e309ee79a" 438 | version = "v1.0.3" 439 | 440 | [[projects]] 441 | digest = "1:8e8fc2cb42cfa0a18fda0c9c4034092faa7aac773da5efdde8828eb4b96c001d" 442 | name = "github.com/stretchr/testify" 443 | packages = [ 444 | "assert", 445 | "require", 446 | "suite", 447 | ] 448 | pruneopts = "NT" 449 | revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" 450 | version = "v1.3.0" 451 | 452 | [[projects]] 453 | digest = "1:22f696cee54865fb8e9ff91df7b633f6b8f22037a8015253c6b6a71ca82219c7" 454 | name = "go.uber.org/atomic" 455 | packages = ["."] 456 | pruneopts = "NT" 457 | revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289" 458 | version = "v1.3.2" 459 | 460 | [[projects]] 461 | digest = "1:58ca93bdf81bac106ded02226b5395a0595d5346cdc4caa8d9c1f3a5f8f9976e" 462 | name = "go.uber.org/multierr" 463 | packages = ["."] 464 | pruneopts = "NT" 465 | revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a" 466 | version = "v1.1.0" 467 | 468 | [[projects]] 469 | digest = "1:572fa4496563920f3e3107a2294cf2621d6cc4ffd03403fb6397b1bab9fa082a" 470 | name = "go.uber.org/zap" 471 | packages = [ 472 | ".", 473 | "buffer", 474 | "internal/bufferpool", 475 | "internal/color", 476 | "internal/exit", 477 | "zapcore", 478 | ] 479 | pruneopts = "NT" 480 | revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982" 481 | version = "v1.9.1" 482 | 483 | [[projects]] 484 | branch = "master" 485 | digest = "1:98aa4a4a4f424cde92614ade7dac45f66c898e2acb8973f809cf9a424ec625e9" 486 | name = "golang.org/x/crypto" 487 | packages = ["ssh/terminal"] 488 | pruneopts = "NT" 489 | revision = "88737f569e3a9c7ab309cdc09a07fe7fc87233c3" 490 | 491 | [[projects]] 492 | branch = "master" 493 | digest = "1:89cf4e2680b312eb7a1b76f32c29089145b639f578b5fcef106c71ee867921f6" 494 | name = "golang.org/x/net" 495 | packages = [ 496 | "context", 497 | "context/ctxhttp", 498 | "http/httpguts", 499 | "http2", 500 | "http2/hpack", 501 | "idna", 502 | ] 503 | pruneopts = "NT" 504 | revision = "1da14a5a36f220ea3f03470682b737b1dfd5de22" 505 | 506 | [[projects]] 507 | branch = "master" 508 | digest = "1:54c605b4036ec49dbc4c887969128d5ee68140cf0bbec46e67cbb2497e69c15e" 509 | name = "golang.org/x/oauth2" 510 | packages = [ 511 | ".", 512 | "google", 513 | "internal", 514 | "jws", 515 | "jwt", 516 | ] 517 | pruneopts = "NT" 518 | revision = "9f3314589c9a9136388751d9adae6b0ed400978a" 519 | 520 | [[projects]] 521 | branch = "master" 522 | digest = "1:5a0a5ba0bb4fadf7e1c3eaaa48923e0efef23e43243e6038c426288aeef92c42" 523 | name = "golang.org/x/sync" 524 | packages = ["errgroup"] 525 | pruneopts = "NT" 526 | revision = "56d357773e8497dfd526f0727e187720d1093757" 527 | 528 | [[projects]] 529 | branch = "master" 530 | digest = "1:aded639d831ffb2df2531a0298f4bd094b56cb3a79bb212c3b7ebdf5b5f40eb0" 531 | name = "golang.org/x/sys" 532 | packages = [ 533 | "unix", 534 | "windows", 535 | ] 536 | pruneopts = "NT" 537 | revision = "12500544f89f9420afe9529ba8940bf72d294972" 538 | 539 | [[projects]] 540 | digest = "1:8c74f97396ed63cc2ef04ebb5fc37bb032871b8fd890a25991ed40974b00cd2a" 541 | name = "golang.org/x/text" 542 | packages = [ 543 | "collate", 544 | "collate/build", 545 | "internal/colltab", 546 | "internal/gen", 547 | "internal/tag", 548 | "internal/triegen", 549 | "internal/ucd", 550 | "language", 551 | "secure/bidirule", 552 | "transform", 553 | "unicode/bidi", 554 | "unicode/cldr", 555 | "unicode/norm", 556 | "unicode/rangetable", 557 | "width", 558 | ] 559 | pruneopts = "NT" 560 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" 561 | version = "v0.3.0" 562 | 563 | [[projects]] 564 | branch = "master" 565 | digest = "1:9fdc2b55e8e0fafe4b41884091e51e77344f7dc511c5acedcfd98200003bff90" 566 | name = "golang.org/x/time" 567 | packages = ["rate"] 568 | pruneopts = "NT" 569 | revision = "9d24e82272b4f38b78bc8cff74fa936d31ccd8ef" 570 | 571 | [[projects]] 572 | branch = "master" 573 | digest = "1:b2970bf435c7977009f5cb26226cb418287aef82b6cfb662504c300b4a3d6fad" 574 | name = "golang.org/x/tools" 575 | packages = [ 576 | "go/ast/astutil", 577 | "go/gcexportdata", 578 | "go/internal/gcimporter", 579 | "go/internal/packagesdriver", 580 | "go/packages", 581 | "go/types/typeutil", 582 | "imports", 583 | "internal/fastwalk", 584 | "internal/gopathwalk", 585 | "internal/module", 586 | "internal/semver", 587 | ] 588 | pruneopts = "NT" 589 | revision = "4ca4b55e2050cfa75f1a1f72ae10825e80b052a0" 590 | 591 | [[projects]] 592 | digest = "1:711179d92dbef98932acd7afd0dab80b4cf2d97f099f3285c9ba8fa451809fec" 593 | name = "google.golang.org/appengine" 594 | packages = [ 595 | ".", 596 | "internal", 597 | "internal/app_identity", 598 | "internal/base", 599 | "internal/datastore", 600 | "internal/log", 601 | "internal/modules", 602 | "internal/remote_api", 603 | "internal/urlfetch", 604 | "urlfetch", 605 | ] 606 | pruneopts = "NT" 607 | revision = "54a98f90d1c46b7731eb8fb305d2a321c30ef610" 608 | version = "v1.5.0" 609 | 610 | [[projects]] 611 | digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a" 612 | name = "gopkg.in/inf.v0" 613 | packages = ["."] 614 | pruneopts = "NT" 615 | revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" 616 | version = "v0.9.1" 617 | 618 | [[projects]] 619 | digest = "1:18108594151654e9e696b27b181b953f9a90b16bf14d253dd1b397b025a1487f" 620 | name = "gopkg.in/yaml.v2" 621 | packages = ["."] 622 | pruneopts = "NT" 623 | revision = "51d6538a90f86fe93ac480b35f37b2be17fef232" 624 | version = "v2.2.2" 625 | 626 | [[projects]] 627 | digest = "1:18b9b70bdf29da610c0df032cf60ee7526a48756fa44012cc639dcb557335cbc" 628 | name = "k8s.io/api" 629 | packages = [ 630 | "admission/v1beta1", 631 | "admissionregistration/v1alpha1", 632 | "admissionregistration/v1beta1", 633 | "apps/v1", 634 | "apps/v1beta1", 635 | "apps/v1beta2", 636 | "auditregistration/v1alpha1", 637 | "authentication/v1", 638 | "authentication/v1beta1", 639 | "authorization/v1", 640 | "authorization/v1beta1", 641 | "autoscaling/v1", 642 | "autoscaling/v2beta1", 643 | "autoscaling/v2beta2", 644 | "batch/v1", 645 | "batch/v1beta1", 646 | "batch/v2alpha1", 647 | "certificates/v1beta1", 648 | "coordination/v1beta1", 649 | "core/v1", 650 | "events/v1beta1", 651 | "extensions/v1beta1", 652 | "networking/v1", 653 | "policy/v1beta1", 654 | "rbac/v1", 655 | "rbac/v1alpha1", 656 | "rbac/v1beta1", 657 | "scheduling/v1alpha1", 658 | "scheduling/v1beta1", 659 | "settings/v1alpha1", 660 | "storage/v1", 661 | "storage/v1alpha1", 662 | "storage/v1beta1", 663 | ] 664 | pruneopts = "NT" 665 | revision = "5cb15d34447165a97c76ed5a60e4e99c8a01ecfe" 666 | version = "kubernetes-1.13.4" 667 | 668 | [[projects]] 669 | digest = "1:c6f23048e162e65d586c809fd02e263e180ad157f110df17437c22517bb59a4b" 670 | name = "k8s.io/apiextensions-apiserver" 671 | packages = [ 672 | "pkg/apis/apiextensions", 673 | "pkg/apis/apiextensions/v1beta1", 674 | "pkg/client/clientset/clientset", 675 | "pkg/client/clientset/clientset/scheme", 676 | "pkg/client/clientset/clientset/typed/apiextensions/v1beta1", 677 | ] 678 | pruneopts = "NT" 679 | revision = "d002e88f6236312f0289d9d1deab106751718ff0" 680 | version = "kubernetes-1.13.4" 681 | 682 | [[projects]] 683 | digest = "1:f44b5a32a31245ea062cd397cc343bda06d75c731596589996c1f77634e653af" 684 | name = "k8s.io/apimachinery" 685 | packages = [ 686 | "pkg/api/errors", 687 | "pkg/api/meta", 688 | "pkg/api/resource", 689 | "pkg/apis/meta/internalversion", 690 | "pkg/apis/meta/v1", 691 | "pkg/apis/meta/v1/unstructured", 692 | "pkg/apis/meta/v1beta1", 693 | "pkg/conversion", 694 | "pkg/conversion/queryparams", 695 | "pkg/fields", 696 | "pkg/labels", 697 | "pkg/runtime", 698 | "pkg/runtime/schema", 699 | "pkg/runtime/serializer", 700 | "pkg/runtime/serializer/json", 701 | "pkg/runtime/serializer/protobuf", 702 | "pkg/runtime/serializer/recognizer", 703 | "pkg/runtime/serializer/streaming", 704 | "pkg/runtime/serializer/versioning", 705 | "pkg/selection", 706 | "pkg/types", 707 | "pkg/util/cache", 708 | "pkg/util/clock", 709 | "pkg/util/diff", 710 | "pkg/util/errors", 711 | "pkg/util/framer", 712 | "pkg/util/intstr", 713 | "pkg/util/json", 714 | "pkg/util/mergepatch", 715 | "pkg/util/naming", 716 | "pkg/util/net", 717 | "pkg/util/rand", 718 | "pkg/util/runtime", 719 | "pkg/util/sets", 720 | "pkg/util/strategicpatch", 721 | "pkg/util/uuid", 722 | "pkg/util/validation", 723 | "pkg/util/validation/field", 724 | "pkg/util/wait", 725 | "pkg/util/yaml", 726 | "pkg/version", 727 | "pkg/watch", 728 | "third_party/forked/golang/json", 729 | "third_party/forked/golang/reflect", 730 | ] 731 | pruneopts = "NT" 732 | revision = "86fb29eff6288413d76bd8506874fddd9fccdff0" 733 | version = "kubernetes-1.13.4" 734 | 735 | [[projects]] 736 | digest = "1:7f28bbfb5889618ab038d4d250d7adb6762aa43b2fc120a95a1cd47c68af6dd4" 737 | name = "k8s.io/client-go" 738 | packages = [ 739 | "discovery", 740 | "discovery/fake", 741 | "dynamic", 742 | "kubernetes", 743 | "kubernetes/scheme", 744 | "kubernetes/typed/admissionregistration/v1alpha1", 745 | "kubernetes/typed/admissionregistration/v1beta1", 746 | "kubernetes/typed/apps/v1", 747 | "kubernetes/typed/apps/v1beta1", 748 | "kubernetes/typed/apps/v1beta2", 749 | "kubernetes/typed/auditregistration/v1alpha1", 750 | "kubernetes/typed/authentication/v1", 751 | "kubernetes/typed/authentication/v1beta1", 752 | "kubernetes/typed/authorization/v1", 753 | "kubernetes/typed/authorization/v1beta1", 754 | "kubernetes/typed/autoscaling/v1", 755 | "kubernetes/typed/autoscaling/v2beta1", 756 | "kubernetes/typed/autoscaling/v2beta2", 757 | "kubernetes/typed/batch/v1", 758 | "kubernetes/typed/batch/v1beta1", 759 | "kubernetes/typed/batch/v2alpha1", 760 | "kubernetes/typed/certificates/v1beta1", 761 | "kubernetes/typed/coordination/v1beta1", 762 | "kubernetes/typed/core/v1", 763 | "kubernetes/typed/events/v1beta1", 764 | "kubernetes/typed/extensions/v1beta1", 765 | "kubernetes/typed/networking/v1", 766 | "kubernetes/typed/policy/v1beta1", 767 | "kubernetes/typed/rbac/v1", 768 | "kubernetes/typed/rbac/v1alpha1", 769 | "kubernetes/typed/rbac/v1beta1", 770 | "kubernetes/typed/scheduling/v1alpha1", 771 | "kubernetes/typed/scheduling/v1beta1", 772 | "kubernetes/typed/settings/v1alpha1", 773 | "kubernetes/typed/storage/v1", 774 | "kubernetes/typed/storage/v1alpha1", 775 | "kubernetes/typed/storage/v1beta1", 776 | "pkg/apis/clientauthentication", 777 | "pkg/apis/clientauthentication/v1alpha1", 778 | "pkg/apis/clientauthentication/v1beta1", 779 | "pkg/version", 780 | "plugin/pkg/client/auth/exec", 781 | "plugin/pkg/client/auth/gcp", 782 | "rest", 783 | "rest/watch", 784 | "restmapper", 785 | "testing", 786 | "third_party/forked/golang/template", 787 | "tools/auth", 788 | "tools/cache", 789 | "tools/clientcmd", 790 | "tools/clientcmd/api", 791 | "tools/clientcmd/api/latest", 792 | "tools/clientcmd/api/v1", 793 | "tools/leaderelection", 794 | "tools/leaderelection/resourcelock", 795 | "tools/metrics", 796 | "tools/pager", 797 | "tools/record", 798 | "tools/reference", 799 | "transport", 800 | "util/buffer", 801 | "util/cert", 802 | "util/connrotation", 803 | "util/flowcontrol", 804 | "util/homedir", 805 | "util/integer", 806 | "util/jsonpath", 807 | "util/retry", 808 | "util/workqueue", 809 | ] 810 | pruneopts = "NT" 811 | revision = "b40b2a5939e43f7ffe0028ad67586b7ce50bb675" 812 | version = "kubernetes-1.13.4" 813 | 814 | [[projects]] 815 | digest = "1:dc1ae99dcab96913d81ae970b1f7a7411a54199b14bfb17a7e86f9a56979c720" 816 | name = "k8s.io/code-generator" 817 | packages = [ 818 | "cmd/client-gen", 819 | "cmd/client-gen/args", 820 | "cmd/client-gen/generators", 821 | "cmd/client-gen/generators/fake", 822 | "cmd/client-gen/generators/scheme", 823 | "cmd/client-gen/generators/util", 824 | "cmd/client-gen/path", 825 | "cmd/client-gen/types", 826 | "cmd/conversion-gen", 827 | "cmd/conversion-gen/args", 828 | "cmd/conversion-gen/generators", 829 | "cmd/deepcopy-gen", 830 | "cmd/deepcopy-gen/args", 831 | "cmd/defaulter-gen", 832 | "cmd/defaulter-gen/args", 833 | "cmd/informer-gen", 834 | "cmd/informer-gen/args", 835 | "cmd/informer-gen/generators", 836 | "cmd/lister-gen", 837 | "cmd/lister-gen/args", 838 | "cmd/lister-gen/generators", 839 | "pkg/util", 840 | ] 841 | pruneopts = "T" 842 | revision = "c2090bec4d9b1fb25de3812f868accc2bc9ecbae" 843 | version = "kubernetes-1.13.4" 844 | 845 | [[projects]] 846 | branch = "master" 847 | digest = "1:06449c9193d3d1f9375b97d1ce8a3f7a59d531c69ca34a6b0663cf3c144c2178" 848 | name = "k8s.io/gengo" 849 | packages = [ 850 | "args", 851 | "examples/deepcopy-gen/generators", 852 | "examples/defaulter-gen/generators", 853 | "examples/set-gen/sets", 854 | "generator", 855 | "namer", 856 | "parser", 857 | "types", 858 | ] 859 | pruneopts = "T" 860 | revision = "e17681d19d3ac4837a019ece36c2a0ec31ffe985" 861 | 862 | [[projects]] 863 | digest = "1:300621bb4f98c1440b7298b376058928baf1fceb221a7f4520a92b7b9919bb3d" 864 | name = "k8s.io/klog" 865 | packages = ["."] 866 | pruneopts = "NT" 867 | revision = "e531227889390a39d9533dde61f590fe9f4b0035" 868 | version = "v0.3.0" 869 | 870 | [[projects]] 871 | digest = "1:c48a795cd7048bb1888273bc604b6e69b22f9b8089c3df65f77cc527757b515c" 872 | name = "k8s.io/kube-openapi" 873 | packages = [ 874 | "cmd/openapi-gen", 875 | "cmd/openapi-gen/args", 876 | "pkg/common", 877 | "pkg/generators", 878 | "pkg/generators/rules", 879 | "pkg/util/proto", 880 | "pkg/util/sets", 881 | ] 882 | pruneopts = "NT" 883 | revision = "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" 884 | 885 | [[projects]] 886 | digest = "1:7ba08926bb3200bcac7122822f34c78f653243c4d9c04569d71bf5d27dfb943b" 887 | name = "k8s.io/kubernetes" 888 | packages = ["pkg/util/hash"] 889 | pruneopts = "NT" 890 | revision = "c6d339953bd4fd8c021a6b5fb46d7952b30be9f9" 891 | 892 | [[projects]] 893 | digest = "1:06035489efbd51ccface65fc878ceeb849aba05b2f9443c8993f363fc96e80ac" 894 | name = "sigs.k8s.io/controller-runtime" 895 | packages = [ 896 | "pkg/cache", 897 | "pkg/cache/internal", 898 | "pkg/client", 899 | "pkg/client/apiutil", 900 | "pkg/client/config", 901 | "pkg/controller", 902 | "pkg/controller/controllerutil", 903 | "pkg/event", 904 | "pkg/handler", 905 | "pkg/internal/controller", 906 | "pkg/internal/controller/metrics", 907 | "pkg/internal/recorder", 908 | "pkg/leaderelection", 909 | "pkg/manager", 910 | "pkg/metrics", 911 | "pkg/patch", 912 | "pkg/predicate", 913 | "pkg/reconcile", 914 | "pkg/recorder", 915 | "pkg/runtime/inject", 916 | "pkg/runtime/log", 917 | "pkg/runtime/scheme", 918 | "pkg/runtime/signals", 919 | "pkg/source", 920 | "pkg/source/internal", 921 | "pkg/webhook/admission", 922 | "pkg/webhook/admission/types", 923 | "pkg/webhook/internal/metrics", 924 | "pkg/webhook/types", 925 | ] 926 | pruneopts = "NT" 927 | revision = "12d98582e72927b6cd0123e2b4e819f9341ce62c" 928 | version = "v0.1.10" 929 | 930 | [[projects]] 931 | digest = "1:0a14ea9a2647d064bb9d48b2de78306e74b196681efd7b654eb0b518d90c2e8d" 932 | name = "sigs.k8s.io/controller-tools" 933 | packages = [ 934 | "pkg/crd/generator", 935 | "pkg/crd/util", 936 | "pkg/internal/codegen", 937 | "pkg/internal/codegen/parse", 938 | "pkg/internal/general", 939 | "pkg/util", 940 | ] 941 | pruneopts = "NT" 942 | revision = "950a0e88e4effb864253b3c7504b326cc83b9d11" 943 | version = "v0.1.8" 944 | 945 | [[projects]] 946 | digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c" 947 | name = "sigs.k8s.io/yaml" 948 | packages = ["."] 949 | pruneopts = "NT" 950 | revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" 951 | version = "v1.1.0" 952 | 953 | [solve-meta] 954 | analyzer-name = "dep" 955 | analyzer-version = 1 956 | input-imports = [ 957 | "github.com/go-openapi/spec", 958 | "github.com/operator-framework/operator-sdk/pkg/k8sutil", 959 | "github.com/operator-framework/operator-sdk/pkg/leader", 960 | "github.com/operator-framework/operator-sdk/pkg/log/zap", 961 | "github.com/operator-framework/operator-sdk/pkg/metrics", 962 | "github.com/operator-framework/operator-sdk/version", 963 | "github.com/pkg/errors", 964 | "github.com/spf13/pflag", 965 | "github.com/stretchr/testify/assert", 966 | "github.com/stretchr/testify/suite", 967 | "golang.org/x/sync/errgroup", 968 | "k8s.io/api/apps/v1", 969 | "k8s.io/api/apps/v1beta2", 970 | "k8s.io/api/core/v1", 971 | "k8s.io/api/rbac/v1", 972 | "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", 973 | "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset", 974 | "k8s.io/apimachinery/pkg/api/errors", 975 | "k8s.io/apimachinery/pkg/apis/meta/v1", 976 | "k8s.io/apimachinery/pkg/fields", 977 | "k8s.io/apimachinery/pkg/labels", 978 | "k8s.io/apimachinery/pkg/runtime", 979 | "k8s.io/apimachinery/pkg/runtime/schema", 980 | "k8s.io/apimachinery/pkg/runtime/serializer", 981 | "k8s.io/apimachinery/pkg/types", 982 | "k8s.io/apimachinery/pkg/util/intstr", 983 | "k8s.io/apimachinery/pkg/util/rand", 984 | "k8s.io/apimachinery/pkg/util/runtime", 985 | "k8s.io/apimachinery/pkg/util/wait", 986 | "k8s.io/apimachinery/pkg/util/yaml", 987 | "k8s.io/apimachinery/pkg/watch", 988 | "k8s.io/client-go/discovery", 989 | "k8s.io/client-go/discovery/fake", 990 | "k8s.io/client-go/kubernetes", 991 | "k8s.io/client-go/plugin/pkg/client/auth/gcp", 992 | "k8s.io/client-go/rest", 993 | "k8s.io/client-go/testing", 994 | "k8s.io/client-go/tools/cache", 995 | "k8s.io/client-go/tools/clientcmd", 996 | "k8s.io/client-go/util/flowcontrol", 997 | "k8s.io/code-generator/cmd/client-gen", 998 | "k8s.io/code-generator/cmd/conversion-gen", 999 | "k8s.io/code-generator/cmd/deepcopy-gen", 1000 | "k8s.io/code-generator/cmd/defaulter-gen", 1001 | "k8s.io/code-generator/cmd/informer-gen", 1002 | "k8s.io/code-generator/cmd/lister-gen", 1003 | "k8s.io/gengo/args", 1004 | "k8s.io/kube-openapi/cmd/openapi-gen", 1005 | "k8s.io/kube-openapi/pkg/common", 1006 | "k8s.io/kubernetes/pkg/util/hash", 1007 | "sigs.k8s.io/controller-runtime/pkg/client", 1008 | "sigs.k8s.io/controller-runtime/pkg/client/config", 1009 | "sigs.k8s.io/controller-runtime/pkg/controller", 1010 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil", 1011 | "sigs.k8s.io/controller-runtime/pkg/handler", 1012 | "sigs.k8s.io/controller-runtime/pkg/manager", 1013 | "sigs.k8s.io/controller-runtime/pkg/reconcile", 1014 | "sigs.k8s.io/controller-runtime/pkg/runtime/log", 1015 | "sigs.k8s.io/controller-runtime/pkg/runtime/scheme", 1016 | "sigs.k8s.io/controller-runtime/pkg/runtime/signals", 1017 | "sigs.k8s.io/controller-runtime/pkg/source", 1018 | "sigs.k8s.io/controller-tools/pkg/crd/generator", 1019 | ] 1020 | solver-name = "gps-cdcl" 1021 | solver-version = 1 1022 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Force dep to vendor the code generators, which aren't imported just used at dev time. 2 | required = [ 3 | "k8s.io/code-generator/cmd/defaulter-gen", 4 | "k8s.io/code-generator/cmd/deepcopy-gen", 5 | "k8s.io/code-generator/cmd/conversion-gen", 6 | "k8s.io/code-generator/cmd/client-gen", 7 | "k8s.io/code-generator/cmd/lister-gen", 8 | "k8s.io/code-generator/cmd/informer-gen", 9 | "k8s.io/kube-openapi/cmd/openapi-gen", 10 | "k8s.io/gengo/args", 11 | "sigs.k8s.io/controller-tools/pkg/crd/generator", 12 | ] 13 | 14 | [[override]] 15 | name = "k8s.io/code-generator" 16 | version = "kubernetes-1.13.4" 17 | 18 | [[override]] 19 | name = "github.com/go-openapi/spec" 20 | branch = "master" 21 | 22 | [[override]] 23 | name = "sigs.k8s.io/controller-tools" 24 | version = "=v0.1.8" 25 | 26 | [[override]] 27 | name = "k8s.io/api" 28 | version = "kubernetes-1.13.4" 29 | 30 | [[override]] 31 | name = "k8s.io/apimachinery" 32 | version = "kubernetes-1.13.4" 33 | 34 | [[override]] 35 | name = "k8s.io/apiextensions-apiserver" 36 | version = "kubernetes-1.13.4" 37 | 38 | [[override]] 39 | name = "k8s.io/apiserver" 40 | version = "kubernetes-1.13.4" 41 | 42 | [[override]] 43 | name = "k8s.io/client-go" 44 | version = "kubernetes-1.13.4" 45 | 46 | [[override]] 47 | name = "k8s.io/cli-runtime" 48 | version = "kubernetes-1.13.4" 49 | 50 | [[override]] 51 | name = "k8s.io/kube-openapi" 52 | revision = "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803" 53 | 54 | [[override]] 55 | name = "k8s.io/kubernetes" 56 | revision = "c6d339953bd4fd8c021a6b5fb46d7952b30be9f9" 57 | 58 | [[constraint]] 59 | name = "github.com/operator-framework/operator-sdk" 60 | version = "=v0.10.0" 61 | 62 | [prune] 63 | go-tests = true 64 | non-go = true 65 | 66 | [[prune.project]] 67 | name = "k8s.io/code-generator" 68 | non-go = false 69 | 70 | [[prune.project]] 71 | name = "k8s.io/gengo" 72 | non-go = false 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Draven 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash -o pipefail 2 | 3 | FIRST_GOPATH:=$(firstword $(subst :, ,$(shell go env GOPATH))) 4 | GO_PKG=github.com/draveness/proxier 5 | K8S_GEN_BINARIES:=deepcopy-gen informer-gen lister-gen client-gen 6 | 7 | TYPES_V1BETA1_TARGET:=pkg/apis/maegus/v1beta1/proxier_types.go 8 | 9 | K8S_GEN_DEPS:=.header 10 | K8S_GEN_DEPS+=$(TYPES_V1BETA1_TARGET) 11 | K8S_GEN_DEPS+=$(foreach bin,$(K8S_GEN_BINARIES),$(FIRST_GOPATH)/bin/$(bin)) 12 | K8S_GEN_DEPS+=$(OPENAPI_GEN_BINARY) 13 | 14 | OPERATOR_E2E_IMAGE_TAG:=$(shell tar -cf - pkg | md5) 15 | OPERATOR_E2E_IMAGE_NAME:=draveness/proxier-e2e:$(OPERATOR_E2E_IMAGE_TAG) 16 | 17 | .PHONY: test 18 | test: 19 | go test -count=1 ./pkg/... 20 | 21 | e2e: 22 | ./hack/docker-image-exists.sh || \ 23 | (operator-sdk build $(OPERATOR_E2E_IMAGE_NAME) && docker push $(OPERATOR_E2E_IMAGE_NAME)) 24 | go test -v ./test/e2e/ --kubeconfig "$(HOME)/.kube/k8s-playground-kubeconfig.yaml" --operator-image $(OPERATOR_E2E_IMAGE_NAME) 25 | 26 | run: 27 | operator-sdk up local --namespace=default 28 | 29 | LISTER_TARGET := pkg/client/listers/maegus/v1beta1/proxier.go 30 | $(LISTER_TARGET): $(K8S_GEN_DEPS) 31 | $(LISTER_GEN_BINARY) \ 32 | $(K8S_GEN_ARGS) \ 33 | --input-dirs "$(GO_PKG)/pkg/apis/maegus/v1beta1" \ 34 | --output-package "$(GO_PKG)/pkg/client/listers" 35 | 36 | CLIENT_TARGET := pkg/client/versioned/clientset.go 37 | $(CLIENT_TARGET): $(K8S_GEN_DEPS) 38 | $(CLIENT_GEN_BINARY) \ 39 | $(K8S_GEN_ARGS) \ 40 | --input-base "" \ 41 | --clientset-name "versioned" \ 42 | --input "$(GO_PKG)/pkg/apis/maegus/v1beta1" \ 43 | --output-package "$(GO_PKG)/pkg/client" 44 | 45 | INFORMER_TARGET := pkg/client/informers/externalversions/maegus/v1beta1/proxier.go 46 | $(INFORMER_TARGET): $(K8S_GEN_DEPS) $(LISTER_TARGET) $(CLIENT_TARGET) 47 | $(INFORMER_GEN_BINARY) \ 48 | $(K8S_GEN_ARGS) \ 49 | --versioned-clientset-package "$(GO_PKG)/pkg/client/versioned" \ 50 | --listers-package "$(GO_PKG)/pkg/client/listers" \ 51 | --input-dirs "$(GO_PKG)/pkg/apis/maegus/v1beta1" \ 52 | --output-package "$(GO_PKG)/pkg/client/informers" 53 | 54 | .PHONY: k8s-gen 55 | k8s-gen: \ 56 | $(CLIENT_TARGET) \ 57 | $(LISTER_TARGET) \ 58 | $(INFORMER_TARGET) 59 | 60 | .PHONY: release 61 | release: 62 | ./hack/make-release.sh 63 | operator-sdk build draveness/proxier:$(RELEASE) 64 | docker push draveness/proxier:$(RELEASE) 65 | git tag $(RELEASE) 66 | 67 | define _K8S_GEN_VAR_TARGET_ 68 | $(shell echo $(1) | tr '[:lower:]' '[:upper:]' | tr '-' '_')_BINARY:=$(FIRST_GOPATH)/bin/$(1) 69 | 70 | $(FIRST_GOPATH)/bin/$(1): 71 | go get -u -d k8s.io/code-generator/cmd/$(1) 72 | cd $(FIRST_GOPATH)/src/k8s.io/code-generator; git checkout $(K8S_GEN_VERSION) 73 | go install k8s.io/code-generator/cmd/$(1) 74 | 75 | endef 76 | 77 | $(foreach binary,$(K8S_GEN_BINARIES),$(eval $(call _K8S_GEN_VAR_TARGET_,$(binary)))) 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![proxier-banner](./images/proxier-banner.png) 2 | 3 | [![Go Report Card](https://goreportcard.com/badge/github.com/draveness/proxier)](https://goreportcard.com/report/github.com/draveness/proxier) 4 | [![LICENSE](https://img.shields.io/github/license/draveness/proxier.svg)](https://github.com/draveness/proxier/blob/master/LICENSE) 5 | [![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/) 6 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fdraveness%2Fproxier.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fdraveness%2Fproxier?ref=badge_shield) 7 | 8 | # Proxier [Under Development] 9 | 10 | Proxier is a better approach to expose applications in Kubernetes. It supports load balancing to a set of pods with weights and provides high-performance load balancing with nginx and HAProxy. 11 | 12 | + [x] supports canary deployment and load balancing by weight 13 | + [x] builtin load balancing applications support, e.g., nginx and HAProxy 14 | + [ ] scales horizontally with pressure by default 15 | 16 | ```yaml 17 | apiVersion: maegus.com/v1beta1 18 | kind: Proxier 19 | metadata: 20 | name: example-proxier 21 | spec: 22 | ports: 23 | - name: http 24 | protocol: TCP 25 | port: 80 26 | selector: 27 | app: example 28 | backends: 29 | - name: v1 30 | weight: 90 31 | selector: 32 | version: v1 33 | - name: v2 34 | weight: 9 35 | selector: 36 | version: v2 37 | ``` 38 | 39 | ## Architecture overview 40 | 41 | ![proxier-architecture](./images/proxier-architecture.png) 42 | 43 | ## Installation 44 | 45 | ``` 46 | kubectl apply -f https://raw.githubusercontent.com/draveness/proxier/master/deploy/proxier.yaml 47 | ``` 48 | 49 | ## Usage 50 | 51 | ## License 52 | 53 | MIT License, see [LICENSE](./LICENSE) 54 | -------------------------------------------------------------------------------- /build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.access.redhat.com/ubi7-dev-preview/ubi-minimal:7.6 2 | 3 | ENV OPERATOR=/usr/local/bin/proxier \ 4 | USER_UID=1001 \ 5 | USER_NAME=proxier 6 | 7 | # install operator binary 8 | COPY build/_output/bin/proxier ${OPERATOR} 9 | 10 | COPY build/bin /usr/local/bin 11 | RUN /usr/local/bin/user_setup 12 | 13 | ENTRYPOINT ["/usr/local/bin/entrypoint"] 14 | 15 | USER ${USER_UID} 16 | -------------------------------------------------------------------------------- /build/bin/entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # This is documented here: 4 | # https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines 5 | 6 | if ! whoami &>/dev/null; then 7 | if [ -w /etc/passwd ]; then 8 | echo "${USER_NAME:-proxier}:x:$(id -u):$(id -g):${USER_NAME:-proxier} user:${HOME}:/sbin/nologin" >> /etc/passwd 9 | fi 10 | fi 11 | 12 | exec ${OPERATOR} $@ 13 | -------------------------------------------------------------------------------- /build/bin/user_setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -x 3 | 4 | # ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be) 5 | mkdir -p ${HOME} 6 | chown ${USER_UID}:0 ${HOME} 7 | chmod ug+rwx ${HOME} 8 | 9 | # runtime user will need to be able to self-insert in /etc/passwd 10 | chmod g+rw /etc/passwd 11 | 12 | # no need for this script to remain in the image after running 13 | rm $0 14 | -------------------------------------------------------------------------------- /cmd/manager/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "runtime" 9 | 10 | // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) 11 | _ "k8s.io/client-go/plugin/pkg/client/auth" 12 | "k8s.io/client-go/rest" 13 | 14 | "github.com/draveness/proxier/pkg/apis" 15 | "github.com/draveness/proxier/pkg/controller" 16 | 17 | "github.com/operator-framework/operator-sdk/pkg/k8sutil" 18 | kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics" 19 | "github.com/operator-framework/operator-sdk/pkg/leader" 20 | "github.com/operator-framework/operator-sdk/pkg/log/zap" 21 | "github.com/operator-framework/operator-sdk/pkg/metrics" 22 | "github.com/operator-framework/operator-sdk/pkg/restmapper" 23 | sdkVersion "github.com/operator-framework/operator-sdk/version" 24 | "github.com/spf13/pflag" 25 | v1 "k8s.io/api/core/v1" 26 | "k8s.io/apimachinery/pkg/util/intstr" 27 | "sigs.k8s.io/controller-runtime/pkg/client/config" 28 | "sigs.k8s.io/controller-runtime/pkg/manager" 29 | logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" 30 | "sigs.k8s.io/controller-runtime/pkg/runtime/signals" 31 | ) 32 | 33 | // Change below variables to serve metrics on different host or port. 34 | var ( 35 | metricsHost = "0.0.0.0" 36 | metricsPort int32 = 8383 37 | operatorMetricsPort int32 = 8686 38 | ) 39 | var log = logf.Log.WithName("cmd") 40 | 41 | func printVersion() { 42 | log.Info(fmt.Sprintf("Go Version: %s", runtime.Version())) 43 | log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) 44 | log.Info(fmt.Sprintf("Version of operator-sdk: %v", sdkVersion.Version)) 45 | } 46 | 47 | func main() { 48 | // Add the zap logger flag set to the CLI. The flag set must 49 | // be added before calling pflag.Parse(). 50 | pflag.CommandLine.AddFlagSet(zap.FlagSet()) 51 | 52 | // Add flags registered by imported packages (e.g. glog and 53 | // controller-runtime) 54 | pflag.CommandLine.AddGoFlagSet(flag.CommandLine) 55 | 56 | pflag.Parse() 57 | 58 | // Use a zap logr.Logger implementation. If none of the zap 59 | // flags are configured (or if the zap flag set is not being 60 | // used), this defaults to a production zap logger. 61 | // 62 | // The logger instantiated here can be changed to any logger 63 | // implementing the logr.Logger interface. This logger will 64 | // be propagated through the whole operator, generating 65 | // uniform and structured logs. 66 | logf.SetLogger(zap.Logger()) 67 | 68 | printVersion() 69 | 70 | namespace, err := k8sutil.GetWatchNamespace() 71 | if err != nil { 72 | log.Error(err, "Failed to get watch namespace") 73 | os.Exit(1) 74 | } 75 | 76 | // Get a config to talk to the apiserver 77 | cfg, err := config.GetConfig() 78 | if err != nil { 79 | log.Error(err, "") 80 | os.Exit(1) 81 | } 82 | 83 | ctx := context.Background() 84 | // Become the leader before proceeding 85 | err = leader.Become(ctx, "proxier-lock") 86 | if err != nil { 87 | log.Error(err, "") 88 | os.Exit(1) 89 | } 90 | 91 | // Create a new Cmd to provide shared dependencies and start components 92 | mgr, err := manager.New(cfg, manager.Options{ 93 | Namespace: namespace, 94 | MapperProvider: restmapper.NewDynamicRESTMapper, 95 | MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort), 96 | }) 97 | if err != nil { 98 | log.Error(err, "") 99 | os.Exit(1) 100 | } 101 | 102 | log.Info("Registering Components.") 103 | 104 | // Setup Scheme for all resources 105 | if err := apis.AddToScheme(mgr.GetScheme()); err != nil { 106 | log.Error(err, "") 107 | os.Exit(1) 108 | } 109 | 110 | // Setup all Controllers 111 | if err := controller.AddToManager(mgr); err != nil { 112 | log.Error(err, "") 113 | os.Exit(1) 114 | } 115 | 116 | if err = serveCRMetrics(cfg); err != nil { 117 | log.Info("Could not generate and serve custom resource metrics", "error", err.Error()) 118 | } 119 | 120 | // Add to the below struct any other metrics ports you want to expose. 121 | servicePorts := []v1.ServicePort{ 122 | {Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}}, 123 | {Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}}, 124 | } 125 | // Create Service object to expose the metrics port(s). 126 | service, err := metrics.CreateMetricsService(ctx, cfg, servicePorts) 127 | if err != nil { 128 | log.Info("Could not create metrics Service", "error", err.Error()) 129 | } 130 | 131 | // CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources 132 | // necessary to configure Prometheus to scrape metrics from this operator. 133 | services := []*v1.Service{service} 134 | _, err = metrics.CreateServiceMonitors(cfg, namespace, services) 135 | if err != nil { 136 | log.Info("Could not create ServiceMonitor object", "error", err.Error()) 137 | // If this operator is deployed to a cluster without the prometheus-operator running, it will return 138 | // ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation. 139 | if err == metrics.ErrServiceMonitorNotPresent { 140 | log.Info("Install prometheus-operator in your cluster to create ServiceMonitor objects", "error", err.Error()) 141 | } 142 | } 143 | 144 | log.Info("Starting the Cmd.") 145 | 146 | // Start the Cmd 147 | if err := mgr.Start(signals.SetupSignalHandler()); err != nil { 148 | log.Error(err, "Manager exited non-zero") 149 | os.Exit(1) 150 | } 151 | } 152 | 153 | // serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types. 154 | // It serves those metrics on "http://metricsHost:operatorMetricsPort". 155 | func serveCRMetrics(cfg *rest.Config) error { 156 | // Below function returns filtered operator/CustomResource specific GVKs. 157 | // For more control override the below GVK list with your own custom logic. 158 | filteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme) 159 | if err != nil { 160 | return err 161 | } 162 | // Get the namespace the operator is currently deployed in. 163 | operatorNs, err := k8sutil.GetOperatorNamespace() 164 | if err != nil { 165 | return err 166 | } 167 | // To generate metrics in other namespaces, add the values below. 168 | ns := []string{operatorNs} 169 | // Generate and serve custom resource specific metrics. 170 | err = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort) 171 | if err != nil { 172 | return err 173 | } 174 | return nil 175 | } 176 | -------------------------------------------------------------------------------- /deploy/cluster_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: proxier 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - pods 11 | - services 12 | - endpoints 13 | - persistentvolumeclaims 14 | - events 15 | - configmaps 16 | - secrets 17 | verbs: 18 | - '*' 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - namespaces 23 | verbs: 24 | - get 25 | - apiGroups: 26 | - apps 27 | resources: 28 | - deployments 29 | - daemonsets 30 | - replicasets 31 | - statefulsets 32 | verbs: 33 | - '*' 34 | - apiGroups: 35 | - monitoring.coreos.com 36 | resources: 37 | - servicemonitors 38 | verbs: 39 | - get 40 | - create 41 | - apiGroups: 42 | - apps 43 | resourceNames: 44 | - proxier 45 | resources: 46 | - deployments/finalizers 47 | verbs: 48 | - update 49 | - apiGroups: 50 | - maegus.com 51 | resources: 52 | - '*' 53 | verbs: 54 | - '*' 55 | -------------------------------------------------------------------------------- /deploy/cluster_role_binding.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: proxier 5 | subjects: 6 | - kind: ServiceAccount 7 | name: proxier 8 | namespace: default 9 | roleRef: 10 | kind: ClusterRole 11 | name: proxier 12 | apiGroup: rbac.authorization.k8s.io 13 | -------------------------------------------------------------------------------- /deploy/crds/maegus_v1beta1_proxier_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: proxiers.maegus.com 5 | spec: 6 | group: maegus.com 7 | names: 8 | kind: Proxier 9 | listKind: ProxierList 10 | plural: proxiers 11 | singular: proxier 12 | scope: Namespaced 13 | subresources: 14 | status: {} 15 | validation: 16 | openAPIV3Schema: 17 | properties: 18 | apiVersion: 19 | type: string 20 | kind: 21 | type: string 22 | metadata: 23 | type: object 24 | spec: 25 | properties: 26 | backends: 27 | items: 28 | properties: 29 | name: 30 | minLength: 1 31 | type: string 32 | selector: 33 | additionalProperties: 34 | type: string 35 | type: object 36 | weight: 37 | format: int32 38 | minimum: 1 39 | type: integer 40 | required: 41 | - name 42 | - weight 43 | type: object 44 | minItems: 1 45 | type: array 46 | ports: 47 | items: 48 | properties: 49 | name: 50 | type: string 51 | port: 52 | format: int32 53 | type: integer 54 | protocol: 55 | type: string 56 | targetPort: 57 | oneOf: 58 | - type: string 59 | - type: integer 60 | required: 61 | - port 62 | type: object 63 | type: array 64 | selector: 65 | additionalProperties: 66 | type: string 67 | type: object 68 | required: 69 | - backends 70 | - ports 71 | type: object 72 | status: 73 | properties: 74 | activeBackends: 75 | format: int32 76 | type: integer 77 | obsoleteBackends: 78 | format: int32 79 | type: integer 80 | type: object 81 | version: v1beta1 82 | versions: 83 | - name: v1beta1 84 | served: true 85 | storage: true 86 | -------------------------------------------------------------------------------- /deploy/operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: proxier-operator 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | name: proxier-operator 10 | template: 11 | metadata: 12 | labels: 13 | name: proxier-operator 14 | spec: 15 | serviceAccountName: proxier 16 | containers: 17 | - name: proxier 18 | image: draveness/proxier:v0.2.0 19 | command: 20 | - proxier 21 | imagePullPolicy: Always 22 | env: 23 | - name: WATCH_NAMESPACE 24 | value: "" 25 | - name: POD_NAME 26 | valueFrom: 27 | fieldRef: 28 | fieldPath: metadata.name 29 | - name: OPERATOR_NAME 30 | value: "proxier-operator" 31 | -------------------------------------------------------------------------------- /deploy/proxier.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: proxier 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - pods 12 | - services 13 | - endpoints 14 | - persistentvolumeclaims 15 | - events 16 | - configmaps 17 | - secrets 18 | verbs: 19 | - '*' 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - namespaces 24 | verbs: 25 | - get 26 | - apiGroups: 27 | - apps 28 | resources: 29 | - deployments 30 | - daemonsets 31 | - replicasets 32 | - statefulsets 33 | verbs: 34 | - '*' 35 | - apiGroups: 36 | - monitoring.coreos.com 37 | resources: 38 | - servicemonitors 39 | verbs: 40 | - get 41 | - create 42 | - apiGroups: 43 | - apps 44 | resourceNames: 45 | - proxier 46 | resources: 47 | - deployments/finalizers 48 | verbs: 49 | - update 50 | - apiGroups: 51 | - maegus.com 52 | resources: 53 | - '*' 54 | verbs: 55 | - '*' 56 | --- 57 | kind: ClusterRoleBinding 58 | apiVersion: rbac.authorization.k8s.io/v1 59 | metadata: 60 | name: proxier 61 | subjects: 62 | - kind: ServiceAccount 63 | name: proxier 64 | namespace: default 65 | roleRef: 66 | kind: ClusterRole 67 | name: proxier 68 | apiGroup: rbac.authorization.k8s.io 69 | --- 70 | apiVersion: apiextensions.k8s.io/v1beta1 71 | kind: CustomResourceDefinition 72 | metadata: 73 | name: proxiers.maegus.com 74 | spec: 75 | group: maegus.com 76 | names: 77 | kind: Proxier 78 | listKind: ProxierList 79 | plural: proxiers 80 | singular: proxier 81 | scope: Namespaced 82 | subresources: 83 | status: {} 84 | validation: 85 | openAPIV3Schema: 86 | properties: 87 | apiVersion: 88 | type: string 89 | kind: 90 | type: string 91 | metadata: 92 | type: object 93 | spec: 94 | properties: 95 | backends: 96 | items: 97 | properties: 98 | name: 99 | minLength: 1 100 | type: string 101 | selector: 102 | additionalProperties: 103 | type: string 104 | type: object 105 | weight: 106 | format: int32 107 | minimum: 1 108 | type: integer 109 | required: 110 | - name 111 | - weight 112 | type: object 113 | minItems: 1 114 | type: array 115 | ports: 116 | items: 117 | properties: 118 | name: 119 | type: string 120 | port: 121 | format: int32 122 | type: integer 123 | protocol: 124 | type: string 125 | targetPort: 126 | oneOf: 127 | - type: string 128 | - type: integer 129 | required: 130 | - port 131 | type: object 132 | type: array 133 | selector: 134 | additionalProperties: 135 | type: string 136 | type: object 137 | required: 138 | - backends 139 | - ports 140 | type: object 141 | status: 142 | properties: 143 | currentBackends: 144 | format: int32 145 | type: integer 146 | obsoleteBackends: 147 | format: int32 148 | type: integer 149 | type: object 150 | version: v1beta1 151 | versions: 152 | - name: v1beta1 153 | served: true 154 | storage: true 155 | --- 156 | apiVersion: apps/v1 157 | kind: Deployment 158 | metadata: 159 | name: proxier-operator 160 | spec: 161 | replicas: 1 162 | selector: 163 | matchLabels: 164 | name: proxier-operator 165 | template: 166 | metadata: 167 | labels: 168 | name: proxier-operator 169 | spec: 170 | serviceAccountName: proxier 171 | containers: 172 | - name: proxier 173 | image: draveness/proxier:v0.2.0 174 | command: 175 | - proxier 176 | imagePullPolicy: Always 177 | env: 178 | - name: WATCH_NAMESPACE 179 | value: "" 180 | - name: POD_NAME 181 | valueFrom: 182 | fieldRef: 183 | fieldPath: metadata.name 184 | - name: OPERATOR_NAME 185 | value: "proxier-operator" 186 | --- 187 | apiVersion: v1 188 | kind: ServiceAccount 189 | metadata: 190 | name: proxier 191 | -------------------------------------------------------------------------------- /deploy/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: proxier 5 | -------------------------------------------------------------------------------- /examples/busybox.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: busybox 5 | labels: 6 | app: busybox 7 | spec: 8 | containers: 9 | - name: utils 10 | tty: true 11 | stdin: true 12 | image: arunvelsriram/utils 13 | imagePullPolicy: IfNotPresent 14 | restartPolicy: Always 15 | -------------------------------------------------------------------------------- /examples/echo.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: echo-v1 5 | labels: 6 | app: test 7 | version: v1 8 | name: echo-v1 9 | spec: 10 | containers: 11 | - name: echo 12 | image: hashicorp/http-echo 13 | command: ["/http-echo"] 14 | args: ["-text", "hello world v1"] 15 | ports: 16 | - containerPort: 5678 17 | --- 18 | apiVersion: v1 19 | kind: Pod 20 | metadata: 21 | name: echo-v2 22 | labels: 23 | app: test 24 | version: v2 25 | name: echo-v2 26 | spec: 27 | containers: 28 | - name: echo 29 | image: hashicorp/http-echo 30 | command: ["/http-echo"] 31 | args: ["-text", "hello world v2"] 32 | ports: 33 | - containerPort: 5678 34 | -------------------------------------------------------------------------------- /examples/proxier.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: maegus.com/v1beta1 2 | kind: Proxier 3 | metadata: 4 | name: example-proxier 5 | spec: 6 | ports: 7 | - name: http 8 | protocol: TCP 9 | port: 80 10 | targetPort: 5678 11 | selector: 12 | app: test 13 | backends: 14 | - name: v1 15 | weight: 90 16 | selector: 17 | version: v1 18 | - name: v2 19 | weight: 9 20 | selector: 21 | version: v2 22 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/draveness/proxier 2 | 3 | go 1.12 4 | 5 | require ( 6 | cloud.google.com/go v0.37.4 // indirect 7 | github.com/beorn7/perks v1.0.0 // indirect 8 | github.com/go-openapi/spec v0.19.0 9 | github.com/gobuffalo/envy v1.7.0 // indirect 10 | github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect 11 | github.com/operator-framework/operator-sdk v0.10.0 12 | github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c // indirect 13 | github.com/pkg/errors v0.8.1 14 | github.com/prometheus/common v0.3.0 // indirect 15 | github.com/prometheus/procfs v0.0.0-20190416084830-8368d24ba045 // indirect 16 | github.com/spf13/pflag v1.0.3 17 | github.com/stretchr/testify v1.3.0 18 | golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a // indirect 19 | golang.org/x/net v0.0.0-20190415214537-1da14a5a36f2 // indirect 20 | golang.org/x/sync v0.0.0-20190412183630-56d357773e84 21 | golang.org/x/sys v0.0.0-20190416152802-12500544f89f // indirect 22 | golang.org/x/tools v0.0.0-20190417005754-4ca4b55e2050 // indirect 23 | k8s.io/api v0.0.0-20190612125737-db0771252981 24 | k8s.io/apiextensions-apiserver v0.0.0-20190228180357-d002e88f6236 25 | k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad 26 | k8s.io/client-go v11.0.0+incompatible 27 | k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580 28 | k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2 29 | sigs.k8s.io/controller-runtime v0.1.10 30 | sigs.k8s.io/controller-tools v0.1.8 // indirect 31 | ) 32 | 33 | // Pinned to kubernetes-1.13.4 34 | replace ( 35 | k8s.io/api => k8s.io/api v0.0.0-20190222213804-5cb15d344471 36 | k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190228180357-d002e88f6236 37 | k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628 38 | k8s.io/apiserver => k8s.io/apiserver v0.0.0-20190228174905-79427f02047f 39 | k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20190228180923-a9e421a79326 40 | k8s.io/client-go => k8s.io/client-go v0.0.0-20190228174230-b40b2a5939e4 41 | k8s.io/code-generator => k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b 42 | k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20190228175259-3e0149950b0e 43 | k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20180711000925-0cf8f7e6ed1d 44 | k8s.io/kubernetes => k8s.io/kubernetes v1.13.4 45 | ) 46 | -------------------------------------------------------------------------------- /hack/docker-image-exists.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | OPERATOR_E2E_IMAGE_TAG=`tar -cf - pkg | md5` 4 | curl --silent -f -lSL https://index.docker.io/v1/repositories/draveness/proxier-e2e/tags/$OPERATOR_E2E_IMAGE_TAG > /dev/null 5 | -------------------------------------------------------------------------------- /hack/make-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DEPLOY_FILE=deploy/proxier.yaml 4 | 5 | rm $DEPLOY_FILE 2>/dev/null 6 | touch $DEPLOY_FILE 7 | for file in ./deploy/cluster_role.yaml ./deploy/cluster_role_binding.yaml ./deploy/crds/maegus_v1beta1_proxier_crd.yaml ./deploy/operator.yaml ./deploy/service_account.yaml 8 | do 9 | echo "---" >> $DEPLOY_FILE 10 | cat $file >> $DEPLOY_FILE 11 | done 12 | -------------------------------------------------------------------------------- /hack/update-gofmt.sh: -------------------------------------------------------------------------------- 1 | set -eou pipefail 2 | 3 | SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 4 | REPO_ROOT="$(cd "${SCRIPT_ROOT}/../.." && pwd)" 5 | pushd ${REPO_ROOT} > /dev/null 6 | 7 | find . -name "*.go" | grep -v -e "\/vendor\/" -e "/*deepcopy.go" -e "/*kubebuilder.go" -e "/doc.go" | xargs gofmt -s -w 8 | 9 | popd > /dev/null 10 | 11 | -------------------------------------------------------------------------------- /images/proxier-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draveness/proxier/35097528b53c110db89dfa918bee2164bf49f05d/images/proxier-architecture.png -------------------------------------------------------------------------------- /images/proxier-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/draveness/proxier/35097528b53c110db89dfa918bee2164bf49f05d/images/proxier-banner.png -------------------------------------------------------------------------------- /pkg/apis/addto_scheme_maegus_v1beta1.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 5 | ) 6 | 7 | func init() { 8 | // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back 9 | AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme) 10 | } 11 | -------------------------------------------------------------------------------- /pkg/apis/apis.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "k8s.io/apimachinery/pkg/runtime" 5 | ) 6 | 7 | // AddToSchemes may be used to add all resources defined in the project to a Scheme 8 | var AddToSchemes runtime.SchemeBuilder 9 | 10 | // AddToScheme adds all Resources to the Scheme 11 | func AddToScheme(s *runtime.Scheme) error { 12 | return AddToSchemes.AddToScheme(s) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/annotations.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | const ( 4 | // ConfigMapHashAnnotationKey is the name of an annotation which detects the update of 5 | // proxier corresponding config map. 6 | ConfigMapHashAnnotationKey = "proxier.maegus.com/configmap-hash" 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | // Package v1beta1 contains API Schema definitions for the maegus v1beta1 API group 2 | // +k8s:deepcopy-gen=package,register 3 | // +groupName=maegus.com 4 | package v1beta1 5 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/labels.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | const ( 4 | // ProxierKeyLabel is the key of proxier name 5 | ProxierKeyLabel = "maegus.com/proxier-name" 6 | ) 7 | 8 | // GetProxierName returns proxier name from labels. 9 | func GetProxierName(labels map[string]string) string { 10 | return labels[ProxierKeyLabel] 11 | } 12 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/proxier_types.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 | "k8s.io/apimachinery/pkg/util/intstr" 6 | ) 7 | 8 | // Protocol defines network protocols supported for things like container ports. 9 | type Protocol string 10 | 11 | const ( 12 | // ProtocolTCP is the TCP protocol. 13 | ProtocolTCP Protocol = "TCP" 14 | // ProtocolUDP is the UDP protocol. 15 | ProtocolUDP Protocol = "UDP" 16 | ) 17 | 18 | // ProxierPort contains information on proxier's port. 19 | type ProxierPort struct { 20 | // The name of this port within the proxier. This must be a DNS_LABEL. 21 | // All ports within a ServiceSpec must have unique names. This maps to 22 | // the 'Name' field in EndpointPort objects. 23 | // Optional if only one ProxierPort is defined on this service. 24 | // +required 25 | Name string `json:"name,omitempty"` 26 | 27 | // The IP protocol for this port. Supports "TCP", "UDP". 28 | // Default is TCP. 29 | // +optional 30 | Protocol Protocol `json:"protocol,omitempty"` 31 | 32 | // The port that will be exposed by this proxier 33 | Port int32 `json:"port"` 34 | 35 | // +optional 36 | TargetPort intstr.IntOrString `json:"targetPort,omitempty"` 37 | } 38 | 39 | // ProxierSpec defines the desired state of Proxier 40 | // +k8s:openapi-gen=true 41 | type ProxierSpec struct { 42 | // +kubebuilder:validation:MinItems=1 43 | Backends []BackendSpec `json:"backends"` 44 | 45 | Selector map[string]string `json:"selector,omitempty"` 46 | 47 | Ports []ProxierPort `json:"ports"` 48 | } 49 | 50 | // BackendSpec defines the target backend of Proxier 51 | type BackendSpec struct { 52 | // +kubebuilder:validation:MinLength=1 53 | Name string `json:"name"` 54 | 55 | // +kubebuilder:validation:Minimum=1 56 | Weight int32 `json:"weight"` 57 | 58 | Selector map[string]string `json:"selector,omitempty"` 59 | } 60 | 61 | // ProxierStatus defines the observed state of Proxier 62 | // +k8s:openapi-gen=true 63 | type ProxierStatus struct { 64 | // ActiveBackends stores the count of current active services, which are required by the current 65 | // proxier spec. 66 | // +optional 67 | ActiveBackends int32 `json:"activeBackends,omitempty"` 68 | 69 | // ObsoleteBackends stores the count of obsolete services, which should be removed in controller 70 | // +optional 71 | ObsoleteBackends int32 `json:"obsoleteBackends,omitempty"` 72 | } 73 | 74 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 75 | 76 | // Proxier is the Schema for the proxiers API 77 | // +genclient 78 | // +k8s:openapi-gen=true 79 | // +kubebuilder:subresource:status 80 | type Proxier struct { 81 | metav1.TypeMeta `json:",inline"` 82 | metav1.ObjectMeta `json:"metadata,omitempty"` 83 | 84 | Spec ProxierSpec `json:"spec,omitempty"` 85 | Status ProxierStatus `json:"status,omitempty"` 86 | } 87 | 88 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 89 | 90 | // ProxierList contains a list of Proxier 91 | type ProxierList struct { 92 | metav1.TypeMeta `json:",inline"` 93 | metav1.ListMeta `json:"metadata,omitempty"` 94 | Items []Proxier `json:"items"` 95 | } 96 | 97 | func init() { 98 | SchemeBuilder.Register(&Proxier{}, &ProxierList{}) 99 | } 100 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/register.go: -------------------------------------------------------------------------------- 1 | // NOTE: Boilerplate only. Ignore this file. 2 | 3 | // Package v1beta1 contains API Schema definitions for the maegus v1beta1 API group 4 | // +k8s:deepcopy-gen=package,register 5 | // +groupName=maegus.com 6 | package v1beta1 7 | 8 | import ( 9 | "k8s.io/apimachinery/pkg/runtime/schema" 10 | "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" 11 | ) 12 | 13 | var ( 14 | // SchemeGroupVersion is group version used to register these objects 15 | SchemeGroupVersion = schema.GroupVersion{Group: "maegus.com", Version: "v1beta1"} 16 | 17 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 18 | SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} 19 | 20 | // AddToScheme . 21 | AddToScheme = SchemeBuilder.AddToScheme 22 | ) 23 | 24 | // Kind takes an unqualified kind and returns a Group qualified GroupKind 25 | func Kind(kind string) schema.GroupKind { 26 | return SchemeGroupVersion.WithKind(kind).GroupKind() 27 | } 28 | 29 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 30 | func Resource(resource string) schema.GroupResource { 31 | return SchemeGroupVersion.WithResource(resource).GroupResource() 32 | } 33 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/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 v1beta1 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 *BackendSpec) DeepCopyInto(out *BackendSpec) { 29 | *out = *in 30 | if in.Selector != nil { 31 | in, out := &in.Selector, &out.Selector 32 | *out = make(map[string]string, len(*in)) 33 | for key, val := range *in { 34 | (*out)[key] = val 35 | } 36 | } 37 | return 38 | } 39 | 40 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendSpec. 41 | func (in *BackendSpec) DeepCopy() *BackendSpec { 42 | if in == nil { 43 | return nil 44 | } 45 | out := new(BackendSpec) 46 | in.DeepCopyInto(out) 47 | return out 48 | } 49 | 50 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 51 | func (in *Proxier) DeepCopyInto(out *Proxier) { 52 | *out = *in 53 | out.TypeMeta = in.TypeMeta 54 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 55 | in.Spec.DeepCopyInto(&out.Spec) 56 | out.Status = in.Status 57 | return 58 | } 59 | 60 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Proxier. 61 | func (in *Proxier) DeepCopy() *Proxier { 62 | if in == nil { 63 | return nil 64 | } 65 | out := new(Proxier) 66 | in.DeepCopyInto(out) 67 | return out 68 | } 69 | 70 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 71 | func (in *Proxier) DeepCopyObject() runtime.Object { 72 | if c := in.DeepCopy(); c != nil { 73 | return c 74 | } 75 | return nil 76 | } 77 | 78 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 79 | func (in *ProxierList) DeepCopyInto(out *ProxierList) { 80 | *out = *in 81 | out.TypeMeta = in.TypeMeta 82 | out.ListMeta = in.ListMeta 83 | if in.Items != nil { 84 | in, out := &in.Items, &out.Items 85 | *out = make([]Proxier, len(*in)) 86 | for i := range *in { 87 | (*in)[i].DeepCopyInto(&(*out)[i]) 88 | } 89 | } 90 | return 91 | } 92 | 93 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxierList. 94 | func (in *ProxierList) DeepCopy() *ProxierList { 95 | if in == nil { 96 | return nil 97 | } 98 | out := new(ProxierList) 99 | in.DeepCopyInto(out) 100 | return out 101 | } 102 | 103 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 104 | func (in *ProxierList) DeepCopyObject() runtime.Object { 105 | if c := in.DeepCopy(); c != nil { 106 | return c 107 | } 108 | return nil 109 | } 110 | 111 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 112 | func (in *ProxierPort) DeepCopyInto(out *ProxierPort) { 113 | *out = *in 114 | out.TargetPort = in.TargetPort 115 | return 116 | } 117 | 118 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxierPort. 119 | func (in *ProxierPort) DeepCopy() *ProxierPort { 120 | if in == nil { 121 | return nil 122 | } 123 | out := new(ProxierPort) 124 | in.DeepCopyInto(out) 125 | return out 126 | } 127 | 128 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 129 | func (in *ProxierSpec) DeepCopyInto(out *ProxierSpec) { 130 | *out = *in 131 | if in.Backends != nil { 132 | in, out := &in.Backends, &out.Backends 133 | *out = make([]BackendSpec, len(*in)) 134 | for i := range *in { 135 | (*in)[i].DeepCopyInto(&(*out)[i]) 136 | } 137 | } 138 | if in.Selector != nil { 139 | in, out := &in.Selector, &out.Selector 140 | *out = make(map[string]string, len(*in)) 141 | for key, val := range *in { 142 | (*out)[key] = val 143 | } 144 | } 145 | if in.Ports != nil { 146 | in, out := &in.Ports, &out.Ports 147 | *out = make([]ProxierPort, len(*in)) 148 | copy(*out, *in) 149 | } 150 | return 151 | } 152 | 153 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxierSpec. 154 | func (in *ProxierSpec) DeepCopy() *ProxierSpec { 155 | if in == nil { 156 | return nil 157 | } 158 | out := new(ProxierSpec) 159 | in.DeepCopyInto(out) 160 | return out 161 | } 162 | 163 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 164 | func (in *ProxierStatus) DeepCopyInto(out *ProxierStatus) { 165 | *out = *in 166 | return 167 | } 168 | 169 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxierStatus. 170 | func (in *ProxierStatus) DeepCopy() *ProxierStatus { 171 | if in == nil { 172 | return nil 173 | } 174 | out := new(ProxierStatus) 175 | in.DeepCopyInto(out) 176 | return out 177 | } 178 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/zz_generated.defaults.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 defaulter-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // RegisterDefaults adds defaulters functions to the given scheme. 28 | // Public to allow building arbitrary schemes. 29 | // All generated defaulters are covering - they call all nested defaulters. 30 | func RegisterDefaults(scheme *runtime.Scheme) error { 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /pkg/apis/maegus/v1beta1/zz_generated.openapi.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | // Code generated by openapi-gen. DO NOT EDIT. 4 | 5 | // This file was autogenerated by openapi-gen. Do not edit it manually! 6 | 7 | package v1beta1 8 | 9 | import ( 10 | spec "github.com/go-openapi/spec" 11 | common "k8s.io/kube-openapi/pkg/common" 12 | ) 13 | 14 | func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { 15 | return map[string]common.OpenAPIDefinition{ 16 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.Proxier": schema_pkg_apis_maegus_v1beta1_Proxier(ref), 17 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierSpec": schema_pkg_apis_maegus_v1beta1_ProxierSpec(ref), 18 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierStatus": schema_pkg_apis_maegus_v1beta1_ProxierStatus(ref), 19 | } 20 | } 21 | 22 | func schema_pkg_apis_maegus_v1beta1_Proxier(ref common.ReferenceCallback) common.OpenAPIDefinition { 23 | return common.OpenAPIDefinition{ 24 | Schema: spec.Schema{ 25 | SchemaProps: spec.SchemaProps{ 26 | Description: "Proxier is the Schema for the proxiers API", 27 | Properties: map[string]spec.Schema{ 28 | "kind": { 29 | SchemaProps: spec.SchemaProps{ 30 | Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", 31 | Type: []string{"string"}, 32 | Format: "", 33 | }, 34 | }, 35 | "apiVersion": { 36 | SchemaProps: spec.SchemaProps{ 37 | Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", 38 | Type: []string{"string"}, 39 | Format: "", 40 | }, 41 | }, 42 | "metadata": { 43 | SchemaProps: spec.SchemaProps{ 44 | Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), 45 | }, 46 | }, 47 | "spec": { 48 | SchemaProps: spec.SchemaProps{ 49 | Ref: ref("github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierSpec"), 50 | }, 51 | }, 52 | "status": { 53 | SchemaProps: spec.SchemaProps{ 54 | Ref: ref("github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierStatus"), 55 | }, 56 | }, 57 | }, 58 | }, 59 | }, 60 | Dependencies: []string{ 61 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierSpec", "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, 62 | } 63 | } 64 | 65 | func schema_pkg_apis_maegus_v1beta1_ProxierSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { 66 | return common.OpenAPIDefinition{ 67 | Schema: spec.Schema{ 68 | SchemaProps: spec.SchemaProps{ 69 | Description: "ProxierSpec defines the desired state of Proxier", 70 | Properties: map[string]spec.Schema{ 71 | "backends": { 72 | SchemaProps: spec.SchemaProps{ 73 | Type: []string{"array"}, 74 | Items: &spec.SchemaOrArray{ 75 | Schema: &spec.Schema{ 76 | SchemaProps: spec.SchemaProps{ 77 | Ref: ref("github.com/draveness/proxier/pkg/apis/maegus/v1beta1.BackendSpec"), 78 | }, 79 | }, 80 | }, 81 | }, 82 | }, 83 | "selector": { 84 | SchemaProps: spec.SchemaProps{ 85 | Type: []string{"object"}, 86 | AdditionalProperties: &spec.SchemaOrBool{ 87 | Schema: &spec.Schema{ 88 | SchemaProps: spec.SchemaProps{ 89 | Type: []string{"string"}, 90 | Format: "", 91 | }, 92 | }, 93 | }, 94 | }, 95 | }, 96 | "ports": { 97 | SchemaProps: spec.SchemaProps{ 98 | Type: []string{"array"}, 99 | Items: &spec.SchemaOrArray{ 100 | Schema: &spec.Schema{ 101 | SchemaProps: spec.SchemaProps{ 102 | Ref: ref("github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierPort"), 103 | }, 104 | }, 105 | }, 106 | }, 107 | }, 108 | }, 109 | Required: []string{"backends", "ports"}, 110 | }, 111 | }, 112 | Dependencies: []string{ 113 | "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.BackendSpec", "github.com/draveness/proxier/pkg/apis/maegus/v1beta1.ProxierPort"}, 114 | } 115 | } 116 | 117 | func schema_pkg_apis_maegus_v1beta1_ProxierStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { 118 | return common.OpenAPIDefinition{ 119 | Schema: spec.Schema{ 120 | SchemaProps: spec.SchemaProps{ 121 | Description: "ProxierStatus defines the observed state of Proxier", 122 | Properties: map[string]spec.Schema{ 123 | "activeBackends": { 124 | SchemaProps: spec.SchemaProps{ 125 | Description: "ActiveBackends stores the count of current active services, which are required by the current proxier spec.", 126 | Type: []string{"integer"}, 127 | Format: "int32", 128 | }, 129 | }, 130 | "obsoleteBackends": { 131 | SchemaProps: spec.SchemaProps{ 132 | Description: "ObsoleteBackends stores the count of obsolete services, which should be removed in controller", 133 | Type: []string{"integer"}, 134 | Format: "int32", 135 | }, 136 | }, 137 | }, 138 | }, 139 | }, 140 | Dependencies: []string{}, 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /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 | internalinterfaces "github.com/draveness/proxier/pkg/client/informers/externalversions/internalinterfaces" 27 | maegus "github.com/draveness/proxier/pkg/client/informers/externalversions/maegus" 28 | versioned "github.com/draveness/proxier/pkg/client/versioned" 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 | Maegus() maegus.Interface 176 | } 177 | 178 | func (f *sharedInformerFactory) Maegus() maegus.Interface { 179 | return maegus.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 | v1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 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=maegus.com, Version=v1beta1 56 | case v1beta1.SchemeGroupVersion.WithResource("proxiers"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Maegus().V1beta1().Proxiers().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/draveness/proxier/pkg/client/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 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 31 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 32 | 33 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 34 | type SharedInformerFactory interface { 35 | Start(stopCh <-chan struct{}) 36 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 37 | } 38 | 39 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 40 | type TweakListOptionsFunc func(*v1.ListOptions) 41 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/maegus/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 maegus 20 | 21 | import ( 22 | internalinterfaces "github.com/draveness/proxier/pkg/client/informers/externalversions/internalinterfaces" 23 | v1beta1 "github.com/draveness/proxier/pkg/client/informers/externalversions/maegus/v1beta1" 24 | ) 25 | 26 | // Interface provides access to each of this group's versions. 27 | type Interface interface { 28 | // V1beta1 provides access to shared informers for resources in V1beta1. 29 | V1beta1() v1beta1.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 | // V1beta1 returns a new v1beta1.Interface. 44 | func (g *group) V1beta1() v1beta1.Interface { 45 | return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/maegus/v1beta1/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 v1beta1 20 | 21 | import ( 22 | internalinterfaces "github.com/draveness/proxier/pkg/client/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to all the informers in this group version. 26 | type Interface interface { 27 | // Proxiers returns a ProxierInformer. 28 | Proxiers() ProxierInformer 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 | // Proxiers returns a ProxierInformer. 43 | func (v *version) Proxiers() ProxierInformer { 44 | return &proxierInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 45 | } 46 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/maegus/v1beta1/proxier.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 v1beta1 20 | 21 | import ( 22 | time "time" 23 | 24 | maegusv1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 25 | internalinterfaces "github.com/draveness/proxier/pkg/client/informers/externalversions/internalinterfaces" 26 | v1beta1 "github.com/draveness/proxier/pkg/client/listers/maegus/v1beta1" 27 | versioned "github.com/draveness/proxier/pkg/client/versioned" 28 | 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 | // ProxierInformer provides access to a shared informer and lister for 35 | // Proxiers. 36 | type ProxierInformer interface { 37 | Informer() cache.SharedIndexInformer 38 | Lister() v1beta1.ProxierLister 39 | } 40 | 41 | type proxierInformer struct { 42 | factory internalinterfaces.SharedInformerFactory 43 | tweakListOptions internalinterfaces.TweakListOptionsFunc 44 | namespace string 45 | } 46 | 47 | // NewProxierInformer constructs a new informer for Proxier 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 NewProxierInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 51 | return NewFilteredProxierInformer(client, namespace, resyncPeriod, indexers, nil) 52 | } 53 | 54 | // NewFilteredProxierInformer constructs a new informer for Proxier 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 NewFilteredProxierInformer(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 v1.ListOptions) (runtime.Object, error) { 61 | if tweakListOptions != nil { 62 | tweakListOptions(&options) 63 | } 64 | return client.MaegusV1beta1().Proxiers(namespace).List(options) 65 | }, 66 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 67 | if tweakListOptions != nil { 68 | tweakListOptions(&options) 69 | } 70 | return client.MaegusV1beta1().Proxiers(namespace).Watch(options) 71 | }, 72 | }, 73 | &maegusv1beta1.Proxier{}, 74 | resyncPeriod, 75 | indexers, 76 | ) 77 | } 78 | 79 | func (f *proxierInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 80 | return NewFilteredProxierInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 81 | } 82 | 83 | func (f *proxierInformer) Informer() cache.SharedIndexInformer { 84 | return f.factory.InformerFor(&maegusv1beta1.Proxier{}, f.defaultInformer) 85 | } 86 | 87 | func (f *proxierInformer) Lister() v1beta1.ProxierLister { 88 | return v1beta1.NewProxierLister(f.Informer().GetIndexer()) 89 | } 90 | -------------------------------------------------------------------------------- /pkg/client/listers/maegus/v1beta1/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 v1beta1 20 | 21 | // ProxierListerExpansion allows custom methods to be added to 22 | // ProxierLister. 23 | type ProxierListerExpansion interface{} 24 | 25 | // ProxierNamespaceListerExpansion allows custom methods to be added to 26 | // ProxierNamespaceLister. 27 | type ProxierNamespaceListerExpansion interface{} 28 | -------------------------------------------------------------------------------- /pkg/client/listers/maegus/v1beta1/proxier.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 v1beta1 20 | 21 | import ( 22 | v1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 23 | "k8s.io/apimachinery/pkg/api/errors" 24 | "k8s.io/apimachinery/pkg/labels" 25 | "k8s.io/client-go/tools/cache" 26 | ) 27 | 28 | // ProxierLister helps list Proxiers. 29 | type ProxierLister interface { 30 | // List lists all Proxiers in the indexer. 31 | List(selector labels.Selector) (ret []*v1beta1.Proxier, err error) 32 | // Proxiers returns an object that can list and get Proxiers. 33 | Proxiers(namespace string) ProxierNamespaceLister 34 | ProxierListerExpansion 35 | } 36 | 37 | // proxierLister implements the ProxierLister interface. 38 | type proxierLister struct { 39 | indexer cache.Indexer 40 | } 41 | 42 | // NewProxierLister returns a new ProxierLister. 43 | func NewProxierLister(indexer cache.Indexer) ProxierLister { 44 | return &proxierLister{indexer: indexer} 45 | } 46 | 47 | // List lists all Proxiers in the indexer. 48 | func (s *proxierLister) List(selector labels.Selector) (ret []*v1beta1.Proxier, err error) { 49 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 50 | ret = append(ret, m.(*v1beta1.Proxier)) 51 | }) 52 | return ret, err 53 | } 54 | 55 | // Proxiers returns an object that can list and get Proxiers. 56 | func (s *proxierLister) Proxiers(namespace string) ProxierNamespaceLister { 57 | return proxierNamespaceLister{indexer: s.indexer, namespace: namespace} 58 | } 59 | 60 | // ProxierNamespaceLister helps list and get Proxiers. 61 | type ProxierNamespaceLister interface { 62 | // List lists all Proxiers in the indexer for a given namespace. 63 | List(selector labels.Selector) (ret []*v1beta1.Proxier, err error) 64 | // Get retrieves the Proxier from the indexer for a given namespace and name. 65 | Get(name string) (*v1beta1.Proxier, error) 66 | ProxierNamespaceListerExpansion 67 | } 68 | 69 | // proxierNamespaceLister implements the ProxierNamespaceLister 70 | // interface. 71 | type proxierNamespaceLister struct { 72 | indexer cache.Indexer 73 | namespace string 74 | } 75 | 76 | // List lists all Proxiers in the indexer for a given namespace. 77 | func (s proxierNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.Proxier, err error) { 78 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 79 | ret = append(ret, m.(*v1beta1.Proxier)) 80 | }) 81 | return ret, err 82 | } 83 | 84 | // Get retrieves the Proxier from the indexer for a given namespace and name. 85 | func (s proxierNamespaceLister) Get(name string) (*v1beta1.Proxier, 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(v1beta1.Resource("proxier"), name) 92 | } 93 | return obj.(*v1beta1.Proxier), nil 94 | } 95 | -------------------------------------------------------------------------------- /pkg/client/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 | maegusv1beta1 "github.com/draveness/proxier/pkg/client/versioned/typed/maegus/v1beta1" 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 | MaegusV1beta1() maegusv1beta1.MaegusV1beta1Interface 31 | } 32 | 33 | // Clientset contains the clients for groups. Each group has exactly one 34 | // version included in a Clientset. 35 | type Clientset struct { 36 | *discovery.DiscoveryClient 37 | maegusV1beta1 *maegusv1beta1.MaegusV1beta1Client 38 | } 39 | 40 | // MaegusV1beta1 retrieves the MaegusV1beta1Client 41 | func (c *Clientset) MaegusV1beta1() maegusv1beta1.MaegusV1beta1Interface { 42 | return c.maegusV1beta1 43 | } 44 | 45 | // Discovery retrieves the DiscoveryClient 46 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 47 | if c == nil { 48 | return nil 49 | } 50 | return c.DiscoveryClient 51 | } 52 | 53 | // NewForConfig creates a new Clientset for the given config. 54 | func NewForConfig(c *rest.Config) (*Clientset, error) { 55 | configShallowCopy := *c 56 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 57 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 58 | } 59 | var cs Clientset 60 | var err error 61 | cs.maegusV1beta1, err = maegusv1beta1.NewForConfig(&configShallowCopy) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 67 | if err != nil { 68 | return nil, err 69 | } 70 | return &cs, nil 71 | } 72 | 73 | // NewForConfigOrDie creates a new Clientset for the given config and 74 | // panics if there is an error in the config. 75 | func NewForConfigOrDie(c *rest.Config) *Clientset { 76 | var cs Clientset 77 | cs.maegusV1beta1 = maegusv1beta1.NewForConfigOrDie(c) 78 | 79 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 80 | return &cs 81 | } 82 | 83 | // New creates a new Clientset for the given RESTClient. 84 | func New(c rest.Interface) *Clientset { 85 | var cs Clientset 86 | cs.maegusV1beta1 = maegusv1beta1.New(c) 87 | 88 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 89 | return &cs 90 | } 91 | -------------------------------------------------------------------------------- /pkg/client/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/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/draveness/proxier/pkg/client/versioned" 23 | maegusv1beta1 "github.com/draveness/proxier/pkg/client/versioned/typed/maegus/v1beta1" 24 | fakemaegusv1beta1 "github.com/draveness/proxier/pkg/client/versioned/typed/maegus/v1beta1/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 | cs := &Clientset{} 45 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 46 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 47 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 48 | gvr := action.GetResource() 49 | ns := action.GetNamespace() 50 | watch, err := o.Watch(gvr, ns) 51 | if err != nil { 52 | return false, nil, err 53 | } 54 | return true, watch, nil 55 | }) 56 | 57 | return cs 58 | } 59 | 60 | // Clientset implements clientset.Interface. Meant to be embedded into a 61 | // struct to get a default implementation. This makes faking out just the method 62 | // you want to test easier. 63 | type Clientset struct { 64 | testing.Fake 65 | discovery *fakediscovery.FakeDiscovery 66 | } 67 | 68 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 69 | return c.discovery 70 | } 71 | 72 | var _ clientset.Interface = &Clientset{} 73 | 74 | // MaegusV1beta1 retrieves the MaegusV1beta1Client 75 | func (c *Clientset) MaegusV1beta1() maegusv1beta1.MaegusV1beta1Interface { 76 | return &fakemaegusv1beta1.FakeMaegusV1beta1{Fake: &c.Fake} 77 | } 78 | -------------------------------------------------------------------------------- /pkg/client/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/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 | maegusv1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 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 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | var parameterCodec = runtime.NewParameterCodec(scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | maegusv1beta1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/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/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 | maegusv1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 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 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | maegusv1beta1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/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 v1beta1 21 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/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/versioned/typed/maegus/v1beta1/fake/fake_maegus_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 | v1beta1 "github.com/draveness/proxier/pkg/client/versioned/typed/maegus/v1beta1" 23 | rest "k8s.io/client-go/rest" 24 | testing "k8s.io/client-go/testing" 25 | ) 26 | 27 | type FakeMaegusV1beta1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeMaegusV1beta1) Proxiers(namespace string) v1beta1.ProxierInterface { 32 | return &FakeProxiers{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 *FakeMaegusV1beta1) RESTClient() rest.Interface { 38 | var ret *rest.RESTClient 39 | return ret 40 | } 41 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/fake/fake_proxier.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 | v1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 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 | // FakeProxiers implements ProxierInterface 32 | type FakeProxiers struct { 33 | Fake *FakeMaegusV1beta1 34 | ns string 35 | } 36 | 37 | var proxiersResource = schema.GroupVersionResource{Group: "maegus.com", Version: "v1beta1", Resource: "proxiers"} 38 | 39 | var proxiersKind = schema.GroupVersionKind{Group: "maegus.com", Version: "v1beta1", Kind: "Proxier"} 40 | 41 | // Get takes name of the proxier, and returns the corresponding proxier object, and an error if there is any. 42 | func (c *FakeProxiers) Get(name string, options v1.GetOptions) (result *v1beta1.Proxier, err error) { 43 | obj, err := c.Fake. 44 | Invokes(testing.NewGetAction(proxiersResource, c.ns, name), &v1beta1.Proxier{}) 45 | 46 | if obj == nil { 47 | return nil, err 48 | } 49 | return obj.(*v1beta1.Proxier), err 50 | } 51 | 52 | // List takes label and field selectors, and returns the list of Proxiers that match those selectors. 53 | func (c *FakeProxiers) List(opts v1.ListOptions) (result *v1beta1.ProxierList, err error) { 54 | obj, err := c.Fake. 55 | Invokes(testing.NewListAction(proxiersResource, proxiersKind, c.ns, opts), &v1beta1.ProxierList{}) 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 := &v1beta1.ProxierList{ListMeta: obj.(*v1beta1.ProxierList).ListMeta} 66 | for _, item := range obj.(*v1beta1.ProxierList).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 proxiers. 75 | func (c *FakeProxiers) Watch(opts v1.ListOptions) (watch.Interface, error) { 76 | return c.Fake. 77 | InvokesWatch(testing.NewWatchAction(proxiersResource, c.ns, opts)) 78 | 79 | } 80 | 81 | // Create takes the representation of a proxier and creates it. Returns the server's representation of the proxier, and an error, if there is any. 82 | func (c *FakeProxiers) Create(proxier *v1beta1.Proxier) (result *v1beta1.Proxier, err error) { 83 | obj, err := c.Fake. 84 | Invokes(testing.NewCreateAction(proxiersResource, c.ns, proxier), &v1beta1.Proxier{}) 85 | 86 | if obj == nil { 87 | return nil, err 88 | } 89 | return obj.(*v1beta1.Proxier), err 90 | } 91 | 92 | // Update takes the representation of a proxier and updates it. Returns the server's representation of the proxier, and an error, if there is any. 93 | func (c *FakeProxiers) Update(proxier *v1beta1.Proxier) (result *v1beta1.Proxier, err error) { 94 | obj, err := c.Fake. 95 | Invokes(testing.NewUpdateAction(proxiersResource, c.ns, proxier), &v1beta1.Proxier{}) 96 | 97 | if obj == nil { 98 | return nil, err 99 | } 100 | return obj.(*v1beta1.Proxier), err 101 | } 102 | 103 | // UpdateStatus was generated because the type contains a Status member. 104 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 105 | func (c *FakeProxiers) UpdateStatus(proxier *v1beta1.Proxier) (*v1beta1.Proxier, error) { 106 | obj, err := c.Fake. 107 | Invokes(testing.NewUpdateSubresourceAction(proxiersResource, "status", c.ns, proxier), &v1beta1.Proxier{}) 108 | 109 | if obj == nil { 110 | return nil, err 111 | } 112 | return obj.(*v1beta1.Proxier), err 113 | } 114 | 115 | // Delete takes name of the proxier and deletes it. Returns an error if one occurs. 116 | func (c *FakeProxiers) Delete(name string, options *v1.DeleteOptions) error { 117 | _, err := c.Fake. 118 | Invokes(testing.NewDeleteAction(proxiersResource, c.ns, name), &v1beta1.Proxier{}) 119 | 120 | return err 121 | } 122 | 123 | // DeleteCollection deletes a collection of objects. 124 | func (c *FakeProxiers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 125 | action := testing.NewDeleteCollectionAction(proxiersResource, c.ns, listOptions) 126 | 127 | _, err := c.Fake.Invokes(action, &v1beta1.ProxierList{}) 128 | return err 129 | } 130 | 131 | // Patch applies the patch and returns the patched proxier. 132 | func (c *FakeProxiers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Proxier, err error) { 133 | obj, err := c.Fake. 134 | Invokes(testing.NewPatchSubresourceAction(proxiersResource, c.ns, name, pt, data, subresources...), &v1beta1.Proxier{}) 135 | 136 | if obj == nil { 137 | return nil, err 138 | } 139 | return obj.(*v1beta1.Proxier), err 140 | } 141 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/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 v1beta1 20 | 21 | type ProxierExpansion interface{} 22 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/maegus_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 v1beta1 20 | 21 | import ( 22 | v1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 23 | "github.com/draveness/proxier/pkg/client/versioned/scheme" 24 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 25 | rest "k8s.io/client-go/rest" 26 | ) 27 | 28 | type MaegusV1beta1Interface interface { 29 | RESTClient() rest.Interface 30 | ProxiersGetter 31 | } 32 | 33 | // MaegusV1beta1Client is used to interact with features provided by the maegus.com group. 34 | type MaegusV1beta1Client struct { 35 | restClient rest.Interface 36 | } 37 | 38 | func (c *MaegusV1beta1Client) Proxiers(namespace string) ProxierInterface { 39 | return newProxiers(c, namespace) 40 | } 41 | 42 | // NewForConfig creates a new MaegusV1beta1Client for the given config. 43 | func NewForConfig(c *rest.Config) (*MaegusV1beta1Client, 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 &MaegusV1beta1Client{client}, nil 53 | } 54 | 55 | // NewForConfigOrDie creates a new MaegusV1beta1Client for the given config and 56 | // panics if there is an error in the config. 57 | func NewForConfigOrDie(c *rest.Config) *MaegusV1beta1Client { 58 | client, err := NewForConfig(c) 59 | if err != nil { 60 | panic(err) 61 | } 62 | return client 63 | } 64 | 65 | // New creates a new MaegusV1beta1Client for the given RESTClient. 66 | func New(c rest.Interface) *MaegusV1beta1Client { 67 | return &MaegusV1beta1Client{c} 68 | } 69 | 70 | func setConfigDefaults(config *rest.Config) error { 71 | gv := v1beta1.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 *MaegusV1beta1Client) RESTClient() rest.Interface { 86 | if c == nil { 87 | return nil 88 | } 89 | return c.restClient 90 | } 91 | -------------------------------------------------------------------------------- /pkg/client/versioned/typed/maegus/v1beta1/proxier.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 v1beta1 20 | 21 | import ( 22 | "time" 23 | 24 | v1beta1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 25 | scheme "github.com/draveness/proxier/pkg/client/versioned/scheme" 26 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | types "k8s.io/apimachinery/pkg/types" 28 | watch "k8s.io/apimachinery/pkg/watch" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | // ProxiersGetter has a method to return a ProxierInterface. 33 | // A group's client should implement this interface. 34 | type ProxiersGetter interface { 35 | Proxiers(namespace string) ProxierInterface 36 | } 37 | 38 | // ProxierInterface has methods to work with Proxier resources. 39 | type ProxierInterface interface { 40 | Create(*v1beta1.Proxier) (*v1beta1.Proxier, error) 41 | Update(*v1beta1.Proxier) (*v1beta1.Proxier, error) 42 | UpdateStatus(*v1beta1.Proxier) (*v1beta1.Proxier, error) 43 | Delete(name string, options *v1.DeleteOptions) error 44 | DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error 45 | Get(name string, options v1.GetOptions) (*v1beta1.Proxier, error) 46 | List(opts v1.ListOptions) (*v1beta1.ProxierList, error) 47 | Watch(opts v1.ListOptions) (watch.Interface, error) 48 | Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Proxier, err error) 49 | ProxierExpansion 50 | } 51 | 52 | // proxiers implements ProxierInterface 53 | type proxiers struct { 54 | client rest.Interface 55 | ns string 56 | } 57 | 58 | // newProxiers returns a Proxiers 59 | func newProxiers(c *MaegusV1beta1Client, namespace string) *proxiers { 60 | return &proxiers{ 61 | client: c.RESTClient(), 62 | ns: namespace, 63 | } 64 | } 65 | 66 | // Get takes name of the proxier, and returns the corresponding proxier object, and an error if there is any. 67 | func (c *proxiers) Get(name string, options v1.GetOptions) (result *v1beta1.Proxier, err error) { 68 | result = &v1beta1.Proxier{} 69 | err = c.client.Get(). 70 | Namespace(c.ns). 71 | Resource("proxiers"). 72 | Name(name). 73 | VersionedParams(&options, scheme.ParameterCodec). 74 | Do(). 75 | Into(result) 76 | return 77 | } 78 | 79 | // List takes label and field selectors, and returns the list of Proxiers that match those selectors. 80 | func (c *proxiers) List(opts v1.ListOptions) (result *v1beta1.ProxierList, err error) { 81 | var timeout time.Duration 82 | if opts.TimeoutSeconds != nil { 83 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 84 | } 85 | result = &v1beta1.ProxierList{} 86 | err = c.client.Get(). 87 | Namespace(c.ns). 88 | Resource("proxiers"). 89 | VersionedParams(&opts, scheme.ParameterCodec). 90 | Timeout(timeout). 91 | Do(). 92 | Into(result) 93 | return 94 | } 95 | 96 | // Watch returns a watch.Interface that watches the requested proxiers. 97 | func (c *proxiers) Watch(opts v1.ListOptions) (watch.Interface, error) { 98 | var timeout time.Duration 99 | if opts.TimeoutSeconds != nil { 100 | timeout = time.Duration(*opts.TimeoutSeconds) * time.Second 101 | } 102 | opts.Watch = true 103 | return c.client.Get(). 104 | Namespace(c.ns). 105 | Resource("proxiers"). 106 | VersionedParams(&opts, scheme.ParameterCodec). 107 | Timeout(timeout). 108 | Watch() 109 | } 110 | 111 | // Create takes the representation of a proxier and creates it. Returns the server's representation of the proxier, and an error, if there is any. 112 | func (c *proxiers) Create(proxier *v1beta1.Proxier) (result *v1beta1.Proxier, err error) { 113 | result = &v1beta1.Proxier{} 114 | err = c.client.Post(). 115 | Namespace(c.ns). 116 | Resource("proxiers"). 117 | Body(proxier). 118 | Do(). 119 | Into(result) 120 | return 121 | } 122 | 123 | // Update takes the representation of a proxier and updates it. Returns the server's representation of the proxier, and an error, if there is any. 124 | func (c *proxiers) Update(proxier *v1beta1.Proxier) (result *v1beta1.Proxier, err error) { 125 | result = &v1beta1.Proxier{} 126 | err = c.client.Put(). 127 | Namespace(c.ns). 128 | Resource("proxiers"). 129 | Name(proxier.Name). 130 | Body(proxier). 131 | Do(). 132 | Into(result) 133 | return 134 | } 135 | 136 | // UpdateStatus was generated because the type contains a Status member. 137 | // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). 138 | 139 | func (c *proxiers) UpdateStatus(proxier *v1beta1.Proxier) (result *v1beta1.Proxier, err error) { 140 | result = &v1beta1.Proxier{} 141 | err = c.client.Put(). 142 | Namespace(c.ns). 143 | Resource("proxiers"). 144 | Name(proxier.Name). 145 | SubResource("status"). 146 | Body(proxier). 147 | Do(). 148 | Into(result) 149 | return 150 | } 151 | 152 | // Delete takes name of the proxier and deletes it. Returns an error if one occurs. 153 | func (c *proxiers) Delete(name string, options *v1.DeleteOptions) error { 154 | return c.client.Delete(). 155 | Namespace(c.ns). 156 | Resource("proxiers"). 157 | Name(name). 158 | Body(options). 159 | Do(). 160 | Error() 161 | } 162 | 163 | // DeleteCollection deletes a collection of objects. 164 | func (c *proxiers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { 165 | var timeout time.Duration 166 | if listOptions.TimeoutSeconds != nil { 167 | timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second 168 | } 169 | return c.client.Delete(). 170 | Namespace(c.ns). 171 | Resource("proxiers"). 172 | VersionedParams(&listOptions, scheme.ParameterCodec). 173 | Timeout(timeout). 174 | Body(options). 175 | Do(). 176 | Error() 177 | } 178 | 179 | // Patch applies the patch and returns the patched proxier. 180 | func (c *proxiers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.Proxier, err error) { 181 | result = &v1beta1.Proxier{} 182 | err = c.client.Patch(pt). 183 | Namespace(c.ns). 184 | Resource("proxiers"). 185 | SubResource(subresources...). 186 | Name(name). 187 | Body(data). 188 | Do(). 189 | Into(result) 190 | return 191 | } 192 | -------------------------------------------------------------------------------- /pkg/controller/add_proxier.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/draveness/proxier/pkg/controller/proxier" 5 | ) 6 | 7 | func init() { 8 | // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. 9 | AddToManagerFuncs = append(AddToManagerFuncs, proxier.Add) 10 | } 11 | -------------------------------------------------------------------------------- /pkg/controller/controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "sigs.k8s.io/controller-runtime/pkg/manager" 5 | ) 6 | 7 | // AddToManagerFuncs is a list of functions to add all Controllers to the Manager 8 | var AddToManagerFuncs []func(manager.Manager) error 9 | 10 | // AddToManager adds all Controllers to the Manager 11 | func AddToManager(m manager.Manager) error { 12 | for _, f := range AddToManagerFuncs { 13 | if err := f(m); err != nil { 14 | return err 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/controller/proxier/deployment.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "context" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | "github.com/draveness/proxier/pkg/controller/proxier/nginx" 8 | appsv1 "k8s.io/api/apps/v1" 9 | corev1 "k8s.io/api/core/v1" 10 | "k8s.io/apimachinery/pkg/api/errors" 11 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 | "k8s.io/apimachinery/pkg/types" 13 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 14 | ) 15 | 16 | func (r *ReconcileProxier) syncDeployment(instance *maegusv1.Proxier) error { 17 | // Sync ConfigMap for deployment 18 | newConfigMap := &corev1.ConfigMap{ 19 | ObjectMeta: metav1.ObjectMeta{ 20 | Name: instance.Name + "-proxy-configmap", 21 | Namespace: instance.Namespace, 22 | }, 23 | Data: map[string]string{ 24 | "nginx.conf": nginx.NewConfig(instance), 25 | }, 26 | } 27 | 28 | if err := controllerutil.SetControllerReference(instance, newConfigMap, r.scheme); err != nil { 29 | return err 30 | } 31 | 32 | foundConfigMap := &corev1.ConfigMap{} 33 | err := r.client.Get(context.Background(), types.NamespacedName{Name: newConfigMap.Name, Namespace: newConfigMap.Namespace}, foundConfigMap) 34 | if err != nil && errors.IsNotFound(err) { 35 | err = r.client.Create(context.Background(), newConfigMap) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | // ConfigMap created successfully - don't requeue 41 | return nil 42 | } else if err != nil { 43 | return err 44 | } 45 | 46 | foundConfigMap.Data = newConfigMap.Data 47 | 48 | err = r.client.Update(context.Background(), foundConfigMap) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | deployment, err := NewDeployment(instance) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | annotations := map[string]string{} 59 | annotations[maegusv1.ConfigMapHashAnnotationKey] = computeHash(newConfigMap) 60 | deployment.Spec.Template.ObjectMeta.Annotations = annotations 61 | 62 | if err := controllerutil.SetControllerReference(instance, deployment, r.scheme); err != nil { 63 | return err 64 | } 65 | 66 | // Check if this Deployment already exists 67 | foundDeployment := &appsv1.Deployment{} 68 | err = r.client.Get(context.Background(), types.NamespacedName{Name: deployment.Name, Namespace: deployment.Namespace}, foundDeployment) 69 | if err != nil && errors.IsNotFound(err) { 70 | err = r.client.Create(context.Background(), deployment) 71 | if err != nil { 72 | return err 73 | } 74 | 75 | // Deployment created successfully - don't requeue 76 | return nil 77 | } else if err != nil { 78 | return err 79 | } 80 | 81 | foundDeployment.Spec.Template = deployment.Spec.Template 82 | 83 | err = r.client.Update(context.Background(), foundDeployment) 84 | if err != nil { 85 | return err 86 | } 87 | 88 | return nil 89 | } 90 | 91 | // NewDeployment returns a nginx pod with the same namespace as the instance 92 | func NewDeployment(instance *maegusv1.Proxier) (*appsv1.Deployment, error) { 93 | labels := NewPodLabels(instance) 94 | 95 | replicas := int32(1) 96 | 97 | deployment := appsv1.Deployment{ 98 | ObjectMeta: metav1.ObjectMeta{ 99 | Name: NewDeploymentName(instance), 100 | Namespace: instance.Namespace, 101 | Labels: labels, 102 | }, 103 | Spec: appsv1.DeploymentSpec{ 104 | Replicas: &replicas, 105 | Selector: &metav1.LabelSelector{ 106 | MatchLabels: labels, 107 | }, 108 | Template: corev1.PodTemplateSpec{ 109 | ObjectMeta: metav1.ObjectMeta{ 110 | Name: instance.Name + "-proxy", 111 | Namespace: instance.Namespace, 112 | Labels: labels, 113 | }, 114 | Spec: corev1.PodSpec{ 115 | Containers: []corev1.Container{ 116 | { 117 | Name: "nginx", 118 | Image: "nginx:1.15.9", 119 | Ports: []corev1.ContainerPort{ 120 | { 121 | ContainerPort: 80, 122 | }, 123 | }, 124 | VolumeMounts: []corev1.VolumeMount{ 125 | { 126 | Name: instance.Name + "-proxy-configmap", 127 | MountPath: "/etc/nginx", 128 | ReadOnly: true, 129 | }, 130 | }, 131 | }, 132 | }, 133 | Volumes: []corev1.Volume{ 134 | { 135 | Name: instance.Name + "-proxy-configmap", 136 | VolumeSource: corev1.VolumeSource{ 137 | ConfigMap: &corev1.ConfigMapVolumeSource{ 138 | LocalObjectReference: corev1.LocalObjectReference{ 139 | Name: instance.Name + "-proxy-configmap", 140 | }, 141 | }, 142 | }, 143 | }, 144 | }, 145 | }, 146 | }, 147 | }, 148 | } 149 | 150 | return &deployment, nil 151 | } 152 | 153 | // NewDeploymentName returns deployment name for specific proxier. 154 | func NewDeploymentName(instance *maegusv1.Proxier) string { 155 | return instance.Name + "-proxy" 156 | } 157 | -------------------------------------------------------------------------------- /pkg/controller/proxier/label.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "fmt" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | ) 8 | 9 | // NewPodLabels returns label used for pod. 10 | func NewPodLabels(proxier *maegusv1.Proxier) map[string]string { 11 | return map[string]string{ 12 | maegusv1.ProxierKeyLabel: fmt.Sprintf("%s", proxier.Name), 13 | } 14 | } 15 | 16 | // NewServiceLabels returns label used for service. 17 | func NewServiceLabels(proxier *maegusv1.Proxier) map[string]string { 18 | return map[string]string{ 19 | maegusv1.ProxierKeyLabel: fmt.Sprintf("%s", proxier.Name), 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pkg/controller/proxier/label_test.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "testing" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | "github.com/stretchr/testify/assert" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | func TestNewPodLabels(t *testing.T) { 12 | proxier := &maegusv1.Proxier{ 13 | ObjectMeta: metav1.ObjectMeta{ 14 | Name: "test", 15 | Namespace: "default", 16 | }, 17 | } 18 | 19 | labels := NewPodLabels(proxier) 20 | assert.Equal(t, map[string]string{ 21 | maegusv1.ProxierKeyLabel: "test", 22 | }, labels) 23 | } 24 | 25 | func TestNewServiceLabels(t *testing.T) { 26 | proxier := &maegusv1.Proxier{ 27 | ObjectMeta: metav1.ObjectMeta{ 28 | Name: "test", 29 | Namespace: "default", 30 | }, 31 | } 32 | 33 | labels := NewServiceLabels(proxier) 34 | assert.Equal(t, map[string]string{ 35 | maegusv1.ProxierKeyLabel: "test", 36 | }, labels) 37 | } 38 | -------------------------------------------------------------------------------- /pkg/controller/proxier/nginx/nginx.go: -------------------------------------------------------------------------------- 1 | package nginx 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 8 | ) 9 | 10 | type server struct { 11 | name string 12 | protocol string 13 | port int32 14 | upstream string 15 | } 16 | 17 | func (s server) conf() string { 18 | var protocol string 19 | if string(s.protocol) == "udp" { 20 | protocol = "udp" 21 | } 22 | return fmt.Sprintf(` 23 | server { 24 | listen %d %s; 25 | proxy_pass %s; 26 | } 27 | `, s.port, protocol, s.upstream) 28 | } 29 | 30 | type upstream struct { 31 | name string 32 | backends []backend 33 | port int32 34 | } 35 | 36 | func (up upstream) conf() string { 37 | backendStrs := "" 38 | for _, backend := range up.backends { 39 | backendStrs += fmt.Sprintf(" server %s:%d weight=%d;\n", backend.name, up.port, backend.weight) 40 | } 41 | 42 | return fmt.Sprintf(` 43 | upstream %s { 44 | %s 45 | } 46 | `, up.name, backendStrs) 47 | } 48 | 49 | type backend struct { 50 | name string 51 | weight int32 52 | } 53 | 54 | func NewConfig(instance *maegusv1.Proxier) string { 55 | servers := []server{} 56 | for _, port := range instance.Spec.Ports { 57 | server := server{ 58 | name: port.Name, 59 | protocol: strings.ToLower(string(port.Protocol)), 60 | port: port.Port, 61 | upstream: fmt.Sprintf("upstream_%s", port.Name), 62 | } 63 | servers = append(servers, server) 64 | } 65 | 66 | backends := []backend{} 67 | for _, be := range instance.Spec.Backends { 68 | backend := backend{ 69 | name: fmt.Sprintf("%s-%s-backend", instance.Name, be.Name), 70 | weight: be.Weight, 71 | } 72 | backends = append(backends, backend) 73 | } 74 | 75 | upstreams := []upstream{} 76 | for _, server := range servers { 77 | upstreams = append(upstreams, upstream{ 78 | name: server.upstream, 79 | port: server.port, 80 | backends: backends, 81 | }) 82 | } 83 | 84 | conf := "" 85 | conf += "events {\n" 86 | conf += " worker_connections 1024;\n" 87 | conf += "}\n" 88 | conf += "stream {\n" 89 | 90 | for _, server := range servers { 91 | conf += server.conf() 92 | } 93 | 94 | for _, upstream := range upstreams { 95 | conf += upstream.conf() 96 | } 97 | 98 | conf += "}\n" 99 | 100 | return conf 101 | } 102 | -------------------------------------------------------------------------------- /pkg/controller/proxier/proxier_controller.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "context" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | 8 | corev1 "k8s.io/api/core/v1" 9 | "k8s.io/apimachinery/pkg/api/errors" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | "k8s.io/apimachinery/pkg/runtime" 12 | "k8s.io/apimachinery/pkg/types" 13 | "sigs.k8s.io/controller-runtime/pkg/client" 14 | "sigs.k8s.io/controller-runtime/pkg/controller" 15 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 16 | "sigs.k8s.io/controller-runtime/pkg/handler" 17 | "sigs.k8s.io/controller-runtime/pkg/manager" 18 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 19 | logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" 20 | "sigs.k8s.io/controller-runtime/pkg/source" 21 | ) 22 | 23 | var log = logf.Log.WithName("controller_proxier") 24 | 25 | // Add creates a new Proxier Controller and adds it to the Manager. The Manager will set fields on the Controller 26 | // and Start it when the Manager is Started. 27 | func Add(mgr manager.Manager) error { 28 | return add(mgr, newReconciler(mgr)) 29 | } 30 | 31 | // newReconciler returns a new reconcile.Reconciler 32 | func newReconciler(mgr manager.Manager) reconcile.Reconciler { 33 | return &ReconcileProxier{client: mgr.GetClient(), scheme: mgr.GetScheme()} 34 | } 35 | 36 | // add adds a new Controller to mgr with r as the reconcile.Reconciler 37 | func add(mgr manager.Manager, r reconcile.Reconciler) error { 38 | // Create a new controller 39 | c, err := controller.New("proxier-controller", mgr, controller.Options{Reconciler: r}) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | err = c.Watch(&source.Kind{Type: &maegusv1.Proxier{}}, &handler.EnqueueRequestForObject{}) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | err = c.Watch(&source.Kind{Type: &corev1.ConfigMap{}}, &handler.EnqueueRequestForOwner{ 50 | IsController: true, 51 | OwnerType: &maegusv1.Proxier{}, 52 | }) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{ 58 | IsController: true, 59 | OwnerType: &maegusv1.Proxier{}, 60 | }) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | err = c.Watch(&source.Kind{Type: &corev1.Service{}}, &handler.EnqueueRequestForOwner{ 66 | IsController: true, 67 | OwnerType: &maegusv1.Proxier{}, 68 | }) 69 | if err != nil { 70 | return err 71 | } 72 | 73 | return nil 74 | } 75 | 76 | var _ reconcile.Reconciler = &ReconcileProxier{} 77 | 78 | // ReconcileProxier reconciles a Proxier object 79 | type ReconcileProxier struct { 80 | // This client, initialized using mgr.Client() above, is a split client 81 | // that reads objects from the cache and writes to the apiserver 82 | client client.Client 83 | scheme *runtime.Scheme 84 | } 85 | 86 | // Reconcile reads that state of the cluster for a Proxier object and makes changes based on the state read 87 | // and what is in the Proxier.Spec 88 | func (r *ReconcileProxier) Reconcile(request reconcile.Request) (reconcile.Result, error) { 89 | reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) 90 | reqLogger.Info("Reconciling Proxier") 91 | 92 | // Fetch the Proxier instance 93 | instance := &maegusv1.Proxier{} 94 | err := r.client.Get(context.Background(), request.NamespacedName, instance) 95 | if err != nil { 96 | if errors.IsNotFound(err) { 97 | // Request object not found, could have been deleted after reconcile request. 98 | // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 99 | // Return and don't requeue 100 | return reconcile.Result{}, nil 101 | } 102 | // Error reading the object - requeue the request. 103 | return reconcile.Result{}, err 104 | } 105 | 106 | if err := r.syncProxierStatus(instance); err != nil { 107 | return reconcile.Result{}, err 108 | } 109 | 110 | if err := r.syncServers(instance); err != nil { 111 | return reconcile.Result{}, err 112 | } 113 | 114 | if err := r.syncDeployment(instance); err != nil { 115 | return reconcile.Result{}, err 116 | } 117 | 118 | if err := r.syncService(instance); err != nil { 119 | return reconcile.Result{}, err 120 | } 121 | 122 | return reconcile.Result{}, nil 123 | } 124 | 125 | func (r *ReconcileProxier) syncService(instance *maegusv1.Proxier) error { 126 | // Define a new Pod object 127 | service, err := NewServiceForProxier(instance) 128 | if err != nil { 129 | return err 130 | } 131 | 132 | // Set Proxier instance as the owner and controller 133 | if err := controllerutil.SetControllerReference(instance, service, r.scheme); err != nil { 134 | return err 135 | } 136 | 137 | // Check if this Service already exists 138 | found := &corev1.Service{} 139 | err = r.client.Get(context.Background(), types.NamespacedName{Name: service.Name, Namespace: service.Namespace}, found) 140 | if err != nil && errors.IsNotFound(err) { 141 | err = r.client.Create(context.Background(), service) 142 | if err != nil { 143 | return err 144 | } 145 | 146 | // Service created successfully - don't requeue 147 | return nil 148 | } else if err != nil { 149 | return err 150 | } 151 | 152 | found.Spec.Ports = service.Spec.Ports 153 | found.Spec.Selector = service.Spec.Selector 154 | 155 | err = r.client.Update(context.Background(), found) 156 | if err != nil { 157 | return err 158 | } 159 | 160 | return nil 161 | } 162 | 163 | // NewServiceForProxier returns a service for proxier. 164 | func NewServiceForProxier(instance *maegusv1.Proxier) (*corev1.Service, error) { 165 | proxierPorts := []corev1.ServicePort{} 166 | for _, port := range instance.Spec.Ports { 167 | proxierPorts = append(proxierPorts, corev1.ServicePort{ 168 | Name: port.Name, 169 | Protocol: corev1.Protocol(port.Protocol), 170 | Port: port.Port, 171 | }) 172 | } 173 | 174 | return &corev1.Service{ 175 | ObjectMeta: metav1.ObjectMeta{ 176 | Name: instance.Name, 177 | Namespace: instance.Namespace, 178 | }, 179 | Spec: corev1.ServiceSpec{ 180 | Selector: NewPodLabels(instance), 181 | Type: corev1.ServiceTypeClusterIP, 182 | Ports: proxierPorts, 183 | }, 184 | }, nil 185 | } 186 | -------------------------------------------------------------------------------- /pkg/controller/proxier/servers.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "reflect" 7 | "sync" 8 | 9 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 10 | corev1 "k8s.io/api/core/v1" 11 | "k8s.io/apimachinery/pkg/api/errors" 12 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 | "k8s.io/apimachinery/pkg/types" 14 | "sigs.k8s.io/controller-runtime/pkg/client" 15 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 16 | ) 17 | 18 | func (r *ReconcileProxier) syncProxierStatus(instance *maegusv1.Proxier) error { 19 | var serviceList corev1.ServiceList 20 | if err := r.client.List(context.Background(), client.MatchingLabels(NewServiceLabels(instance)), &serviceList); err != nil { 21 | return err 22 | } 23 | 24 | _, obsoleteServices, activeServices := groupServers(instance, serviceList.Items) 25 | 26 | newStatus := maegusv1.ProxierStatus{ 27 | ActiveBackends: int32(len(activeServices)), 28 | ObsoleteBackends: int32(len(obsoleteServices)), 29 | } 30 | 31 | if reflect.DeepEqual(instance.Status, newStatus) { 32 | return nil 33 | } 34 | 35 | newProxier := instance 36 | newProxier.Status = newStatus 37 | return r.client.Status().Update(context.Background(), newProxier) 38 | } 39 | 40 | func (r *ReconcileProxier) syncServers(instance *maegusv1.Proxier) error { 41 | var serviceList corev1.ServiceList 42 | if err := r.client.List(context.Background(), client.MatchingLabels(NewServiceLabels(instance)), &serviceList); err != nil { 43 | return err 44 | } 45 | 46 | servicesToCreate, servicesToDelete, _ := groupServers(instance, serviceList.Items) 47 | 48 | waitGroup := sync.WaitGroup{} 49 | waitGroup.Add(len(servicesToDelete)) 50 | for i := range servicesToDelete { 51 | serviceToDelete := servicesToDelete[i] 52 | go func(service *corev1.Service) { 53 | defer waitGroup.Done() 54 | if err := r.client.Delete(context.Background(), service); err != nil { 55 | // TODO: handle delete service error in sync servers 56 | } 57 | }(&serviceToDelete) 58 | } 59 | waitGroup.Wait() 60 | 61 | createErrCh := make(chan error, len(servicesToCreate)) 62 | waitGroup.Add(len(servicesToCreate)) 63 | for i := range servicesToCreate { 64 | serviceToCreate := servicesToCreate[i] 65 | go func(service *corev1.Service) { 66 | defer waitGroup.Done() 67 | if err := controllerutil.SetControllerReference(instance, service, r.scheme); err != nil { 68 | createErrCh <- err 69 | return 70 | } 71 | 72 | found := &corev1.Service{} 73 | err := r.client.Get(context.Background(), types.NamespacedName{Name: service.Name, Namespace: service.Namespace}, found) 74 | if err != nil && errors.IsNotFound(err) { 75 | err = r.client.Create(context.Background(), service) 76 | if err != nil { 77 | createErrCh <- err 78 | } 79 | return 80 | 81 | } else if err != nil { 82 | createErrCh <- err 83 | return 84 | } 85 | 86 | found.Spec.Ports = service.Spec.Ports 87 | found.Spec.Selector = service.Spec.Selector 88 | 89 | err = r.client.Update(context.Background(), found) 90 | if err != nil { 91 | createErrCh <- err 92 | return 93 | } 94 | }(&serviceToCreate) 95 | } 96 | waitGroup.Wait() 97 | 98 | select { 99 | case err := <-createErrCh: 100 | // all errors have been reported before and they're likely to be the same, so we'll only return the first one we hit. 101 | if err != nil { 102 | return err 103 | } 104 | default: 105 | } 106 | 107 | return r.syncProxierStatus(instance) 108 | } 109 | 110 | func groupServers(instance *maegusv1.Proxier, services []corev1.Service) ([]corev1.Service, []corev1.Service, []corev1.Service) { 111 | servicesToCreate := []corev1.Service{} 112 | 113 | proxierPorts := []corev1.ServicePort{} 114 | for _, port := range instance.Spec.Ports { 115 | proxierPorts = append(proxierPorts, corev1.ServicePort{ 116 | Name: port.Name, 117 | Protocol: corev1.Protocol(port.Protocol), 118 | Port: port.Port, 119 | TargetPort: port.TargetPort, 120 | }) 121 | } 122 | 123 | for _, backend := range instance.Spec.Backends { 124 | backendSelector := map[string]string{} 125 | for key, value := range instance.Spec.Selector { 126 | backendSelector[key] = value 127 | } 128 | for key, value := range backend.Selector { 129 | backendSelector[key] = value 130 | } 131 | 132 | serviceToCreate := corev1.Service{ 133 | ObjectMeta: metav1.ObjectMeta{ 134 | Name: fmt.Sprintf("%s-%s-backend", instance.Name, backend.Name), 135 | Namespace: instance.Namespace, 136 | Labels: NewServiceLabels(instance), 137 | }, 138 | Spec: corev1.ServiceSpec{ 139 | Selector: backendSelector, 140 | Type: corev1.ServiceTypeClusterIP, 141 | Ports: proxierPorts, 142 | }, 143 | } 144 | 145 | servicesToCreate = append(servicesToCreate, serviceToCreate) 146 | } 147 | 148 | activeServices := []corev1.Service{} 149 | servicesToDelete := []corev1.Service{} 150 | 151 | for i := range services { 152 | service := services[i] 153 | found := false 154 | 155 | for j := range servicesToCreate { 156 | serviceToCreate := servicesToCreate[j] 157 | if serviceToCreate.Name == service.Name && 158 | serviceToCreate.Namespace == service.Namespace { 159 | activeServices = append(activeServices, service) 160 | found = true 161 | break 162 | } 163 | } 164 | 165 | if !found { 166 | servicesToDelete = append(servicesToDelete, service) 167 | } 168 | } 169 | 170 | return servicesToCreate, servicesToDelete, activeServices 171 | } 172 | -------------------------------------------------------------------------------- /pkg/controller/proxier/servers_test.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "testing" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | 8 | "github.com/draveness/proxier/test/framework" 9 | "github.com/stretchr/testify/assert" 10 | corev1 "k8s.io/api/core/v1" 11 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 | ) 13 | 14 | func TestGroupServers(t *testing.T) { 15 | instance := framework.MakeBasicProxier("default", "group-server", []string{"v2", "v3"}, []int32{10, 20}) 16 | 17 | existingServices := []corev1.Service{ 18 | { 19 | ObjectMeta: metav1.ObjectMeta{ 20 | Name: "group-server-v1-backend", 21 | Namespace: "default", 22 | Labels: NewServiceLabels(instance), 23 | }, 24 | Spec: corev1.ServiceSpec{ 25 | Selector: map[string]string{ 26 | "version": "v1", 27 | "app": "group-server", 28 | }, 29 | Type: corev1.ServiceTypeClusterIP, 30 | Ports: []corev1.ServicePort{ 31 | { 32 | Name: "http", 33 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 34 | Port: 80, 35 | }, 36 | }, 37 | }, 38 | }, 39 | { 40 | ObjectMeta: metav1.ObjectMeta{ 41 | Name: "group-server-v2-backend", 42 | Namespace: "default", 43 | Labels: NewServiceLabels(instance), 44 | }, 45 | Spec: corev1.ServiceSpec{ 46 | Selector: map[string]string{ 47 | "version": "v2", 48 | "app": "group-server", 49 | }, 50 | Type: corev1.ServiceTypeClusterIP, 51 | Ports: []corev1.ServicePort{ 52 | { 53 | Name: "http", 54 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 55 | Port: 80, 56 | }, 57 | }, 58 | }, 59 | }, 60 | } 61 | 62 | servicesToCreate, servicesToDelete, activeServices := groupServers(instance, existingServices) 63 | 64 | assert.Equal(t, []corev1.Service{ 65 | { 66 | ObjectMeta: metav1.ObjectMeta{ 67 | Name: "group-server-v1-backend", 68 | Namespace: "default", 69 | Labels: NewServiceLabels(instance), 70 | }, 71 | Spec: corev1.ServiceSpec{ 72 | Selector: map[string]string{ 73 | "version": "v1", 74 | "app": "group-server", 75 | }, 76 | Type: corev1.ServiceTypeClusterIP, 77 | Ports: []corev1.ServicePort{ 78 | { 79 | Name: "http", 80 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 81 | Port: 80, 82 | }, 83 | }, 84 | }, 85 | }, 86 | }, servicesToDelete) 87 | assert.Equal(t, []corev1.Service{ 88 | { 89 | ObjectMeta: metav1.ObjectMeta{ 90 | Name: "group-server-v2-backend", 91 | Namespace: "default", 92 | Labels: NewServiceLabels(instance), 93 | }, 94 | Spec: corev1.ServiceSpec{ 95 | Selector: map[string]string{ 96 | "version": "v2", 97 | "app": "group-server", 98 | }, 99 | Type: corev1.ServiceTypeClusterIP, 100 | Ports: []corev1.ServicePort{ 101 | { 102 | Name: "http", 103 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 104 | Port: 80, 105 | }, 106 | }, 107 | }, 108 | }, 109 | { 110 | ObjectMeta: metav1.ObjectMeta{ 111 | Name: "group-server-v3-backend", 112 | Namespace: "default", 113 | Labels: NewServiceLabels(instance), 114 | }, 115 | Spec: corev1.ServiceSpec{ 116 | Selector: map[string]string{ 117 | "version": "v3", 118 | "app": "group-server", 119 | }, 120 | Type: corev1.ServiceTypeClusterIP, 121 | Ports: []corev1.ServicePort{ 122 | { 123 | Name: "http", 124 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 125 | Port: 80, 126 | }, 127 | }, 128 | }, 129 | }, 130 | }, servicesToCreate) 131 | assert.Equal(t, []corev1.Service{ 132 | { 133 | ObjectMeta: metav1.ObjectMeta{ 134 | Name: "group-server-v2-backend", 135 | Namespace: "default", 136 | Labels: NewServiceLabels(instance), 137 | }, 138 | Spec: corev1.ServiceSpec{ 139 | Selector: map[string]string{ 140 | "version": "v2", 141 | "app": "group-server", 142 | }, 143 | Type: corev1.ServiceTypeClusterIP, 144 | Ports: []corev1.ServicePort{ 145 | { 146 | Name: "http", 147 | Protocol: corev1.Protocol(maegusv1.ProtocolTCP), 148 | Port: 80, 149 | }, 150 | }, 151 | }, 152 | }, 153 | }, activeServices) 154 | } 155 | -------------------------------------------------------------------------------- /pkg/controller/proxier/utils.go: -------------------------------------------------------------------------------- 1 | package proxier 2 | 3 | import ( 4 | "fmt" 5 | "hash/fnv" 6 | 7 | corev1 "k8s.io/api/core/v1" 8 | "k8s.io/apimachinery/pkg/util/rand" 9 | hashutil "k8s.io/kubernetes/pkg/util/hash" 10 | ) 11 | 12 | func computeHash(cm *corev1.ConfigMap) string { 13 | configMapHasher := fnv.New32a() 14 | hashutil.DeepHashObject(configMapHasher, cm) 15 | 16 | return rand.SafeEncodeString(fmt.Sprint(configMapHasher.Sum32())) 17 | } 18 | -------------------------------------------------------------------------------- /test/e2e/const.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import "time" 4 | 5 | const ( 6 | retryInterval = time.Second * 5 7 | timeout = time.Second * 20 8 | cleanupRetryInterval = time.Second * 1 9 | cleanupTimeout = time.Second * 5 10 | ) 11 | -------------------------------------------------------------------------------- /test/e2e/main_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | "os" 7 | "testing" 8 | 9 | "github.com/draveness/proxier/test/framework" 10 | "github.com/stretchr/testify/suite" 11 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 | 13 | "k8s.io/apimachinery/pkg/fields" 14 | ) 15 | 16 | var ( 17 | f *framework.Framework 18 | operatorImage *string 19 | ) 20 | 21 | func TestMain(m *testing.M) { 22 | kubeconfig := flag.String( 23 | "kubeconfig", 24 | "", 25 | "kube config path, e.g. $HOME/.kube/config", 26 | ) 27 | operatorImage = flag.String( 28 | "operator-image", 29 | "", 30 | "operator image, e.g. draveness/proxier:v1.0.0", 31 | ) 32 | flag.Parse() 33 | 34 | var ( 35 | err error 36 | exitCode int 37 | ) 38 | 39 | if f, err = framework.New(*kubeconfig, *operatorImage); err != nil { 40 | log.Printf("failed to setup framework: %v\n", err) 41 | os.Exit(1) 42 | } 43 | 44 | exitCode = m.Run() 45 | 46 | os.Exit(exitCode) 47 | } 48 | 49 | func TestAllNS(t *testing.T) { 50 | ctx := f.NewTestCtx(t) 51 | defer ctx.Cleanup(t) 52 | 53 | ns := ctx.CreateNamespace(t, f.KubeClient) 54 | 55 | err := f.CreateProxierOperator(ns, *operatorImage, nil) 56 | if err != nil { 57 | t.Fatal(err) 58 | } 59 | 60 | // t.Run blocks until the function passed as the second argument (f) returns or 61 | // calls t.Parallel to become a parallel test. Run reports whether f succeeded 62 | // (or at least did not fail before calling t.Parallel). As all tests in 63 | // testAllNS are parallel, the defered ctx.Cleanup above would be run before 64 | // all tests finished. Wrapping it in testAllNS fixes this. 65 | t.Run("x", testAllNS) 66 | 67 | // Check if Proxier Operator ever restarted. 68 | opts := metav1.ListOptions{LabelSelector: fields.SelectorFromSet(fields.Set(map[string]string{ 69 | "name": "proxier-operator", 70 | })).String()} 71 | 72 | pl, err := f.KubeClient.CoreV1().Pods(ns).List(opts) 73 | if err != nil { 74 | t.Fatal(err) 75 | } 76 | if expected := 1; len(pl.Items) != expected { 77 | t.Fatalf("expected %v Proxier Operator pods, but got %v", expected, len(pl.Items)) 78 | } 79 | restarts, err := f.GetPodRestartCount(ns, pl.Items[0].GetName()) 80 | if err != nil { 81 | t.Fatalf("failed to retrieve restart count of Proxier Operator pod: %v", err) 82 | } 83 | if len(restarts) != 1 { 84 | t.Fatalf("expected to have 1 container but got %d", len(restarts)) 85 | } 86 | for _, restart := range restarts { 87 | if restart != 0 { 88 | t.Fatalf( 89 | "expected Proxier Operator to never restart during entire test execution but got %d restarts", 90 | restart, 91 | ) 92 | } 93 | } 94 | } 95 | 96 | func testAllNS(t *testing.T) { 97 | suite.Run(t, new(ProxierCreateSuite)) 98 | } 99 | -------------------------------------------------------------------------------- /test/e2e/proxier_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "fmt" 5 | 6 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 7 | "github.com/draveness/proxier/pkg/controller/proxier" 8 | "github.com/draveness/proxier/test/framework" 9 | "github.com/stretchr/testify/suite" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | ) 12 | 13 | type ProxierCreateSuite struct { 14 | suite.Suite 15 | } 16 | 17 | func (suite *ProxierCreateSuite) TestProxierCreateBackends() { 18 | ctx := f.NewTestCtx(suite.T()) 19 | defer ctx.Cleanup(suite.T()) 20 | 21 | namespace := ctx.CreateNamespace(suite.T(), f.KubeClient) 22 | ctx.SetupProxierRBAC(suite.T(), namespace, f.KubeClient) 23 | 24 | suite.T().Parallel() 25 | 26 | instance := framework.MakeBasicProxier(namespace, "test", []string{"v1", "v2"}, []int32{100, 10}) 27 | 28 | if _, err := f.CreateProxierAndWaitUntilReady(namespace, instance); err != nil { 29 | suite.Nil(err, "create proxier error") 30 | } 31 | 32 | svcList, err := f.KubeClient.CoreV1().Services(namespace).List(metav1.ListOptions{ 33 | LabelSelector: maegusv1.ProxierKeyLabel + "=" + instance.Name, 34 | }) 35 | 36 | suite.Nil(err, "list service error") 37 | suite.Equal(2, len(svcList.Items), "proxier should create backend services") 38 | } 39 | 40 | func (suite *ProxierCreateSuite) TestProxierCreateNginxDeployment() { 41 | ctx := f.NewTestCtx(suite.T()) 42 | defer ctx.Cleanup(suite.T()) 43 | 44 | namespace := ctx.CreateNamespace(suite.T(), f.KubeClient) 45 | ctx.SetupProxierRBAC(suite.T(), namespace, f.KubeClient) 46 | 47 | suite.T().Parallel() 48 | 49 | instance := framework.MakeBasicProxier(namespace, "test", []string{"v1", "v2"}, []int32{100, 10}) 50 | 51 | if _, err := f.CreateProxierAndWaitUntilReady(namespace, instance); err != nil { 52 | suite.Nil(err, "create proxier error") 53 | } 54 | 55 | deploymentName := proxier.NewDeploymentName(instance) 56 | deployment, err := f.KubeClient.AppsV1().Deployments(namespace).Get(deploymentName, metav1.GetOptions{}) 57 | 58 | suite.Nil(err, "get deployment error") 59 | suite.Equal("nginx", deployment.Spec.Template.Spec.Containers[0].Name, "invalid nginx name") 60 | suite.Equal("nginx:1.15.9", deployment.Spec.Template.Spec.Containers[0].Image, "invalid nginx image") 61 | } 62 | 63 | func (suite *ProxierCreateSuite) TestProxierCreateService() { 64 | ctx := f.NewTestCtx(suite.T()) 65 | defer ctx.Cleanup(suite.T()) 66 | 67 | namespace := ctx.CreateNamespace(suite.T(), f.KubeClient) 68 | ctx.SetupProxierRBAC(suite.T(), namespace, f.KubeClient) 69 | 70 | suite.T().Parallel() 71 | 72 | instance := framework.MakeBasicProxier(namespace, "echo", []string{"v1", "v2"}, []int32{100, 10}) 73 | 74 | if _, err := f.CreateProxierAndWaitUntilReady(namespace, instance); err != nil { 75 | suite.Nil(err, "create proxier error") 76 | } 77 | 78 | proxierService, err := f.KubeClient.CoreV1().Services(namespace).Get(instance.Name, metav1.GetOptions{}) 79 | suite.Nil(err, "get service error") 80 | suite.Equal(instance.Name, proxierService.Name, "proxier and service shoud have the same name") 81 | } 82 | 83 | func (suite *ProxierCreateSuite) TestUpdateProxierRemoveService() { 84 | ctx := f.NewTestCtx(suite.T()) 85 | defer ctx.Cleanup(suite.T()) 86 | 87 | namespace := ctx.CreateNamespace(suite.T(), f.KubeClient) 88 | ctx.SetupProxierRBAC(suite.T(), namespace, f.KubeClient) 89 | 90 | suite.T().Parallel() 91 | 92 | instance := framework.MakeBasicProxier(namespace, "echo", []string{"v1", "v2"}, []int32{100, 10}) 93 | 94 | if _, err := f.CreateProxierAndWaitUntilReady(namespace, instance); err != nil { 95 | suite.Nil(err, "create proxier error") 96 | } 97 | 98 | proxier, err := f.MaegusClientV1.Proxiers(instance.Namespace).Get(instance.Name, metav1.GetOptions{}) 99 | suite.Nil(err) 100 | 101 | proxier.Spec = framework.MakeBasicProxier(namespace, "echo", []string{"v3"}, []int32{10}).Spec 102 | if _, err := f.UpdateProxierAndWaitUntilReady(namespace, proxier); err != nil { 103 | suite.Nil(err, "update proxier error") 104 | } 105 | 106 | for _, backend := range []string{"v1", "v2"} { 107 | if err := f.WaitUntilServiceGone(namespace, fmt.Sprintf("%s-%s-backend", instance.Name, backend), timeout); err != nil { 108 | suite.Nil(err, fmt.Sprintf("create service %s error", backend)) 109 | } 110 | } 111 | 112 | svcList, err := f.KubeClient.CoreV1().Services(namespace).List(metav1.ListOptions{ 113 | LabelSelector: maegusv1.ProxierKeyLabel + "=" + instance.Name, 114 | }) 115 | 116 | suite.Nil(err, "list service error") 117 | suite.Equal(1, len(svcList.Items), "proxier should remove useless backend services") 118 | } 119 | -------------------------------------------------------------------------------- /test/fixtures/echo-v1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: echo-v1 5 | labels: 6 | app: echo 7 | version: v1 8 | name: echo-v1 9 | spec: 10 | containers: 11 | - name: echo 12 | image: hashicorp/http-echo 13 | command: ["/http-echo"] 14 | args: ["-text", "hello world v1"] 15 | ports: 16 | - containerPort: 5678 17 | -------------------------------------------------------------------------------- /test/fixtures/echo-v2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: echo-v2 5 | labels: 6 | app: echo 7 | version: v2 8 | name: echo-v2 9 | spec: 10 | containers: 11 | - name: echo 12 | image: hashicorp/http-echo 13 | command: ["/http-echo"] 14 | args: ["-text", "hello world v2"] 15 | ports: 16 | - containerPort: 5678 17 | -------------------------------------------------------------------------------- /test/framework/cluster_role.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | rbacv1 "k8s.io/api/rbac/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/apimachinery/pkg/util/yaml" 7 | "k8s.io/client-go/kubernetes" 8 | ) 9 | 10 | func CreateClusterRole(kubeClient kubernetes.Interface, relativePath string) error { 11 | clusterRole, err := parseClusterRoleYaml(relativePath) 12 | if err != nil { 13 | return err 14 | } 15 | 16 | _, err = kubeClient.RbacV1().ClusterRoles().Get(clusterRole.Name, metav1.GetOptions{}) 17 | 18 | if err == nil { 19 | // ClusterRole already exists -> Update 20 | _, err = kubeClient.RbacV1().ClusterRoles().Update(clusterRole) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | } else { 26 | // ClusterRole doesn't exists -> Create 27 | _, err = kubeClient.RbacV1().ClusterRoles().Create(clusterRole) 28 | if err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | 36 | func DeleteClusterRole(kubeClient kubernetes.Interface, relativePath string) error { 37 | clusterRole, err := parseClusterRoleYaml(relativePath) 38 | if err != nil { 39 | return err 40 | } 41 | 42 | return kubeClient.RbacV1().ClusterRoles().Delete(clusterRole.Name, &metav1.DeleteOptions{}) 43 | } 44 | 45 | func parseClusterRoleYaml(relativePath string) (*rbacv1.ClusterRole, error) { 46 | manifest, err := PathToOSFile(relativePath) 47 | if err != nil { 48 | return nil, err 49 | } 50 | 51 | clusterRole := rbacv1.ClusterRole{} 52 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&clusterRole); err != nil { 53 | return nil, err 54 | } 55 | 56 | return &clusterRole, nil 57 | } 58 | -------------------------------------------------------------------------------- /test/framework/cluster_role_binding.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | rbacv1 "k8s.io/api/rbac/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/apimachinery/pkg/util/yaml" 7 | "k8s.io/client-go/kubernetes" 8 | ) 9 | 10 | func CreateClusterRoleBinding(kubeClient kubernetes.Interface, ns string, relativePath string) (finalizerFn, error) { 11 | finalizerFn := func() error { return DeleteClusterRoleBinding(kubeClient, relativePath) } 12 | clusterRoleBinding, err := parseClusterRoleBindingYaml(relativePath) 13 | if err != nil { 14 | return finalizerFn, err 15 | } 16 | 17 | clusterRoleBinding.Subjects[0].Namespace = ns 18 | 19 | _, err = kubeClient.RbacV1().ClusterRoleBindings().Get(clusterRoleBinding.Name, metav1.GetOptions{}) 20 | 21 | if err == nil { 22 | // ClusterRoleBinding already exists -> Update 23 | _, err = kubeClient.RbacV1().ClusterRoleBindings().Update(clusterRoleBinding) 24 | if err != nil { 25 | return finalizerFn, err 26 | } 27 | } else { 28 | // ClusterRoleBinding doesn't exists -> Create 29 | _, err = kubeClient.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding) 30 | if err != nil { 31 | return finalizerFn, err 32 | } 33 | } 34 | 35 | return finalizerFn, err 36 | } 37 | 38 | func DeleteClusterRoleBinding(kubeClient kubernetes.Interface, relativePath string) error { 39 | clusterRoleBinding, err := parseClusterRoleYaml(relativePath) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | return kubeClient.RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, &metav1.DeleteOptions{}) 45 | } 46 | 47 | func parseClusterRoleBindingYaml(relativePath string) (*rbacv1.ClusterRoleBinding, error) { 48 | manifest, err := PathToOSFile(relativePath) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | clusterRoleBinding := rbacv1.ClusterRoleBinding{} 54 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&clusterRoleBinding); err != nil { 55 | return nil, err 56 | } 57 | 58 | return &clusterRoleBinding, nil 59 | } 60 | -------------------------------------------------------------------------------- /test/framework/context.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | "testing" 7 | "time" 8 | 9 | "golang.org/x/sync/errgroup" 10 | ) 11 | 12 | type TestCtx struct { 13 | ID string 14 | cleanUpFns []finalizerFn 15 | } 16 | 17 | type finalizerFn func() error 18 | 19 | func (f *Framework) NewTestCtx(t *testing.T) TestCtx { 20 | // TestCtx is used among others for namespace names where '/' is forbidden 21 | prefix := strings.TrimPrefix( 22 | strings.Replace( 23 | strings.ToLower(t.Name()), 24 | "/", 25 | "-", 26 | -1, 27 | ), 28 | "test", 29 | ) 30 | 31 | id := prefix + "-" + strconv.FormatInt(time.Now().Unix(), 36) 32 | return TestCtx{ 33 | ID: id, 34 | } 35 | } 36 | 37 | // GetObjID returns an ascending ID based on the length of cleanUpFns. It is 38 | // based on the premise that every new object also appends a new finalizerFn on 39 | // cleanUpFns. This can e.g. be used to create multiple namespaces in the same 40 | // test context. 41 | func (ctx *TestCtx) GetObjID() string { 42 | return ctx.ID + "-" + strconv.Itoa(len(ctx.cleanUpFns)) 43 | } 44 | 45 | func (ctx *TestCtx) Cleanup(t *testing.T) { 46 | var eg errgroup.Group 47 | 48 | for i := len(ctx.cleanUpFns) - 1; i >= 0; i-- { 49 | eg.Go(ctx.cleanUpFns[i]) 50 | } 51 | 52 | if err := eg.Wait(); err != nil { 53 | t.Fatal(err) 54 | } 55 | } 56 | 57 | func (ctx *TestCtx) AddFinalizerFn(fn finalizerFn) { 58 | ctx.cleanUpFns = append(ctx.cleanUpFns, fn) 59 | } 60 | -------------------------------------------------------------------------------- /test/framework/crd.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/pkg/errors" 9 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" 10 | "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 11 | apierrors "k8s.io/apimachinery/pkg/api/errors" 12 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 | "k8s.io/apimachinery/pkg/runtime" 14 | "k8s.io/apimachinery/pkg/util/wait" 15 | "k8s.io/apimachinery/pkg/util/yaml" 16 | ) 17 | 18 | func MakeCRD(pathToYaml string) (*apiextensionsv1.CustomResourceDefinition, error) { 19 | manifest, err := PathToOSFile(pathToYaml) 20 | if err != nil { 21 | return nil, err 22 | } 23 | crd := apiextensionsv1.CustomResourceDefinition{} 24 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&crd); err != nil { 25 | return nil, errors.Wrap(err, fmt.Sprintf("failed to decode file %s", pathToYaml)) 26 | } 27 | 28 | return &crd, nil 29 | } 30 | 31 | func CreateCRD(kubeClient clientset.Interface, namespace string, crd *apiextensionsv1.CustomResourceDefinition) error { 32 | crd.Namespace = namespace 33 | crd, err := kubeClient.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd) 34 | if err != nil { 35 | return err 36 | } 37 | return nil 38 | } 39 | 40 | // WaitForCRDReady waits for a custom resource definition to be available for use. 41 | func WaitForCRDReady(listFunc func(opts metav1.ListOptions) (runtime.Object, error)) error { 42 | err := wait.Poll(3*time.Second, 10*time.Minute, func() (bool, error) { 43 | _, err := listFunc(metav1.ListOptions{}) 44 | if err != nil { 45 | if se, ok := err.(*apierrors.StatusError); ok { 46 | if se.Status().Code == http.StatusNotFound { 47 | return false, nil 48 | } 49 | } 50 | return false, errors.Wrap(err, "failed to list CRD") 51 | } 52 | return true, nil 53 | }) 54 | 55 | return errors.Wrap(err, fmt.Sprintf("timed out waiting for Custom Resource")) 56 | } 57 | -------------------------------------------------------------------------------- /test/framework/deployment.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/pkg/errors" 8 | appsv1 "k8s.io/api/apps/v1beta2" 9 | apierrors "k8s.io/apimachinery/pkg/api/errors" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | "k8s.io/apimachinery/pkg/util/wait" 12 | "k8s.io/apimachinery/pkg/util/yaml" 13 | "k8s.io/client-go/kubernetes" 14 | ) 15 | 16 | func MakeDeployment(pathToYaml string) (*appsv1.Deployment, error) { 17 | manifest, err := PathToOSFile(pathToYaml) 18 | if err != nil { 19 | return nil, err 20 | } 21 | tectonicPromOp := appsv1.Deployment{} 22 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&tectonicPromOp); err != nil { 23 | return nil, errors.Wrap(err, fmt.Sprintf("failed to decode file %s", pathToYaml)) 24 | } 25 | 26 | return &tectonicPromOp, nil 27 | } 28 | 29 | func CreateDeployment(kubeClient kubernetes.Interface, namespace string, d *appsv1.Deployment) error { 30 | d.Namespace = namespace 31 | _, err := kubeClient.AppsV1beta2().Deployments(namespace).Create(d) 32 | if err != nil { 33 | return errors.Wrap(err, fmt.Sprintf("failed to create deployment %s", d.Name)) 34 | } 35 | return nil 36 | } 37 | 38 | func DeleteDeployment(kubeClient kubernetes.Interface, namespace, name string) error { 39 | d, err := kubeClient.AppsV1beta2().Deployments(namespace).Get(name, metav1.GetOptions{}) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | zero := int32(0) 45 | d.Spec.Replicas = &zero 46 | 47 | d, err = kubeClient.AppsV1beta2().Deployments(namespace).Update(d) 48 | if err != nil { 49 | return err 50 | } 51 | return kubeClient.AppsV1beta2().Deployments(namespace).Delete(d.Name, &metav1.DeleteOptions{}) 52 | } 53 | 54 | func WaitUntilDeploymentGone(kubeClient kubernetes.Interface, namespace, name string, timeout time.Duration) error { 55 | return wait.Poll(time.Second, timeout, func() (bool, error) { 56 | _, err := kubeClient. 57 | AppsV1beta2().Deployments(namespace). 58 | Get(name, metav1.GetOptions{}) 59 | 60 | if err != nil { 61 | if apierrors.IsNotFound(err) { 62 | return true, nil 63 | } 64 | 65 | return false, err 66 | } 67 | 68 | return false, nil 69 | }) 70 | } 71 | 72 | // WaitForDeployment returns when deployment is created. 73 | func (f *Framework) WaitForDeployment(namespace, name string, timeout time.Duration) error { 74 | return wait.Poll(time.Second, timeout, func() (bool, error) { 75 | _, err := f.KubeClient.AppsV1beta2().Deployments(namespace).Get(name, metav1.GetOptions{}) 76 | 77 | if err != nil { 78 | if apierrors.IsNotFound(err) { 79 | return false, nil 80 | } 81 | 82 | return false, err 83 | } 84 | 85 | return true, nil 86 | }) 87 | } 88 | -------------------------------------------------------------------------------- /test/framework/framework.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | "testing" 7 | "time" 8 | 9 | maegusclient "github.com/draveness/proxier/pkg/client/versioned/typed/maegus/v1beta1" 10 | "github.com/pkg/errors" 11 | v1 "k8s.io/api/core/v1" 12 | "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 13 | apierrors "k8s.io/apimachinery/pkg/api/errors" 14 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 | "k8s.io/apimachinery/pkg/fields" 16 | "k8s.io/apimachinery/pkg/runtime" 17 | "k8s.io/client-go/kubernetes" 18 | 19 | "k8s.io/client-go/rest" 20 | "k8s.io/client-go/tools/clientcmd" 21 | ) 22 | 23 | type Framework struct { 24 | KubeClient kubernetes.Interface 25 | MaegusClientV1 maegusclient.MaegusV1beta1Interface 26 | ApiextensionsClientV1 clientset.Interface 27 | HTTPClient *http.Client 28 | MasterHost string 29 | DefaultTimeout time.Duration 30 | } 31 | 32 | // New setups a test framework and returns it. 33 | func New(kubeconfig, opImage string) (*Framework, error) { 34 | config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) 35 | if err != nil { 36 | return nil, errors.Wrap(err, "build config from flags failed") 37 | } 38 | 39 | cli, err := kubernetes.NewForConfig(config) 40 | if err != nil { 41 | return nil, errors.Wrap(err, "creating new kube-client failed") 42 | } 43 | 44 | httpc := cli.CoreV1().RESTClient().(*rest.RESTClient).Client 45 | if err != nil { 46 | return nil, errors.Wrap(err, "creating http-client failed") 47 | } 48 | 49 | maegusClientV1, err := maegusclient.NewForConfig(config) 50 | if err != nil { 51 | return nil, errors.Wrap(err, "creating v1 maegus client failed") 52 | } 53 | 54 | apiextensionsClientV1, err := clientset.NewForConfig(config) 55 | if err != nil { 56 | return nil, errors.Wrap(err, "creating v1 apiextensions client failed") 57 | } 58 | 59 | f := &Framework{ 60 | MasterHost: config.Host, 61 | MaegusClientV1: maegusClientV1, 62 | ApiextensionsClientV1: apiextensionsClientV1, 63 | KubeClient: cli, 64 | HTTPClient: httpc, 65 | DefaultTimeout: time.Minute, 66 | } 67 | 68 | return f, nil 69 | } 70 | 71 | // CreateProxierOperator create service account, cluster role, cluster role binding and make 72 | // deployment for proxier resources. 73 | func (f *Framework) CreateProxierOperator(namespace string, operatorImage string, namespacesToWatch []string) error { 74 | crd, err := MakeCRD("../../deploy/crds/maegus_v1beta1_proxier_crd.yaml") 75 | if err != nil { 76 | return err 77 | } 78 | 79 | if err := CreateCRD(f.ApiextensionsClientV1, namespace, crd); err != nil && !apierrors.IsAlreadyExists(err) { 80 | return errors.Wrap(err, "failed to create proxier crd") 81 | } 82 | 83 | _, err = CreateServiceAccount(f.KubeClient, namespace, "../../deploy/service_account.yaml") 84 | if err != nil && !apierrors.IsAlreadyExists(err) { 85 | return errors.Wrap(err, "failed to create proxier operator service account") 86 | } 87 | 88 | if err := CreateClusterRole(f.KubeClient, "../../deploy/cluster_role.yaml"); err != nil && !apierrors.IsAlreadyExists(err) { 89 | return errors.Wrap(err, "failed to create proxier cluster role") 90 | } 91 | 92 | if _, err := CreateClusterRoleBinding(f.KubeClient, namespace, "../../deploy/cluster_role_binding.yaml"); err != nil && !apierrors.IsAlreadyExists(err) { 93 | return errors.Wrap(err, "failed to create prometheus cluster role binding") 94 | } 95 | 96 | deployment, err := MakeDeployment("../../deploy/operator.yaml") 97 | if err != nil { 98 | return err 99 | } 100 | 101 | if operatorImage != "" { 102 | // Override operator image used, if specified when running tests. 103 | deployment.Spec.Template.Spec.Containers[0].Image = operatorImage 104 | repoAndTag := strings.Split(operatorImage, ":") 105 | if len(repoAndTag) != 2 { 106 | return errors.Errorf( 107 | "expected operator image '%v' split by colon to result in two substrings but got '%v'", 108 | operatorImage, 109 | repoAndTag, 110 | ) 111 | } 112 | } 113 | 114 | err = CreateDeployment(f.KubeClient, namespace, deployment) 115 | if err != nil { 116 | return err 117 | } 118 | 119 | opts := metav1.ListOptions{LabelSelector: fields.SelectorFromSet(fields.Set(deployment.Spec.Template.ObjectMeta.Labels)).String()} 120 | err = WaitForPodsReady(f.KubeClient, namespace, f.DefaultTimeout, 1, opts) 121 | if err != nil { 122 | return errors.Wrap(err, "failed to wait for prometheus operator to become ready") 123 | } 124 | 125 | err = WaitForCRDReady(func(opts metav1.ListOptions) (runtime.Object, error) { 126 | return f.MaegusClientV1.Proxiers(v1.NamespaceAll).List(opts) 127 | }) 128 | if err != nil { 129 | return errors.Wrap(err, "Proxier CRD not ready: %v\n") 130 | } 131 | 132 | return nil 133 | } 134 | 135 | func (ctx *TestCtx) SetupProxierRBAC(t *testing.T, ns string, kubeClient kubernetes.Interface) { 136 | if err := CreateClusterRole(kubeClient, "../../deploy/cluster_role.yaml"); err != nil && !apierrors.IsAlreadyExists(err) { 137 | t.Fatalf("failed to create proxier cluster role: %v", err) 138 | } 139 | if finalizerFn, err := CreateServiceAccount(kubeClient, ns, "../../deploy/service_account.yaml"); err != nil { 140 | t.Fatal(errors.Wrap(err, "failed to create proxier service account")) 141 | } else { 142 | ctx.AddFinalizerFn(finalizerFn) 143 | } 144 | 145 | if finalizerFn, err := CreateRoleBinding(kubeClient, ns, "../../deploy/cluster_role_binding.yaml"); err != nil { 146 | t.Fatal(errors.Wrap(err, "failed to create proxier role binding")) 147 | } else { 148 | ctx.AddFinalizerFn(finalizerFn) 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /test/framework/helpers.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "time" 8 | 9 | "github.com/pkg/errors" 10 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 | "k8s.io/apimachinery/pkg/util/wait" 12 | "k8s.io/client-go/kubernetes" 13 | ) 14 | 15 | // PathToOSFile opens a file and return the os.File pointer. 16 | func PathToOSFile(relativPath string) (*os.File, error) { 17 | path, err := filepath.Abs(relativPath) 18 | if err != nil { 19 | return nil, errors.Wrap(err, fmt.Sprintf("failed generate absolut file path of %s", relativPath)) 20 | } 21 | 22 | manifest, err := os.Open(path) 23 | if err != nil { 24 | return nil, errors.Wrap(err, fmt.Sprintf("failed to open file %s", path)) 25 | } 26 | 27 | return manifest, nil 28 | } 29 | 30 | // WaitForPodsReady waits for a selection of Pods to be running and each 31 | // container to pass its readiness check. 32 | func WaitForPodsReady(kubeClient kubernetes.Interface, namespace string, timeout time.Duration, expectedReplicas int, opts metav1.ListOptions) error { 33 | return wait.Poll(time.Second, timeout, func() (bool, error) { 34 | pl, err := kubeClient.CoreV1().Pods(namespace).List(opts) 35 | if err != nil { 36 | return false, err 37 | } 38 | 39 | runningAndReady := 0 40 | for _, p := range pl.Items { 41 | isRunningAndReady, err := PodRunningAndReady(p) 42 | if err != nil { 43 | return false, err 44 | } 45 | 46 | if isRunningAndReady { 47 | runningAndReady++ 48 | } 49 | } 50 | 51 | if runningAndReady == expectedReplicas { 52 | return true, nil 53 | } 54 | return false, nil 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /test/framework/namespace.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pkg/errors" 8 | v1 "k8s.io/api/core/v1" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | "k8s.io/client-go/kubernetes" 11 | ) 12 | 13 | func CreateNamespace(kubeClient kubernetes.Interface, name string) (*v1.Namespace, error) { 14 | namespace, err := kubeClient.CoreV1().Namespaces().Create(&v1.Namespace{ 15 | ObjectMeta: metav1.ObjectMeta{ 16 | Name: name, 17 | }, 18 | }) 19 | if err != nil { 20 | return nil, errors.Wrap(err, fmt.Sprintf("failed to create namespace with name %v", name)) 21 | } 22 | return namespace, nil 23 | } 24 | 25 | func (ctx *TestCtx) CreateNamespace(t *testing.T, kubeClient kubernetes.Interface) string { 26 | name := ctx.GetObjID() 27 | if _, err := CreateNamespace(kubeClient, name); err != nil { 28 | t.Fatal(err) 29 | } 30 | 31 | namespaceFinalizerFn := func() error { 32 | return DeleteNamespace(kubeClient, name) 33 | } 34 | 35 | ctx.AddFinalizerFn(namespaceFinalizerFn) 36 | 37 | return name 38 | } 39 | 40 | func DeleteNamespace(kubeClient kubernetes.Interface, name string) error { 41 | return kubeClient.CoreV1().Namespaces().Delete(name, nil) 42 | } 43 | 44 | func AddLabelsToNamespace(kubeClient kubernetes.Interface, name string, additionalLabels map[string]string) error { 45 | ns, err := kubeClient.CoreV1().Namespaces().Get(name, metav1.GetOptions{}) 46 | if err != nil { 47 | return err 48 | } 49 | 50 | if ns.Labels == nil { 51 | ns.Labels = map[string]string{} 52 | } 53 | 54 | for k, v := range additionalLabels { 55 | ns.Labels[k] = v 56 | } 57 | 58 | _, err = kubeClient.CoreV1().Namespaces().Update(ns) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | return nil 64 | } 65 | -------------------------------------------------------------------------------- /test/framework/pod.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/pkg/errors" 8 | v1 "k8s.io/api/core/v1" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | "k8s.io/apimachinery/pkg/util/wait" 11 | "k8s.io/apimachinery/pkg/util/yaml" 12 | ) 13 | 14 | func MakePod(pathToYaml string) (*v1.Pod, error) { 15 | manifest, err := PathToOSFile(pathToYaml) 16 | if err != nil { 17 | return nil, err 18 | } 19 | tectonicPromOp := v1.Pod{} 20 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&tectonicPromOp); err != nil { 21 | return nil, errors.Wrap(err, fmt.Sprintf("failed to decode file %s", pathToYaml)) 22 | } 23 | 24 | return &tectonicPromOp, nil 25 | } 26 | 27 | func (f *Framework) CreatePod(namespace string, pod *v1.Pod) error { 28 | pod.Namespace = namespace 29 | _, err := f.KubeClient.CoreV1().Pods(namespace).Create(pod) 30 | if err != nil { 31 | return errors.Wrap(err, fmt.Sprintf("failed to create pod %s", pod.Name)) 32 | } 33 | return nil 34 | } 35 | 36 | func (f *Framework) CreatePodAndWaitUntilReady(namespace string, pod *v1.Pod) error { 37 | if err := f.CreatePod(namespace, pod); err != nil { 38 | return err 39 | } 40 | 41 | if err := f.WaitForPodReady(pod, 30*time.Second); err != nil { 42 | return errors.Wrap(err, fmt.Sprintf("failed to create pod %s", pod.Name)) 43 | } 44 | 45 | return nil 46 | } 47 | 48 | // GetPodRestartCount returns a map of container names and their restart counts for 49 | // a given pod. 50 | func (f *Framework) GetPodRestartCount(ns, podName string) (map[string]int32, error) { 51 | pod, err := f.KubeClient.CoreV1().Pods(ns).Get(podName, metav1.GetOptions{}) 52 | if err != nil { 53 | return nil, errors.Wrap(err, "failed to retrieve pod to get restart count") 54 | } 55 | 56 | restarts := map[string]int32{} 57 | 58 | for _, status := range pod.Status.ContainerStatuses { 59 | restarts[status.Name] = status.RestartCount 60 | } 61 | 62 | return restarts, nil 63 | } 64 | 65 | // WaitForPodReady returns when pod shifted to running phase or timeout. 66 | func (f *Framework) WaitForPodReady(pod *v1.Pod, timeout time.Duration) error { 67 | var pollErr error 68 | 69 | err := wait.Poll(2*time.Second, timeout, func() (bool, error) { 70 | pod, pollErr := f.KubeClient.CoreV1().Pods(pod.Namespace).Get(pod.Name, metav1.GetOptions{}) 71 | 72 | if pollErr != nil { 73 | return false, nil 74 | } 75 | 76 | if pod.Status.Phase != v1.PodRunning { 77 | return false, nil 78 | } 79 | 80 | return true, nil 81 | }) 82 | return errors.Wrapf(pollErr, "waiting for Proxier %v/%v: %v", pod.Namespace, pod.Name, err) 83 | } 84 | 85 | // PodRunningAndReady returns whether a pod is running and each container has 86 | // passed it's ready state. 87 | func PodRunningAndReady(pod v1.Pod) (bool, error) { 88 | switch pod.Status.Phase { 89 | case v1.PodFailed, v1.PodSucceeded: 90 | return false, fmt.Errorf("pod completed") 91 | case v1.PodRunning: 92 | for _, cond := range pod.Status.Conditions { 93 | if cond.Type != v1.PodReady { 94 | continue 95 | } 96 | return cond.Status == v1.ConditionTrue, nil 97 | } 98 | return false, fmt.Errorf("pod ready condition not found") 99 | } 100 | return false, nil 101 | } 102 | -------------------------------------------------------------------------------- /test/framework/proxier.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | maegusv1 "github.com/draveness/proxier/pkg/apis/maegus/v1beta1" 8 | "github.com/draveness/proxier/pkg/controller/proxier" 9 | 10 | "github.com/pkg/errors" 11 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 | "k8s.io/apimachinery/pkg/util/wait" 13 | ) 14 | 15 | // MakeBasicProxier returns a proxier with given versions and weights. 16 | func MakeBasicProxier(ns, name string, versions []string, weights []int32) *maegusv1.Proxier { 17 | backends := []maegusv1.BackendSpec{} 18 | for i := range versions { 19 | backends = append(backends, maegusv1.BackendSpec{ 20 | Name: versions[i], 21 | Weight: weights[i], 22 | Selector: map[string]string{ 23 | "version": versions[i], 24 | }, 25 | }) 26 | } 27 | 28 | return &maegusv1.Proxier{ 29 | ObjectMeta: metav1.ObjectMeta{ 30 | Name: name, 31 | Namespace: ns, 32 | }, 33 | Spec: maegusv1.ProxierSpec{ 34 | Selector: map[string]string{ 35 | "app": name, 36 | }, 37 | Ports: []maegusv1.ProxierPort{ 38 | { 39 | Name: "http", 40 | Protocol: maegusv1.ProtocolTCP, 41 | Port: 80, 42 | }, 43 | }, 44 | Backends: backends, 45 | }, 46 | } 47 | } 48 | 49 | // CreateProxier creates a proxier. 50 | func (f *Framework) CreateProxier(ns string, p *maegusv1.Proxier) (*maegusv1.Proxier, error) { 51 | result, err := f.MaegusClientV1.Proxiers(ns).Create(p) 52 | if err != nil { 53 | return nil, fmt.Errorf("creating proxier instances failed (%v): %v", p.Name, err) 54 | } 55 | 56 | return result, nil 57 | } 58 | 59 | // CreateProxierAndWaitUntilReady creates a proxier instance and waits until ready. 60 | func (f *Framework) CreateProxierAndWaitUntilReady(ns string, p *maegusv1.Proxier) (*maegusv1.Proxier, error) { 61 | result, err := f.CreateProxier(ns, p) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | if err := f.WaitForProxierReady(result, 15*time.Second); err != nil { 67 | return nil, fmt.Errorf("waiting for Proxier instances timed out (%v): %v", p.Name, err) 68 | } 69 | 70 | return result, nil 71 | } 72 | 73 | // UpdateProxier updates a proxier instance. 74 | func (f *Framework) UpdateProxier(ns string, p *maegusv1.Proxier) (*maegusv1.Proxier, error) { 75 | result, err := f.MaegusClientV1.Proxiers(ns).Update(p) 76 | if err != nil { 77 | return nil, fmt.Errorf("updating proxier instances failed (%v): %v", p.Name, err) 78 | } 79 | 80 | return result, nil 81 | } 82 | 83 | // UpdateProxierAndWaitUntilReady updates a proxier instance and waits until ready. 84 | func (f *Framework) UpdateProxierAndWaitUntilReady(ns string, p *maegusv1.Proxier) (*maegusv1.Proxier, error) { 85 | result, err := f.UpdateProxier(ns, p) 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | if err := f.WaitForProxierReady(result, 15*time.Second); err != nil { 91 | return nil, fmt.Errorf("waiting for Proxier instances timed out (%v): %v", p.Name, err) 92 | } 93 | 94 | return result, nil 95 | } 96 | 97 | // WaitForProxierReady returns when proxier shifted to running phase or timeout. 98 | func (f *Framework) WaitForProxierReady(p *maegusv1.Proxier, timeout time.Duration) error { 99 | var pollErr error 100 | 101 | err := wait.Poll(2*time.Second, timeout, func() (bool, error) { 102 | instance, pollErr := f.MaegusClientV1.Proxiers(p.Namespace).Get(p.Name, metav1.GetOptions{}) 103 | 104 | if pollErr != nil { 105 | return false, nil 106 | } 107 | 108 | deploymentName := proxier.NewDeploymentName(p) 109 | if err := f.WaitForDeployment(p.Namespace, deploymentName, timeout); err != nil { 110 | return false, err 111 | } 112 | 113 | if err := f.WaitForServiceReady(p.Namespace, p.Name, timeout); err != nil { 114 | return false, err 115 | } 116 | 117 | for _, backend := range p.Spec.Backends { 118 | // backendServiceName := fmt.Sprintf("%s-%s-backend", p.Name, backend.Name) 119 | if err := f.WaitForServiceReady(p.Namespace, fmt.Sprintf("%s-%s-backend", p.Name, backend.Name), timeout); err != nil { 120 | return false, err 121 | } 122 | } 123 | 124 | if instance.Status.ActiveBackends != int32(len(p.Spec.Backends)) { 125 | return false, nil 126 | } 127 | 128 | if instance.Status.ObsoleteBackends != 0 { 129 | return false, nil 130 | } 131 | 132 | // TODO: check the proxier expected backends with current backends 133 | 134 | return true, nil 135 | }) 136 | return errors.Wrapf(pollErr, "waiting for Proxier %v/%v: %v", p.Namespace, p.Name, err) 137 | } 138 | -------------------------------------------------------------------------------- /test/framework/role_binding.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | rbacv1 "k8s.io/api/rbac/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/apimachinery/pkg/util/yaml" 7 | "k8s.io/client-go/kubernetes" 8 | ) 9 | 10 | func CreateRoleBinding(kubeClient kubernetes.Interface, ns string, relativePath string) (finalizerFn, error) { 11 | finalizerFn := func() error { return DeleteRoleBinding(kubeClient, ns, relativePath) } 12 | roleBinding, err := parseRoleBindingYaml(relativePath) 13 | if err != nil { 14 | return finalizerFn, err 15 | } 16 | 17 | _, err = kubeClient.RbacV1().RoleBindings(ns).Create(roleBinding) 18 | return finalizerFn, err 19 | } 20 | 21 | func DeleteRoleBinding(kubeClient kubernetes.Interface, ns string, relativePath string) error { 22 | roleBinding, err := parseRoleBindingYaml(relativePath) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | return kubeClient.RbacV1().RoleBindings(ns).Delete(roleBinding.Name, &metav1.DeleteOptions{}) 28 | } 29 | 30 | func parseRoleBindingYaml(relativePath string) (*rbacv1.RoleBinding, error) { 31 | manifest, err := PathToOSFile(relativePath) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | roleBinding := rbacv1.RoleBinding{} 37 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&roleBinding); err != nil { 38 | return nil, err 39 | } 40 | 41 | return &roleBinding, nil 42 | } 43 | -------------------------------------------------------------------------------- /test/framework/service.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | "time" 5 | 6 | apierrors "k8s.io/apimachinery/pkg/api/errors" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | "k8s.io/apimachinery/pkg/util/wait" 9 | ) 10 | 11 | // WaitForServiceReady returns when service is ready. 12 | func (f *Framework) WaitForServiceReady(namespace, name string, timeout time.Duration) error { 13 | return wait.Poll(time.Second, timeout, func() (bool, error) { 14 | _, err := f.KubeClient.CoreV1().Services(namespace).Get(name, metav1.GetOptions{}) 15 | 16 | if err != nil { 17 | if apierrors.IsNotFound(err) { 18 | return false, nil 19 | } 20 | 21 | return false, err 22 | } 23 | 24 | return true, nil 25 | }) 26 | } 27 | 28 | // WaitUntilServiceGone returns when service not found. 29 | func (f *Framework) WaitUntilServiceGone(namespace, name string, timeout time.Duration) error { 30 | return wait.Poll(time.Second, timeout, func() (bool, error) { 31 | _, err := f.KubeClient.CoreV1().Services(namespace).Get(name, metav1.GetOptions{}) 32 | 33 | if err != nil { 34 | if apierrors.IsNotFound(err) { 35 | return true, nil 36 | } 37 | 38 | return false, err 39 | } 40 | 41 | return false, nil 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /test/framework/service_account.go: -------------------------------------------------------------------------------- 1 | package framework 2 | 3 | import ( 4 | v1 "k8s.io/api/core/v1" 5 | "k8s.io/apimachinery/pkg/util/yaml" 6 | "k8s.io/client-go/kubernetes" 7 | ) 8 | 9 | func CreateServiceAccount(kubeClient kubernetes.Interface, namespace string, relativPath string) (finalizerFn, error) { 10 | finalizerFn := func() error { return DeleteServiceAccount(kubeClient, namespace, relativPath) } 11 | 12 | serviceAccount, err := parseServiceAccountYaml(relativPath) 13 | if err != nil { 14 | return finalizerFn, err 15 | } 16 | serviceAccount.Namespace = namespace 17 | _, err = kubeClient.CoreV1().ServiceAccounts(namespace).Create(serviceAccount) 18 | if err != nil { 19 | return finalizerFn, err 20 | } 21 | 22 | return finalizerFn, nil 23 | } 24 | 25 | func parseServiceAccountYaml(relativPath string) (*v1.ServiceAccount, error) { 26 | manifest, err := PathToOSFile(relativPath) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | serviceAccount := v1.ServiceAccount{} 32 | if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&serviceAccount); err != nil { 33 | return nil, err 34 | } 35 | 36 | return &serviceAccount, nil 37 | } 38 | 39 | func DeleteServiceAccount(kubeClient kubernetes.Interface, namespace string, relativPath string) error { 40 | serviceAccount, err := parseServiceAccountYaml(relativPath) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | return kubeClient.CoreV1().ServiceAccounts(namespace).Delete(serviceAccount.Name, nil) 46 | } 47 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | var ( 4 | Version = "0.1.0" 5 | ) 6 | --------------------------------------------------------------------------------