From 6087ba1da7bb061e4d1f3c7b71325555a97bbbdc Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 14:00:02 -0500 Subject: [PATCH 01/15] Make pre-commit linter skip vendor directory Signed-off-by: John Strunk --- scripts/pre-commit.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index 9879383..9d379a2 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -18,7 +18,8 @@ function run_check() { shift if [ -x "$(command -v "$exe")" ]; then - find . -regextype egrep -iregex "$regex" -print0 | \ + find . -name vendor -prune -o \ + -regextype egrep -iregex "$regex" -print0 | \ xargs -0rt -n1 "$exe" "$@" elif [ "$all_required" -eq 0 ]; then echo "Warning: $exe not found... skipping some tests." From 6bcaee9909ae451618f23a9843a4aba0616d6c1c Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 13:29:49 -0500 Subject: [PATCH 02/15] Add operator-sdk skeleton This adds the results of running: `operator-sdk new anthill --skip-git-init` and merging those files into the anthill repo unchanged. The initial `vendor` directory has not been committed. Signed-off-by: John Strunk --- .gitignore | 77 ++++ Gopkg.lock | 735 +++++++++++++++++++++++++++++++++++ Gopkg.toml | 54 +++ build/Dockerfile | 7 + cmd/manager/main.go | 78 ++++ deploy/operator.yaml | 36 ++ deploy/role.yaml | 33 ++ deploy/role_binding.yaml | 11 + deploy/service_account.yaml | 4 + pkg/apis/apis.go | 13 + pkg/controller/controller.go | 18 + version/version.go | 5 + 12 files changed, 1071 insertions(+) create mode 100644 .gitignore create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml create mode 100644 build/Dockerfile create mode 100644 cmd/manager/main.go create mode 100644 deploy/operator.yaml create mode 100644 deploy/role.yaml create mode 100644 deploy/role_binding.yaml create mode 100644 deploy/service_account.yaml create mode 100644 pkg/apis/apis.go create mode 100644 pkg/controller/controller.go create mode 100644 version/version.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c50470 --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ +# Temporary Build Files +build/_output +build/_test +# Created by https://www.gitignore.io/api/go,vim,emacs,visualstudiocode +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* +# Org-mode +.org-id-locations +*_archive +# flymake-mode +*_flymake.* +# eshell files +/eshell/history +/eshell/lastdir +# elpa packages +/elpa/ +# reftex files +*.rel +# AUCTeX auto folder +/auto/ +# cask packages +.cask/ +dist/ +# Flycheck +flycheck_*.el +# server auth directory +/server/ +# projectiles files +.projectile +projectile-bookmarks.eld +# directory configuration +.dir-locals.el +# saveplace +places +# url cache +url/cache/ +# cedet +ede-projects.el +# smex +smex-items +# company-statistics +company-statistics-cache.el +# anaconda-mode +anaconda-mode/ +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +# Test binary, build with 'go test -c' +*.test +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +### Vim ### +# swap +.sw[a-p] +.*.sw[a-p] +# session +Session.vim +# temporary +.netrwhist +# auto-generated tag files +tags +### VisualStudioCode ### +.vscode/* +.history +# End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..e8e8ce6 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,735 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:c4638ce2e73b35bb3b0a109d687d798159a1844e1174a80c1cc6d1895d2f6fe0" + name = "cloud.google.com/go" + packages = ["compute/metadata"] + pruneopts = "NT" + revision = "74b12019e2aa53ec27882158f59192d7cd6d1998" + version = "v0.33.1" + +[[projects]] + digest = "1:d8ebbd207f3d3266d4423ce4860c9f3794956306ded6c7ba312ecc69cdfbf04c" + name = "github.com/PuerkitoBio/purell" + packages = ["."] + pruneopts = "NT" + revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4" + version = "v1.1.0" + +[[projects]] + branch = "master" + digest = "1:8098cd40cd09879efbf12e33bcd51ead4a66006ac802cd563a66c4f3373b9727" + name = "github.com/PuerkitoBio/urlesc" + packages = ["."] + pruneopts = "NT" + revision = "de5bf2ad457846296e2031421a34e2568e304e35" + +[[projects]] + digest = "1:4b8b5811da6970495e04d1f4e98bb89518cc3cfc3b3f456bdb876ed7b6c74049" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "NT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:e6f888d4be8ec0f05c50e2aba83da4948b58045dee54d03be81fa74ea673302c" + name = "github.com/emicklei/go-restful" + packages = [ + ".", + "log", + ] + pruneopts = "NT" + revision = "3eb9738c1697594ea6e71a7156a9bb32ed216cf0" + version = "v2.8.0" + +[[projects]] + digest = "1:81466b4218bf6adddac2572a30ac733a9255919bc2f470b4827a317bd4ee1756" + name = "github.com/ghodss/yaml" + packages = ["."] + pruneopts = "NT" + revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" + version = "v1.0.0" + +[[projects]] + branch = "master" + digest = "1:d421af4c4fe51d399667d573982d663fe1fa67020a88d3ae43466ebfe8e2b5c9" + name = "github.com/go-logr/logr" + packages = ["."] + pruneopts = "NT" + revision = "9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e" + +[[projects]] + digest = "1:340497a512995aa69c0add901d79a2096b3449d35a44a6f1f1115091a9f8c687" + name = "github.com/go-logr/zapr" + packages = ["."] + pruneopts = "NT" + revision = "7536572e8d55209135cd5e7ccf7fce43dca217ab" + version = "v0.1.0" + +[[projects]] + digest = "1:260f7ebefc63024c8dfe2c9f1a2935a89fa4213637a1f522f592f80c001cc441" + name = "github.com/go-openapi/jsonpointer" + packages = ["."] + pruneopts = "NT" + revision = "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" + version = "v0.17.2" + +[[projects]] + digest = "1:98abd61947ff5c7c6fcfec5473d02a4821ed3a2dd99a4fbfdb7925b0dd745546" + name = "github.com/go-openapi/jsonreference" + packages = ["."] + pruneopts = "NT" + revision = "8483a886a90412cd6858df4ea3483dce9c8e35a3" + version = "v0.17.2" + +[[projects]] + digest = "1:dfab391de021809e0041f0ab5648da6b74dd16a685472a1b8c3dc06b3dca1ee2" + name = "github.com/go-openapi/spec" + packages = ["."] + pruneopts = "NT" + revision = "5bae59e25b21498baea7f9d46e9c147ec106a42e" + version = "v0.17.2" + +[[projects]] + digest = "1:983f95b2fae6fe8fdd361738325ed6090f4f3bd15ce4db745e899fb5b0fdfc46" + name = "github.com/go-openapi/swag" + packages = ["."] + pruneopts = "NT" + revision = "5899d5c5e619fda5fa86e14795a835f473ca284c" + version = "v0.17.2" + +[[projects]] + digest = "1:2a9d5e367df8c95e780975ca1dd4010bef8e39a3777066d3880ce274b39d4b5a" + name = "github.com/gogo/protobuf" + packages = [ + "proto", + "sortkeys", + ] + pruneopts = "NT" + revision = "636bf0302bc95575d69441b25a2603156ffdddf1" + version = "v1.1.1" + +[[projects]] + branch = "master" + digest = "1:e2b86e41f3d669fc36b50d31d32d22c8ac656c75aa5ea89717ce7177e134ff2a" + name = "github.com/golang/glog" + packages = ["."] + pruneopts = "NT" + revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" + +[[projects]] + branch = "master" + digest = "1:aaedc94233e56ed57cdb04e3abfacc85c90c14082b62e3cdbe8ea72fc06ee035" + name = "github.com/golang/groupcache" + packages = ["lru"] + pruneopts = "NT" + revision = "c65c006176ff7ff98bb916961c7abbc6b0afc0aa" + +[[projects]] + digest = "1:d7cb4458ea8782e6efacd8f4940796ec559c90833509c436f40c4085b98156dd" + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + ] + pruneopts = "NT" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" + +[[projects]] + branch = "master" + digest = "1:05f95ffdfcf651bdb0f05b40b69e7f5663047f8da75c72d58728acb59b5cc107" + name = "github.com/google/btree" + packages = ["."] + pruneopts = "NT" + revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" + +[[projects]] + branch = "master" + digest = "1:52c5834e2bebac9030c97cc0798ac11c3aa8a39f098aeb419f142533da6cd3cc" + name = "github.com/google/gofuzz" + packages = ["."] + pruneopts = "NT" + revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" + +[[projects]] + digest = "1:a1578f7323eca2b88021fdc9a79a99833d40b12c32a5ea4f284e2fad19ea2657" + name = "github.com/google/uuid" + packages = ["."] + pruneopts = "NT" + revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" + version = "v1.0.0" + +[[projects]] + digest = "1:289332c13b80edfefc88397cce5266c16845dcf204fa2f6ac7e464ee4c7f6e96" + name = "github.com/googleapis/gnostic" + packages = [ + "OpenAPIv2", + "compiler", + "extensions", + ] + pruneopts = "NT" + revision = "7c663266750e7d82587642f65e60bc4083f1f84e" + version = "v0.2.0" + +[[projects]] + branch = "master" + digest = "1:97972f03fbf34ec4247ddc78ddb681389c468c020492aa32b109744a54fc0c14" + name = "github.com/gregjones/httpcache" + packages = [ + ".", + "diskcache", + ] + pruneopts = "NT" + revision = "c63ab54fda8f77302f8d414e19933f2b6026a089" + +[[projects]] + digest = "1:b42cde0e1f3c816dd57f57f7bbcf05ca40263ad96f168714c130c611fc0856a6" + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru", + ] + pruneopts = "NT" + revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768" + version = "v0.5.0" + +[[projects]] + digest = "1:9a52adf44086cead3b384e5d0dbf7a1c1cce65e67552ee3383a8561c42a18cd3" + name = "github.com/imdario/mergo" + packages = ["."] + pruneopts = "NT" + revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" + version = "v0.3.6" + +[[projects]] + digest = "1:1d39c063244ad17c4b18e8da1551163b6ffb52bd1640a49a8ec5c3b7bf4dbd5d" + name = "github.com/json-iterator/go" + packages = ["."] + pruneopts = "NT" + revision = "1624edc4454b8682399def8740d46db5e4362ba4" + version = "v1.1.5" + +[[projects]] + branch = "master" + digest = "1:7d9fcac7f1228470c4ea0ee31cdfb662a758c44df691e39b3e76c11d3e12ba8f" + name = "github.com/mailru/easyjson" + packages = [ + "buffer", + "jlexer", + "jwriter", + ] + pruneopts = "NT" + revision = "60711f1a8329503b04e1c88535f419d0bb440bff" + +[[projects]] + branch = "master" + digest = "1:0e9bfc47ab9941ecc3344e580baca5deb4091177e84dd9773b48b38ec26b93d5" + name = "github.com/mattbaird/jsonpatch" + packages = ["."] + pruneopts = "NT" + revision = "81af80346b1a01caae0cbc27fd3c1ba5b11e189f" + +[[projects]] + digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f" + name = "github.com/modern-go/concurrent" + packages = ["."] + pruneopts = "NT" + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" + +[[projects]] + digest = "1:c6aca19413b13dc59c220ad7430329e2ec454cc310bc6d8de2c7e2b93c18a0f6" + name = "github.com/modern-go/reflect2" + packages = ["."] + pruneopts = "NT" + revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" + version = "1.0.1" + +[[projects]] + branch = "master" + digest = "1:57b5e60954a9c1e3b17427ccab5771b96d6c9d48114cb50331eceff2ddc6ad45" + name = "github.com/operator-framework/operator-sdk" + packages = [ + "pkg/k8sutil", + "version", + ] + pruneopts = "NT" + revision = "8412ccb47e4c7e14a5634e563e38e6bc05faa434" + +[[projects]] + digest = "1:93b1d84c5fa6d1ea52f4114c37714cddd84d5b78f151b62bb101128dd51399bf" + name = "github.com/pborman/uuid" + packages = ["."] + pruneopts = "NT" + revision = "adf5a7427709b9deb95d29d3fa8a2bf9cfd388f1" + version = "v1.2" + +[[projects]] + branch = "master" + digest = "1:bf2ac97824a7221eb16b096aecc1c390d4c8a4e49524386aaa2e2dd215cbfb31" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + pruneopts = "NT" + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + digest = "1:e4e9e026b8e4c5630205cd0208efb491b40ad40552e57f7a646bb8a46896077b" + name = "github.com/peterbourgon/diskv" + packages = ["."] + pruneopts = "NT" + revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" + version = "v2.0.1" + +[[projects]] + digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779" + name = "github.com/spf13/pflag" + packages = ["."] + pruneopts = "NT" + revision = "298182f68c66c05229eb03ac171abe6e309ee79a" + version = "v1.0.3" + +[[projects]] + digest = "1:22f696cee54865fb8e9ff91df7b633f6b8f22037a8015253c6b6a71ca82219c7" + name = "go.uber.org/atomic" + packages = ["."] + pruneopts = "NT" + revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289" + version = "v1.3.2" + +[[projects]] + digest = "1:58ca93bdf81bac106ded02226b5395a0595d5346cdc4caa8d9c1f3a5f8f9976e" + name = "go.uber.org/multierr" + packages = ["."] + pruneopts = "NT" + revision = "3c4937480c32f4c13a875a1829af76c98ca3d40a" + version = "v1.1.0" + +[[projects]] + digest = "1:572fa4496563920f3e3107a2294cf2621d6cc4ffd03403fb6397b1bab9fa082a" + name = "go.uber.org/zap" + packages = [ + ".", + "buffer", + "internal/bufferpool", + "internal/color", + "internal/exit", + "zapcore", + ] + pruneopts = "NT" + revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982" + version = "v1.9.1" + +[[projects]] + branch = "master" + digest = "1:417055c259ab65cfeacd7d0bf0b039c2809e80300cf0894937ff4eec2c5a866a" + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + pruneopts = "NT" + revision = "3d3f9f413869b949e48070b5bc593aa22cc2b8f2" + +[[projects]] + branch = "master" + digest = "1:d103910996bb5cd0c1cdbae00f22238e8f136ba70e70c242fcc28c400f2b2c75" + name = "golang.org/x/net" + packages = [ + "context", + "context/ctxhttp", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + ] + pruneopts = "NT" + revision = "adae6a3d119ae4890b46832a2e88a95adc62b8e7" + +[[projects]] + branch = "master" + digest = "1:948ab99b3a990ee11c6beb2d9e65217961897cbc0842acb57aad3d9f63c28f7e" + name = "golang.org/x/oauth2" + packages = [ + ".", + "google", + "internal", + "jws", + "jwt", + ] + pruneopts = "NT" + revision = "f42d05182288abf10faef86d16c0d07b8d40ea2d" + +[[projects]] + branch = "master" + digest = "1:7ebf4e1066ef714f700db6da5affc694e7d3ba83272efe7c18533cbac96df050" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows", + ] + pruneopts = "NT" + revision = "93218def8b18e66adbdab3eca8ec334700329f1f" + +[[projects]] + digest = "1:8c74f97396ed63cc2ef04ebb5fc37bb032871b8fd890a25991ed40974b00cd2a" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + "width", + ] + pruneopts = "NT" + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + branch = "master" + digest = "1:9fdc2b55e8e0fafe4b41884091e51e77344f7dc511c5acedcfd98200003bff90" + name = "golang.org/x/time" + packages = ["rate"] + pruneopts = "NT" + revision = "85acf8d2951cb2a3bde7632f9ff273ef0379bcbd" + +[[projects]] + branch = "master" + digest = "1:a6d387402684066899a57f8d07213ee3c3b7fa46d8248cdc305fe4b1bd6e212a" + name = "golang.org/x/tools" + packages = [ + "go/ast/astutil", + "imports", + "internal/fastwalk", + "internal/gopathwalk", + ] + pruneopts = "NT" + revision = "f87c222f148786695d2ee5761b06751bb9211f61" + +[[projects]] + digest = "1:2a4972ee51c3b9dfafbb3451fa0552e7a198d9d12c721bfc492050fe2f72e0f6" + name = "google.golang.org/appengine" + packages = [ + ".", + "internal", + "internal/app_identity", + "internal/base", + "internal/datastore", + "internal/log", + "internal/modules", + "internal/remote_api", + "internal/urlfetch", + "urlfetch", + ] + pruneopts = "NT" + revision = "4a4468ece617fc8205e99368fa2200e9d1fad421" + version = "v1.3.0" + +[[projects]] + digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a" + name = "gopkg.in/inf.v0" + packages = ["."] + pruneopts = "NT" + revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" + version = "v0.9.1" + +[[projects]] + digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082" + name = "gopkg.in/yaml.v2" + packages = ["."] + pruneopts = "NT" + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[[projects]] + digest = "1:f11e5753e619f411a51a49d60d39b2bc4da6766f5f0af2e2291daa6a3d9385d5" + name = "k8s.io/api" + packages = [ + "admission/v1beta1", + "admissionregistration/v1alpha1", + "admissionregistration/v1beta1", + "apps/v1", + "apps/v1beta1", + "apps/v1beta2", + "authentication/v1", + "authentication/v1beta1", + "authorization/v1", + "authorization/v1beta1", + "autoscaling/v1", + "autoscaling/v2beta1", + "batch/v1", + "batch/v1beta1", + "batch/v2alpha1", + "certificates/v1beta1", + "core/v1", + "events/v1beta1", + "extensions/v1beta1", + "networking/v1", + "policy/v1beta1", + "rbac/v1", + "rbac/v1alpha1", + "rbac/v1beta1", + "scheduling/v1alpha1", + "scheduling/v1beta1", + "settings/v1alpha1", + "storage/v1", + "storage/v1alpha1", + "storage/v1beta1", + ] + pruneopts = "NT" + revision = "2d6f90ab1293a1fb871cf149423ebb72aa7423aa" + +[[projects]] + digest = "1:b07bf863262aae765494d60f0d524483f211b29f9bb27d445a79c13af8676bf2" + name = "k8s.io/apimachinery" + packages = [ + "pkg/api/errors", + "pkg/api/meta", + "pkg/api/resource", + "pkg/apis/meta/internalversion", + "pkg/apis/meta/v1", + "pkg/apis/meta/v1/unstructured", + "pkg/apis/meta/v1beta1", + "pkg/conversion", + "pkg/conversion/queryparams", + "pkg/fields", + "pkg/labels", + "pkg/runtime", + "pkg/runtime/schema", + "pkg/runtime/serializer", + "pkg/runtime/serializer/json", + "pkg/runtime/serializer/protobuf", + "pkg/runtime/serializer/recognizer", + "pkg/runtime/serializer/streaming", + "pkg/runtime/serializer/versioning", + "pkg/selection", + "pkg/types", + "pkg/util/cache", + "pkg/util/clock", + "pkg/util/diff", + "pkg/util/errors", + "pkg/util/framer", + "pkg/util/intstr", + "pkg/util/json", + "pkg/util/mergepatch", + "pkg/util/net", + "pkg/util/runtime", + "pkg/util/sets", + "pkg/util/strategicpatch", + "pkg/util/uuid", + "pkg/util/validation", + "pkg/util/validation/field", + "pkg/util/wait", + "pkg/util/yaml", + "pkg/version", + "pkg/watch", + "third_party/forked/golang/json", + "third_party/forked/golang/reflect", + ] + pruneopts = "NT" + revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" + +[[projects]] + digest = "1:1689a49a3ebc6e379849181f1e0899fccf143cab47586078721818bdcdb712bc" + name = "k8s.io/client-go" + packages = [ + "discovery", + "dynamic", + "kubernetes", + "kubernetes/scheme", + "kubernetes/typed/admissionregistration/v1alpha1", + "kubernetes/typed/admissionregistration/v1beta1", + "kubernetes/typed/apps/v1", + "kubernetes/typed/apps/v1beta1", + "kubernetes/typed/apps/v1beta2", + "kubernetes/typed/authentication/v1", + "kubernetes/typed/authentication/v1beta1", + "kubernetes/typed/authorization/v1", + "kubernetes/typed/authorization/v1beta1", + "kubernetes/typed/autoscaling/v1", + "kubernetes/typed/autoscaling/v2beta1", + "kubernetes/typed/batch/v1", + "kubernetes/typed/batch/v1beta1", + "kubernetes/typed/batch/v2alpha1", + "kubernetes/typed/certificates/v1beta1", + "kubernetes/typed/core/v1", + "kubernetes/typed/events/v1beta1", + "kubernetes/typed/extensions/v1beta1", + "kubernetes/typed/networking/v1", + "kubernetes/typed/policy/v1beta1", + "kubernetes/typed/rbac/v1", + "kubernetes/typed/rbac/v1alpha1", + "kubernetes/typed/rbac/v1beta1", + "kubernetes/typed/scheduling/v1alpha1", + "kubernetes/typed/scheduling/v1beta1", + "kubernetes/typed/settings/v1alpha1", + "kubernetes/typed/storage/v1", + "kubernetes/typed/storage/v1alpha1", + "kubernetes/typed/storage/v1beta1", + "pkg/apis/clientauthentication", + "pkg/apis/clientauthentication/v1alpha1", + "pkg/apis/clientauthentication/v1beta1", + "pkg/version", + "plugin/pkg/client/auth/exec", + "plugin/pkg/client/auth/gcp", + "rest", + "rest/watch", + "restmapper", + "third_party/forked/golang/template", + "tools/auth", + "tools/cache", + "tools/clientcmd", + "tools/clientcmd/api", + "tools/clientcmd/api/latest", + "tools/clientcmd/api/v1", + "tools/leaderelection", + "tools/leaderelection/resourcelock", + "tools/metrics", + "tools/pager", + "tools/record", + "tools/reference", + "transport", + "util/buffer", + "util/cert", + "util/connrotation", + "util/flowcontrol", + "util/homedir", + "util/integer", + "util/jsonpath", + "util/retry", + ] + pruneopts = "NT" + revision = "1f13a808da65775f22cbf47862c4e5898d8f4ca1" + +[[projects]] + digest = "1:8ab487a323486c8bbbaa3b689850487fdccc6cbea8690620e083b2d230a4447e" + name = "k8s.io/code-generator" + packages = [ + "cmd/client-gen", + "cmd/client-gen/args", + "cmd/client-gen/generators", + "cmd/client-gen/generators/fake", + "cmd/client-gen/generators/scheme", + "cmd/client-gen/generators/util", + "cmd/client-gen/path", + "cmd/client-gen/types", + "cmd/conversion-gen", + "cmd/conversion-gen/args", + "cmd/conversion-gen/generators", + "cmd/deepcopy-gen", + "cmd/deepcopy-gen/args", + "cmd/defaulter-gen", + "cmd/defaulter-gen/args", + "cmd/informer-gen", + "cmd/informer-gen/args", + "cmd/informer-gen/generators", + "cmd/lister-gen", + "cmd/lister-gen/args", + "cmd/lister-gen/generators", + "cmd/openapi-gen", + "cmd/openapi-gen/args", + "pkg/util", + ] + pruneopts = "T" + revision = "6702109cc68eb6fe6350b83e14407c8d7309fd1a" + +[[projects]] + branch = "master" + digest = "1:5edbd655d7ee65178fd5750bda9a3d3cd7fb96291937926f4969e6b2dfbc5743" + name = "k8s.io/gengo" + packages = [ + "args", + "examples/deepcopy-gen/generators", + "examples/defaulter-gen/generators", + "examples/set-gen/sets", + "generator", + "namer", + "parser", + "types", + ] + pruneopts = "NT" + revision = "fd15ee9cc2f77baa4f31e59e6acbf21146455073" + +[[projects]] + digest = "1:f3b42f307c7f49a1a7276c48d4b910db76e003220e88797f7acd41e3a9277ddf" + name = "k8s.io/klog" + packages = ["."] + pruneopts = "NT" + revision = "a5bc97fbc634d635061f3146511332c7e313a55a" + version = "v0.1.0" + +[[projects]] + branch = "master" + digest = "1:9ac2fdede4a8304e3b00ea3b36526536339f306d0306e320fc74f6cefeead18e" + name = "k8s.io/kube-openapi" + packages = [ + "cmd/openapi-gen/args", + "pkg/common", + "pkg/generators", + "pkg/generators/rules", + "pkg/util/proto", + "pkg/util/sets", + ] + pruneopts = "NT" + revision = "0317810137be915b9cf888946c6e115c1bfac693" + +[[projects]] + digest = "1:d1b7a6ed45c957e6308759f31fdbff8063741ecb08b7c3b6d67f0c9f4357b2ae" + name = "sigs.k8s.io/controller-runtime" + packages = [ + "pkg/cache", + "pkg/cache/internal", + "pkg/client", + "pkg/client/apiutil", + "pkg/client/config", + "pkg/internal/recorder", + "pkg/leaderelection", + "pkg/manager", + "pkg/patch", + "pkg/recorder", + "pkg/runtime/inject", + "pkg/runtime/log", + "pkg/runtime/signals", + "pkg/webhook/admission", + "pkg/webhook/admission/types", + "pkg/webhook/types", + ] + pruneopts = "NT" + revision = "5fd1e9e9fac5261e9ad9d47c375afc014fc31d21" + version = "v0.1.7" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/operator-framework/operator-sdk/pkg/k8sutil", + "github.com/operator-framework/operator-sdk/version", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/client-go/plugin/pkg/client/auth/gcp", + "k8s.io/code-generator/cmd/client-gen", + "k8s.io/code-generator/cmd/conversion-gen", + "k8s.io/code-generator/cmd/deepcopy-gen", + "k8s.io/code-generator/cmd/defaulter-gen", + "k8s.io/code-generator/cmd/informer-gen", + "k8s.io/code-generator/cmd/lister-gen", + "k8s.io/code-generator/cmd/openapi-gen", + "k8s.io/gengo/args", + "sigs.k8s.io/controller-runtime/pkg/client/config", + "sigs.k8s.io/controller-runtime/pkg/manager", + "sigs.k8s.io/controller-runtime/pkg/runtime/log", + "sigs.k8s.io/controller-runtime/pkg/runtime/signals", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..ce9bb4e --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,54 @@ +# Force dep to vendor the code generators, which aren't imported just used at dev time. +required = [ + "k8s.io/code-generator/cmd/defaulter-gen", + "k8s.io/code-generator/cmd/deepcopy-gen", + "k8s.io/code-generator/cmd/conversion-gen", + "k8s.io/code-generator/cmd/client-gen", + "k8s.io/code-generator/cmd/lister-gen", + "k8s.io/code-generator/cmd/informer-gen", + "k8s.io/code-generator/cmd/openapi-gen", + "k8s.io/gengo/args", +] + +[[override]] + name = "k8s.io/code-generator" + # revision for tag "kubernetes-1.11.2" + revision = "6702109cc68eb6fe6350b83e14407c8d7309fd1a" + +[[override]] + name = "k8s.io/api" + # revision for tag "kubernetes-1.11.2" + revision = "2d6f90ab1293a1fb871cf149423ebb72aa7423aa" + +[[override]] + name = "k8s.io/apiextensions-apiserver" + # revision for tag "kubernetes-1.11.2" + revision = "408db4a50408e2149acbd657bceb2480c13cb0a4" + +[[override]] + name = "k8s.io/apimachinery" + # revision for tag "kubernetes-1.11.2" + revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" + +[[override]] + name = "k8s.io/client-go" + # revision for tag "kubernetes-1.11.2" + revision = "1f13a808da65775f22cbf47862c4e5898d8f4ca1" + +[[override]] + name = "sigs.k8s.io/controller-runtime" + version = "v0.1.4" + +[[constraint]] + name = "github.com/operator-framework/operator-sdk" + # The version rule is used for a specific release and the master branch for in between releases. + branch = "master" #osdk_branch_annotation + # version = "=v0.1.1" #osdk_version_annotation + +[prune] + go-tests = true + non-go = true + + [[prune.project]] + name = "k8s.io/code-generator" + non-go = false diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 0000000..de5325f --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,7 @@ +FROM alpine:3.8 + +RUN apk upgrade --update --no-cache + +USER nobody + +ADD build/_output/bin/anthill /usr/local/bin/anthill diff --git a/cmd/manager/main.go b/cmd/manager/main.go new file mode 100644 index 0000000..6d69f02 --- /dev/null +++ b/cmd/manager/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "flag" + "fmt" + "os" + "runtime" + + "github.com/gluster/anthill/pkg/apis" + "github.com/gluster/anthill/pkg/controller" + "github.com/operator-framework/operator-sdk/pkg/k8sutil" + sdkVersion "github.com/operator-framework/operator-sdk/version" + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/manager" + logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" + "sigs.k8s.io/controller-runtime/pkg/runtime/signals" +) + +func printVersion() { + logf.Log.Info(fmt.Sprintf("Go Version: %s", runtime.Version())) + logf.Log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH)) + logf.Log.Info(fmt.Sprintf("operator-sdk Version: %v", sdkVersion.Version)) +} + +func main() { + printVersion() + flag.Parse() + + // The logger instantiated here can be changed to any logger + // implementing the logr.Logger interface. This logger will + // be propagated through the whole operator, generating + // uniform and structured logs. + logf.SetLogger(logf.ZapLogger(false)) + log := logf.Log.WithName("cmd") + + namespace, err := k8sutil.GetWatchNamespace() + if err != nil { + log.Error(err, "failed to get watch namespace") + os.Exit(1) + } + + // Get a config to talk to the apiserver + cfg, err := config.GetConfig() + if err != nil { + log.Error(err, "") + os.Exit(1) + } + + // Create a new Cmd to provide shared dependencies and start components + mgr, err := manager.New(cfg, manager.Options{Namespace: namespace}) + if err != nil { + log.Error(err, "") + os.Exit(1) + } + + log.Info("Registering Components.") + + // Setup Scheme for all resources + if err := apis.AddToScheme(mgr.GetScheme()); err != nil { + log.Error(err, "") + os.Exit(1) + } + + // Setup all Controllers + if err := controller.AddToManager(mgr); err != nil { + log.Error(err, "") + os.Exit(1) + } + + log.Info("Starting the Cmd.") + + // Start the Cmd + if err := mgr.Start(signals.SetupSignalHandler()); err != nil { + log.Error(err, "manager exited non-zero") + os.Exit(1) + } +} diff --git a/deploy/operator.yaml b/deploy/operator.yaml new file mode 100644 index 0000000..82ccbc9 --- /dev/null +++ b/deploy/operator.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: anthill +spec: + replicas: 1 + selector: + matchLabels: + name: anthill + template: + metadata: + labels: + name: anthill + spec: + serviceAccountName: anthill + containers: + - name: anthill + # Replace this with the built image name + image: REPLACE_IMAGE + ports: + - containerPort: 60000 + name: metrics + command: + - anthill + imagePullPolicy: Always + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: "anthill" diff --git a/deploy/role.yaml b/deploy/role.yaml new file mode 100644 index 0000000..ef40c44 --- /dev/null +++ b/deploy/role.yaml @@ -0,0 +1,33 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: anthill +rules: +- apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - "*" +- apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - "*" +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - "get" + - "create" diff --git a/deploy/role_binding.yaml b/deploy/role_binding.yaml new file mode 100644 index 0000000..ca50ce8 --- /dev/null +++ b/deploy/role_binding.yaml @@ -0,0 +1,11 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: anthill +subjects: +- kind: ServiceAccount + name: anthill +roleRef: + kind: Role + name: anthill + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/service_account.yaml b/deploy/service_account.yaml new file mode 100644 index 0000000..f465817 --- /dev/null +++ b/deploy/service_account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: anthill diff --git a/pkg/apis/apis.go b/pkg/apis/apis.go new file mode 100644 index 0000000..07dc961 --- /dev/null +++ b/pkg/apis/apis.go @@ -0,0 +1,13 @@ +package apis + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// AddToSchemes may be used to add all resources defined in the project to a Scheme +var AddToSchemes runtime.SchemeBuilder + +// AddToScheme adds all Resources to the Scheme +func AddToScheme(s *runtime.Scheme) error { + return AddToSchemes.AddToScheme(s) +} diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go new file mode 100644 index 0000000..7c069f3 --- /dev/null +++ b/pkg/controller/controller.go @@ -0,0 +1,18 @@ +package controller + +import ( + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +// AddToManagerFuncs is a list of functions to add all Controllers to the Manager +var AddToManagerFuncs []func(manager.Manager) error + +// AddToManager adds all Controllers to the Manager +func AddToManager(m manager.Manager) error { + for _, f := range AddToManagerFuncs { + if err := f(m); err != nil { + return err + } + } + return nil +} diff --git a/version/version.go b/version/version.go new file mode 100644 index 0000000..e3e130b --- /dev/null +++ b/version/version.go @@ -0,0 +1,5 @@ +package version + +var ( + Version = "0.0.1" +) From 03fc0f30e58c5a41d928a6b8846d0cbaa2cf7766 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 13:34:17 -0500 Subject: [PATCH 03/15] Add vendor directory to .gitignore Signed-off-by: John Strunk --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7c50470..6158bde 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ tags .vscode/* .history # End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode +/vendor/ From 825cfc83779e4301366dde84cd6610061f1914c4 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 13:42:47 -0500 Subject: [PATCH 04/15] Fix errors in yaml formatting The operator-sdk produced yamls w/ poor indentation. This fixes the affected files so they pass yamllint Signed-off-by: John Strunk --- deploy/operator.yaml | 7 +++-- deploy/role.yaml | 57 +++++++++++++++++++------------------ deploy/role_binding.yaml | 5 ++-- deploy/service_account.yaml | 1 + 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 82ccbc9..7c53466 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -18,10 +19,10 @@ spec: # Replace this with the built image name image: REPLACE_IMAGE ports: - - containerPort: 60000 - name: metrics + - containerPort: 60000 + name: metrics command: - - anthill + - anthill imagePullPolicy: Always env: - name: WATCH_NAMESPACE diff --git a/deploy/role.yaml b/deploy/role.yaml index ef40c44..6512571 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -1,33 +1,34 @@ +--- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: anthill rules: -- apiGroups: - - "" - resources: - - pods - - services - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - "*" -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - "*" -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - "get" - - "create" + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - "*" + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - "*" + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - "get" + - "create" diff --git a/deploy/role_binding.yaml b/deploy/role_binding.yaml index ca50ce8..f498f71 100644 --- a/deploy/role_binding.yaml +++ b/deploy/role_binding.yaml @@ -1,10 +1,11 @@ +--- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: anthill subjects: -- kind: ServiceAccount - name: anthill + - kind: ServiceAccount + name: anthill roleRef: kind: Role name: anthill diff --git a/deploy/service_account.yaml b/deploy/service_account.yaml index f465817..420ad2c 100644 --- a/deploy/service_account.yaml +++ b/deploy/service_account.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ServiceAccount metadata: From d545a31a1f9d5606ddf0f47d5a31445b264cbeab Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 13:58:51 -0500 Subject: [PATCH 05/15] Add GlusterCluster CRD Results of running: `operator-sdk add api --api-version=operator.gluster.org/v1alpha1 --kind=GlusterCluster` Signed-off-by: John Strunk --- .../operator_v1alpha1_glustercluster_cr.yaml | 7 ++ .../operator_v1alpha1_glustercluster_crd.yaml | 13 ++ deploy/role.yaml | 66 +++++----- pkg/apis/addtoscheme_operator_v1alpha1.go | 10 ++ pkg/apis/operator/v1alpha1/doc.go | 4 + .../operator/v1alpha1/glustercluster_types.go | 45 +++++++ pkg/apis/operator/v1alpha1/register.go | 19 +++ .../v1alpha1/zz_generated.deepcopy.go | 118 ++++++++++++++++++ 8 files changed, 252 insertions(+), 30 deletions(-) create mode 100644 deploy/crds/operator_v1alpha1_glustercluster_cr.yaml create mode 100644 deploy/crds/operator_v1alpha1_glustercluster_crd.yaml create mode 100644 pkg/apis/addtoscheme_operator_v1alpha1.go create mode 100644 pkg/apis/operator/v1alpha1/doc.go create mode 100644 pkg/apis/operator/v1alpha1/glustercluster_types.go create mode 100644 pkg/apis/operator/v1alpha1/register.go create mode 100644 pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go diff --git a/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml b/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml new file mode 100644 index 0000000..483c129 --- /dev/null +++ b/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml @@ -0,0 +1,7 @@ +apiVersion: operator.gluster.org/v1alpha1 +kind: GlusterCluster +metadata: + name: example-glustercluster +spec: + # Add fields here + size: 3 diff --git a/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml b/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml new file mode 100644 index 0000000..8b9a042 --- /dev/null +++ b/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml @@ -0,0 +1,13 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: glusterclusters.operator.gluster.org +spec: + group: operator.gluster.org + names: + kind: GlusterCluster + listKind: GlusterClusterList + plural: glusterclusters + singular: glustercluster + scope: Namespaced + version: v1alpha1 diff --git a/deploy/role.yaml b/deploy/role.yaml index 6512571..88f4127 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -1,34 +1,40 @@ ---- -kind: Role apiVersion: rbac.authorization.k8s.io/v1 +kind: Role metadata: + creationTimestamp: null name: anthill rules: - - apiGroups: - - "" - resources: - - pods - - services - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - "*" - - apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - "*" - - apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - "get" - - "create" +- apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - '*' +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create +- apiGroups: + - operator.gluster.org + resources: + - '*' + verbs: + - '*' diff --git a/pkg/apis/addtoscheme_operator_v1alpha1.go b/pkg/apis/addtoscheme_operator_v1alpha1.go new file mode 100644 index 0000000..24cc2ed --- /dev/null +++ b/pkg/apis/addtoscheme_operator_v1alpha1.go @@ -0,0 +1,10 @@ +package apis + +import ( + "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" +) + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) +} diff --git a/pkg/apis/operator/v1alpha1/doc.go b/pkg/apis/operator/v1alpha1/doc.go new file mode 100644 index 0000000..4439bc3 --- /dev/null +++ b/pkg/apis/operator/v1alpha1/doc.go @@ -0,0 +1,4 @@ +// Package v1alpha1 contains API Schema definitions for the operator v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=operator.gluster.org +package v1alpha1 diff --git a/pkg/apis/operator/v1alpha1/glustercluster_types.go b/pkg/apis/operator/v1alpha1/glustercluster_types.go new file mode 100644 index 0000000..ed16da7 --- /dev/null +++ b/pkg/apis/operator/v1alpha1/glustercluster_types.go @@ -0,0 +1,45 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// GlusterClusterSpec defines the desired state of GlusterCluster +type GlusterClusterSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file +} + +// GlusterClusterStatus defines the observed state of GlusterCluster +type GlusterClusterStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// GlusterCluster is the Schema for the glusterclusters API +// +k8s:openapi-gen=true +type GlusterCluster struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GlusterClusterSpec `json:"spec,omitempty"` + Status GlusterClusterStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// GlusterClusterList contains a list of GlusterCluster +type GlusterClusterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GlusterCluster `json:"items"` +} + +func init() { + SchemeBuilder.Register(&GlusterCluster{}, &GlusterClusterList{}) +} diff --git a/pkg/apis/operator/v1alpha1/register.go b/pkg/apis/operator/v1alpha1/register.go new file mode 100644 index 0000000..a33eb9e --- /dev/null +++ b/pkg/apis/operator/v1alpha1/register.go @@ -0,0 +1,19 @@ +// NOTE: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the operator v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=operator.gluster.org +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "operator.gluster.org", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000..ad985fd --- /dev/null +++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,118 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterCluster) DeepCopyInto(out *GlusterCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterCluster. +func (in *GlusterCluster) DeepCopy() *GlusterCluster { + if in == nil { + return nil + } + out := new(GlusterCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GlusterCluster) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterClusterList) DeepCopyInto(out *GlusterClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GlusterCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterClusterList. +func (in *GlusterClusterList) DeepCopy() *GlusterClusterList { + if in == nil { + return nil + } + out := new(GlusterClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GlusterClusterList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterClusterSpec) DeepCopyInto(out *GlusterClusterSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterClusterSpec. +func (in *GlusterClusterSpec) DeepCopy() *GlusterClusterSpec { + if in == nil { + return nil + } + out := new(GlusterClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterClusterStatus) DeepCopyInto(out *GlusterClusterStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterClusterStatus. +func (in *GlusterClusterStatus) DeepCopy() *GlusterClusterStatus { + if in == nil { + return nil + } + out := new(GlusterClusterStatus) + in.DeepCopyInto(out) + return out +} From 9421ebbf5ae39cc5490ef8d528f7f4c18b03f2c5 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 14:05:52 -0500 Subject: [PATCH 06/15] Fix errors in yaml formatting Signed-off-by: John Strunk --- .../operator_v1alpha1_glustercluster_cr.yaml | 1 + .../operator_v1alpha1_glustercluster_crd.yaml | 1 + deploy/role.yaml | 69 ++++++++++--------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml b/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml index 483c129..3c4dc61 100644 --- a/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml +++ b/deploy/crds/operator_v1alpha1_glustercluster_cr.yaml @@ -1,3 +1,4 @@ +--- apiVersion: operator.gluster.org/v1alpha1 kind: GlusterCluster metadata: diff --git a/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml b/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml index 8b9a042..984d6f1 100644 --- a/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml +++ b/deploy/crds/operator_v1alpha1_glustercluster_crd.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: diff --git a/deploy/role.yaml b/deploy/role.yaml index 88f4127..d876d5c 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -1,40 +1,41 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: creationTimestamp: null name: anthill rules: -- apiGroups: - - "" - resources: - - pods - - services - - endpoints - - persistentvolumeclaims - - events - - configmaps - - secrets - verbs: - - '*' -- apiGroups: - - apps - resources: - - deployments - - daemonsets - - replicasets - - statefulsets - verbs: - - '*' -- apiGroups: - - monitoring.coreos.com - resources: - - servicemonitors - verbs: - - get - - create -- apiGroups: - - operator.gluster.org - resources: - - '*' - verbs: - - '*' + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - '*' + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create + - apiGroups: + - operator.gluster.org + resources: + - '*' + verbs: + - '*' From 25a97c084ba624815ccc6e0139ebe2b56a94d4f6 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 14:12:58 -0500 Subject: [PATCH 07/15] Add the controller skeleton for GlusterCluster This is the result of: `operator-sdk add controller --api-version=operator.gluster.org/v1alpha1 --kind=GlusterCluster` Signed-off-by: John Strunk --- pkg/controller/add_glustercluster.go | 10 ++ .../glustercluster_controller.go | 152 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 pkg/controller/add_glustercluster.go create mode 100644 pkg/controller/glustercluster/glustercluster_controller.go diff --git a/pkg/controller/add_glustercluster.go b/pkg/controller/add_glustercluster.go new file mode 100644 index 0000000..9e09648 --- /dev/null +++ b/pkg/controller/add_glustercluster.go @@ -0,0 +1,10 @@ +package controller + +import ( + "github.com/gluster/anthill/pkg/controller/glustercluster" +) + +func init() { + // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. + AddToManagerFuncs = append(AddToManagerFuncs, glustercluster.Add) +} diff --git a/pkg/controller/glustercluster/glustercluster_controller.go b/pkg/controller/glustercluster/glustercluster_controller.go new file mode 100644 index 0000000..3c788d1 --- /dev/null +++ b/pkg/controller/glustercluster/glustercluster_controller.go @@ -0,0 +1,152 @@ +package glustercluster + +import ( + "context" + + operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +var log = logf.Log.WithName("controller_glustercluster") + +/** +* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller +* business logic. Delete these comments after modifying this file.* + */ + +// Add creates a new GlusterCluster Controller and adds it to the Manager. The Manager will set fields on the Controller +// and Start it when the Manager is Started. +func Add(mgr manager.Manager) error { + return add(mgr, newReconciler(mgr)) +} + +// newReconciler returns a new reconcile.Reconciler +func newReconciler(mgr manager.Manager) reconcile.Reconciler { + return &ReconcileGlusterCluster{client: mgr.GetClient(), scheme: mgr.GetScheme()} +} + +// add adds a new Controller to mgr with r as the reconcile.Reconciler +func add(mgr manager.Manager, r reconcile.Reconciler) error { + // Create a new controller + c, err := controller.New("glustercluster-controller", mgr, controller.Options{Reconciler: r}) + if err != nil { + return err + } + + // Watch for changes to primary resource GlusterCluster + err = c.Watch(&source.Kind{Type: &operatorv1alpha1.GlusterCluster{}}, &handler.EnqueueRequestForObject{}) + if err != nil { + return err + } + + // TODO(user): Modify this to be the types you create that are owned by the primary resource + // Watch for changes to secondary resource Pods and requeue the owner GlusterCluster + err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &operatorv1alpha1.GlusterCluster{}, + }) + if err != nil { + return err + } + + return nil +} + +var _ reconcile.Reconciler = &ReconcileGlusterCluster{} + +// ReconcileGlusterCluster reconciles a GlusterCluster object +type ReconcileGlusterCluster struct { + // This client, initialized using mgr.Client() above, is a split client + // that reads objects from the cache and writes to the apiserver + client client.Client + scheme *runtime.Scheme +} + +// Reconcile reads that state of the cluster for a GlusterCluster object and makes changes based on the state read +// and what is in the GlusterCluster.Spec +// TODO(user): Modify this Reconcile function to implement your Controller logic. This example creates +// a Pod as an example +// Note: +// The Controller will requeue the Request to be processed again if the returned error is non-nil or +// Result.Requeue is true, otherwise upon completion it will remove the work from the queue. +func (r *ReconcileGlusterCluster) Reconcile(request reconcile.Request) (reconcile.Result, error) { + reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) + reqLogger.Info("Reconciling GlusterCluster") + + // Fetch the GlusterCluster instance + instance := &operatorv1alpha1.GlusterCluster{} + err := r.client.Get(context.TODO(), request.NamespacedName, instance) + if err != nil { + if errors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + return reconcile.Result{}, nil + } + // Error reading the object - requeue the request. + return reconcile.Result{}, err + } + + // Define a new Pod object + pod := newPodForCR(instance) + + // Set GlusterCluster instance as the owner and controller + if err := controllerutil.SetControllerReference(instance, pod, r.scheme); err != nil { + return reconcile.Result{}, err + } + + // Check if this Pod already exists + found := &corev1.Pod{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: pod.Name, Namespace: pod.Namespace}, found) + if err != nil && errors.IsNotFound(err) { + reqLogger.Info("Creating a new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name) + err = r.client.Create(context.TODO(), pod) + if err != nil { + return reconcile.Result{}, err + } + + // Pod created successfully - don't requeue + return reconcile.Result{}, nil + } else if err != nil { + return reconcile.Result{}, err + } + + // Pod already exists - don't requeue + reqLogger.Info("Skip reconcile: Pod already exists", "Pod.Namespace", found.Namespace, "Pod.Name", found.Name) + return reconcile.Result{}, nil +} + +// newPodForCR returns a busybox pod with the same name/namespace as the cr +func newPodForCR(cr *operatorv1alpha1.GlusterCluster) *corev1.Pod { + labels := map[string]string{ + "app": cr.Name, + } + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: cr.Name + "-pod", + Namespace: cr.Namespace, + Labels: labels, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "busybox", + Image: "busybox", + Command: []string{"sleep", "3600"}, + }, + }, + }, + } +} From b2a3b78aacc51c33dc314ee0fed2b9ad9b0865b9 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 14:47:30 -0500 Subject: [PATCH 08/15] Add instructions to build and run the operator Signed-off-by: John Strunk --- README.md | 65 ++++++++++++++++++++++++++++++++++++++++++- scripts/mdl-style.rb | 9 ++++++ scripts/pre-commit.sh | 4 +-- 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 scripts/mdl-style.rb diff --git a/README.md b/README.md index 3caf2cf..b080a77 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,69 @@ **Interested in helping out?** Take a look at the [contributing doc](CONTRIBUTING.md) to find out how. +## Build + +The operator is based on the [Operator +SDK](https://github.com/operator-framework/operator-sdk). In order to build the +operator, you first need to install the SDK. [Instructions are +here.](https://github.com/operator-framework/operator-sdk#quick-start) + +Once the SDK is installed, Anthill can be built via: + +```bash +$ operator-sdk build docker.io/gluster/anthill +INFO[0001] Building Docker image docker.io/gluster/anthill +Sending build context to Docker daemon 114.7MB +Step 1/4 : FROM alpine:3.8 + ---> 196d12cf6ab1 +Step 2/4 : RUN apk upgrade --update --no-cache + ---> Using cache + ---> 6a5bb76fe272 +Step 3/4 : USER nobody + ---> Using cache + ---> faf8acce50e4 +Step 4/4 : ADD build/_output/bin/anthill /usr/local/bin/anthill + ---> Using cache + ---> b404638145da +Successfully built b404638145da +Successfully tagged gluster/anthill:latest +INFO[0002] Operator build complete. +``` + ## Installation -Once we have something to install, it'll be easy... we promise. :smile: +Install the CRDs into the cluster: + +```bash +$ kubectl apply -f deploy/crds/operator_v1alpha1_glustercluster_crd.yaml +customresourcedefinition.apiextensions.k8s.io "glusterclusters.operator.gluster.org" created +``` + +Install the service account, role, and rolebinding: + +```bash +$ kubectl apply -f deploy/service_account.yaml +serviceaccount "anthill" created + +$ kubectl apply -f deploy/role.yaml +role.rbac.authorization.k8s.io "anthill" created + +$ kubectl apply -f deploy/role_binding.yaml +rolebinding.rbac.authorization.k8s.io "anthill" created +``` + +There are two options for deploying the operator. + +1. It can be run normally, inside the cluster. For this, see + `deploy/operator.yaml` for a skeleton. +1. It can also be run outside the cluster for development purposes. This + removes the need to push the container to a registry by running the operator + executable locally. For this: + + ```bash + $ OPERATOR_NAME=anthill operator-sdk up local --namespace=default + INFO[0000] Running the operator locally. + {"level":"info","ts":1542396040.2412076,"logger":"cmd","caller":"manager/main.go:57","msg":"Registering Components."} + {"level":"info","ts":1542396040.2413611,"logger":"kubebuilder.controller","caller":"controller/controller.go:120","msg":"Starting EventSource","Controller":"glustercluster-controller","Source":"kind source: /, Kind="} + ... + ``` diff --git a/scripts/mdl-style.rb b/scripts/mdl-style.rb new file mode 100644 index 0000000..3f39256 --- /dev/null +++ b/scripts/mdl-style.rb @@ -0,0 +1,9 @@ +all + +#Refer below url for more information about the markdown rules. +#https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md + +rule 'MD013', :code_blocks => false, :tables => false + +exclude_rule 'MD040' # Fenced code blocks should have a language specified +exclude_rule 'MD041' # First line in file should be a top level header diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index 9d379a2..74a57f2 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -40,12 +40,12 @@ run_check '.*\.adoc' asciidoctor -o /dev/null -v --failure-level WARN # markdownlint: https://github.com/markdownlint/markdownlint # https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md # Install via: gem install mdl -run_check '.*\.md' mdl +run_check '.*\.md' mdl --style scripts/mdl-style.rb # Install via: dnf install shellcheck run_check '.*\.(ba)?sh' shellcheck # Install via: pip install yamllint -run_check '.*\.ya?ml' yamllint -s +run_check '.*\.ya?ml' yamllint -s -d "{extends: default, rules: {line-length: {allow-non-breakable-inline-mappings: true}}}" echo "ALL OK." From 6ae06714ac3fced9329c5c27c760c20af5e90853 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 15:02:59 -0500 Subject: [PATCH 09/15] Add GlusterNode skeleton Results of running: `operator-sdk add api --api-version=operator.gluster.org/v1alpha1 --kind=GlusterNode` and fixing yaml formatting Signed-off-by: John Strunk --- .../operator_v1alpha1_glusternode_cr.yaml | 8 ++ .../operator_v1alpha1_glusternode_crd.yaml | 14 +++ deploy/role.yaml | 1 + .../v1alpha1/zz_generated.deepcopy.go | 93 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 deploy/crds/operator_v1alpha1_glusternode_cr.yaml create mode 100644 deploy/crds/operator_v1alpha1_glusternode_crd.yaml diff --git a/deploy/crds/operator_v1alpha1_glusternode_cr.yaml b/deploy/crds/operator_v1alpha1_glusternode_cr.yaml new file mode 100644 index 0000000..4af6628 --- /dev/null +++ b/deploy/crds/operator_v1alpha1_glusternode_cr.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: operator.gluster.org/v1alpha1 +kind: GlusterNode +metadata: + name: example-glusternode +spec: + # Add fields here + size: 3 diff --git a/deploy/crds/operator_v1alpha1_glusternode_crd.yaml b/deploy/crds/operator_v1alpha1_glusternode_crd.yaml new file mode 100644 index 0000000..c91537c --- /dev/null +++ b/deploy/crds/operator_v1alpha1_glusternode_crd.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: glusternodes.operator.gluster.org +spec: + group: operator.gluster.org + names: + kind: GlusterNode + listKind: GlusterNodeList + plural: glusternodes + singular: glusternode + scope: Namespaced + version: v1alpha1 diff --git a/deploy/role.yaml b/deploy/role.yaml index d876d5c..254a1a1 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -37,5 +37,6 @@ rules: - operator.gluster.org resources: - '*' + - glusternodes verbs: - '*' diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go index ad985fd..e19e4e0 100644 --- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -116,3 +116,96 @@ func (in *GlusterClusterStatus) DeepCopy() *GlusterClusterStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterNode) DeepCopyInto(out *GlusterNode) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterNode. +func (in *GlusterNode) DeepCopy() *GlusterNode { + if in == nil { + return nil + } + out := new(GlusterNode) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GlusterNode) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterNodeList) DeepCopyInto(out *GlusterNodeList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GlusterNode, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterNodeList. +func (in *GlusterNodeList) DeepCopy() *GlusterNodeList { + if in == nil { + return nil + } + out := new(GlusterNodeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GlusterNodeList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterNodeSpec) DeepCopyInto(out *GlusterNodeSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterNodeSpec. +func (in *GlusterNodeSpec) DeepCopy() *GlusterNodeSpec { + if in == nil { + return nil + } + out := new(GlusterNodeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GlusterNodeStatus) DeepCopyInto(out *GlusterNodeStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterNodeStatus. +func (in *GlusterNodeStatus) DeepCopy() *GlusterNodeStatus { + if in == nil { + return nil + } + out := new(GlusterNodeStatus) + in.DeepCopyInto(out) + return out +} From 6a65c93290eccda9b46e0f4250988229c36e07fe Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 15:04:59 -0500 Subject: [PATCH 10/15] Add controller for GlusterNode Results of running: `operator-sdk add controller --api-version=operator.gluster.org/v1alpha1 --kind=GlusterNode` Signed-off-by: John Strunk --- .../operator/v1alpha1/glusternode_types.go | 45 ++++++ pkg/controller/add_glusternode.go | 10 ++ .../glusternode/glusternode_controller.go | 152 ++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 pkg/apis/operator/v1alpha1/glusternode_types.go create mode 100644 pkg/controller/add_glusternode.go create mode 100644 pkg/controller/glusternode/glusternode_controller.go diff --git a/pkg/apis/operator/v1alpha1/glusternode_types.go b/pkg/apis/operator/v1alpha1/glusternode_types.go new file mode 100644 index 0000000..b1db568 --- /dev/null +++ b/pkg/apis/operator/v1alpha1/glusternode_types.go @@ -0,0 +1,45 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// GlusterNodeSpec defines the desired state of GlusterNode +type GlusterNodeSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file +} + +// GlusterNodeStatus defines the observed state of GlusterNode +type GlusterNodeStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// GlusterNode is the Schema for the glusternodes API +// +k8s:openapi-gen=true +type GlusterNode struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GlusterNodeSpec `json:"spec,omitempty"` + Status GlusterNodeStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// GlusterNodeList contains a list of GlusterNode +type GlusterNodeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GlusterNode `json:"items"` +} + +func init() { + SchemeBuilder.Register(&GlusterNode{}, &GlusterNodeList{}) +} diff --git a/pkg/controller/add_glusternode.go b/pkg/controller/add_glusternode.go new file mode 100644 index 0000000..fb7f563 --- /dev/null +++ b/pkg/controller/add_glusternode.go @@ -0,0 +1,10 @@ +package controller + +import ( + "github.com/gluster/anthill/pkg/controller/glusternode" +) + +func init() { + // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. + AddToManagerFuncs = append(AddToManagerFuncs, glusternode.Add) +} diff --git a/pkg/controller/glusternode/glusternode_controller.go b/pkg/controller/glusternode/glusternode_controller.go new file mode 100644 index 0000000..7e906c3 --- /dev/null +++ b/pkg/controller/glusternode/glusternode_controller.go @@ -0,0 +1,152 @@ +package glusternode + +import ( + "context" + + operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +var log = logf.Log.WithName("controller_glusternode") + +/** +* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller +* business logic. Delete these comments after modifying this file.* + */ + +// Add creates a new GlusterNode Controller and adds it to the Manager. The Manager will set fields on the Controller +// and Start it when the Manager is Started. +func Add(mgr manager.Manager) error { + return add(mgr, newReconciler(mgr)) +} + +// newReconciler returns a new reconcile.Reconciler +func newReconciler(mgr manager.Manager) reconcile.Reconciler { + return &ReconcileGlusterNode{client: mgr.GetClient(), scheme: mgr.GetScheme()} +} + +// add adds a new Controller to mgr with r as the reconcile.Reconciler +func add(mgr manager.Manager, r reconcile.Reconciler) error { + // Create a new controller + c, err := controller.New("glusternode-controller", mgr, controller.Options{Reconciler: r}) + if err != nil { + return err + } + + // Watch for changes to primary resource GlusterNode + err = c.Watch(&source.Kind{Type: &operatorv1alpha1.GlusterNode{}}, &handler.EnqueueRequestForObject{}) + if err != nil { + return err + } + + // TODO(user): Modify this to be the types you create that are owned by the primary resource + // Watch for changes to secondary resource Pods and requeue the owner GlusterNode + err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &operatorv1alpha1.GlusterNode{}, + }) + if err != nil { + return err + } + + return nil +} + +var _ reconcile.Reconciler = &ReconcileGlusterNode{} + +// ReconcileGlusterNode reconciles a GlusterNode object +type ReconcileGlusterNode struct { + // This client, initialized using mgr.Client() above, is a split client + // that reads objects from the cache and writes to the apiserver + client client.Client + scheme *runtime.Scheme +} + +// Reconcile reads that state of the cluster for a GlusterNode object and makes changes based on the state read +// and what is in the GlusterNode.Spec +// TODO(user): Modify this Reconcile function to implement your Controller logic. This example creates +// a Pod as an example +// Note: +// The Controller will requeue the Request to be processed again if the returned error is non-nil or +// Result.Requeue is true, otherwise upon completion it will remove the work from the queue. +func (r *ReconcileGlusterNode) Reconcile(request reconcile.Request) (reconcile.Result, error) { + reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) + reqLogger.Info("Reconciling GlusterNode") + + // Fetch the GlusterNode instance + instance := &operatorv1alpha1.GlusterNode{} + err := r.client.Get(context.TODO(), request.NamespacedName, instance) + if err != nil { + if errors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + return reconcile.Result{}, nil + } + // Error reading the object - requeue the request. + return reconcile.Result{}, err + } + + // Define a new Pod object + pod := newPodForCR(instance) + + // Set GlusterNode instance as the owner and controller + if err := controllerutil.SetControllerReference(instance, pod, r.scheme); err != nil { + return reconcile.Result{}, err + } + + // Check if this Pod already exists + found := &corev1.Pod{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: pod.Name, Namespace: pod.Namespace}, found) + if err != nil && errors.IsNotFound(err) { + reqLogger.Info("Creating a new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name) + err = r.client.Create(context.TODO(), pod) + if err != nil { + return reconcile.Result{}, err + } + + // Pod created successfully - don't requeue + return reconcile.Result{}, nil + } else if err != nil { + return reconcile.Result{}, err + } + + // Pod already exists - don't requeue + reqLogger.Info("Skip reconcile: Pod already exists", "Pod.Namespace", found.Namespace, "Pod.Name", found.Name) + return reconcile.Result{}, nil +} + +// newPodForCR returns a busybox pod with the same name/namespace as the cr +func newPodForCR(cr *operatorv1alpha1.GlusterNode) *corev1.Pod { + labels := map[string]string{ + "app": cr.Name, + } + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: cr.Name + "-pod", + Namespace: cr.Namespace, + Labels: labels, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "busybox", + Image: "busybox", + Command: []string{"sleep", "3600"}, + }, + }, + }, + } +} From d14e508ed63c6cb327ad2aa663cea4f86811390c Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 16 Nov 2018 17:13:03 -0500 Subject: [PATCH 11/15] Add note to run `dep ensure` Signed-off-by: John Strunk --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b080a77..95967de 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ here.](https://github.com/operator-framework/operator-sdk#quick-start) Once the SDK is installed, Anthill can be built via: ```bash +$ dep ensure + $ operator-sdk build docker.io/gluster/anthill INFO[0001] Building Docker image docker.io/gluster/anthill Sending build context to Docker daemon 114.7MB From b1ae847768d311c2d6b865aad556025bd46c24a2 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 30 Nov 2018 11:03:41 -0500 Subject: [PATCH 12/15] Switch container to use CentOS base image Signed-off-by: John Strunk --- README.md | 25 +++++++++++++------------ build/Dockerfile | 4 +--- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 95967de..4db4a2f 100644 --- a/README.md +++ b/README.md @@ -24,20 +24,21 @@ Once the SDK is installed, Anthill can be built via: $ dep ensure $ operator-sdk build docker.io/gluster/anthill -INFO[0001] Building Docker image docker.io/gluster/anthill -Sending build context to Docker daemon 114.7MB -Step 1/4 : FROM alpine:3.8 - ---> 196d12cf6ab1 -Step 2/4 : RUN apk upgrade --update --no-cache - ---> Using cache - ---> 6a5bb76fe272 -Step 3/4 : USER nobody +$ operator-sdk build docker.io/gluster/anthill +INFO[0000] Building Docker image docker.io/gluster/anthill +Sending build context to Docker daemon 152.1MB +Step 1/3 : FROM docker.io/centos:7.5.1804 +7.5.1804: Pulling from library/centos +Digest: sha256:adbf1369c8dbeaa2bf9df0b891394e3ca09b5272a2fb54e0fadc6b14dd93fcad +Status: Downloaded newer image for centos:7.5.1804 + ---> 76d6bc25b8a5 +Step 2/3 : USER nobody ---> Using cache - ---> faf8acce50e4 -Step 4/4 : ADD build/_output/bin/anthill /usr/local/bin/anthill + ---> dc1dd738f9a4 +Step 3/3 : ADD build/_output/bin/anthill /usr/local/bin/anthill ---> Using cache - ---> b404638145da -Successfully built b404638145da + ---> cffc3a0ef59e +Successfully built cffc3a0ef59e Successfully tagged gluster/anthill:latest INFO[0002] Operator build complete. ``` diff --git a/build/Dockerfile b/build/Dockerfile index de5325f..f5ae1fc 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,6 +1,4 @@ -FROM alpine:3.8 - -RUN apk upgrade --update --no-cache +FROM docker.io/centos:7.5.1804 USER nobody From dc62a9bea9800dcb73777e93bf82ed454f39dac0 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 30 Nov 2018 11:06:09 -0500 Subject: [PATCH 13/15] Merge operator role & rolebinding Signed-off-by: John Strunk --- README.md | 2 -- deploy/role.yaml | 14 ++++++++++++++ deploy/role_binding.yaml | 12 ------------ 3 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 deploy/role_binding.yaml diff --git a/README.md b/README.md index 4db4a2f..da6c771 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,6 @@ serviceaccount "anthill" created $ kubectl apply -f deploy/role.yaml role.rbac.authorization.k8s.io "anthill" created - -$ kubectl apply -f deploy/role_binding.yaml rolebinding.rbac.authorization.k8s.io "anthill" created ``` diff --git a/deploy/role.yaml b/deploy/role.yaml index 254a1a1..b07aec4 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -40,3 +40,17 @@ rules: - glusternodes verbs: - '*' + +--- + +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: anthill +subjects: + - kind: ServiceAccount + name: anthill +roleRef: + kind: Role + name: anthill + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/role_binding.yaml b/deploy/role_binding.yaml deleted file mode 100644 index f498f71..0000000 --- a/deploy/role_binding.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: anthill -subjects: - - kind: ServiceAccount - name: anthill -roleRef: - kind: Role - name: anthill - apiGroup: rbac.authorization.k8s.io From 63b0ad723f6cb8f48d329508f95e192d3f58107a Mon Sep 17 00:00:00 2001 From: John Strunk Date: Fri, 30 Nov 2018 11:17:49 -0500 Subject: [PATCH 14/15] Reorder imports for style Signed-off-by: John Strunk --- cmd/manager/main.go | 5 +++-- pkg/controller/glustercluster/glustercluster_controller.go | 3 ++- pkg/controller/glusternode/glusternode_controller.go | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 6d69f02..3e8e2a0 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -6,8 +6,6 @@ import ( "os" "runtime" - "github.com/gluster/anthill/pkg/apis" - "github.com/gluster/anthill/pkg/controller" "github.com/operator-framework/operator-sdk/pkg/k8sutil" sdkVersion "github.com/operator-framework/operator-sdk/version" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" @@ -15,6 +13,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" "sigs.k8s.io/controller-runtime/pkg/runtime/signals" + + "github.com/gluster/anthill/pkg/apis" + "github.com/gluster/anthill/pkg/controller" ) func printVersion() { diff --git a/pkg/controller/glustercluster/glustercluster_controller.go b/pkg/controller/glustercluster/glustercluster_controller.go index 3c788d1..4480d69 100644 --- a/pkg/controller/glustercluster/glustercluster_controller.go +++ b/pkg/controller/glustercluster/glustercluster_controller.go @@ -3,7 +3,6 @@ package glustercluster import ( "context" - operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,6 +16,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" "sigs.k8s.io/controller-runtime/pkg/source" + + operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" ) var log = logf.Log.WithName("controller_glustercluster") diff --git a/pkg/controller/glusternode/glusternode_controller.go b/pkg/controller/glusternode/glusternode_controller.go index 7e906c3..8bb2105 100644 --- a/pkg/controller/glusternode/glusternode_controller.go +++ b/pkg/controller/glusternode/glusternode_controller.go @@ -3,7 +3,6 @@ package glusternode import ( "context" - operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,6 +16,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" "sigs.k8s.io/controller-runtime/pkg/source" + + operatorv1alpha1 "github.com/gluster/anthill/pkg/apis/operator/v1alpha1" ) var log = logf.Log.WithName("controller_glusternode") From ee8bcfe3bbeff3a1076af2b6ebae519bb58d9365 Mon Sep 17 00:00:00 2001 From: John Strunk Date: Mon, 3 Dec 2018 14:58:47 -0500 Subject: [PATCH 15/15] Remove whitespace in role yaml Signed-off-by: John Strunk --- deploy/role.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/role.yaml b/deploy/role.yaml index b07aec4..2e60efa 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -42,7 +42,6 @@ rules: - '*' --- - kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: