Install base plugins
This commit is contained in:
parent
f3093cdbbc
commit
af9f7f4e76
|
|
@ -2,250 +2,323 @@
|
|||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8713dd3229c46881bb56b24fa3b581a0faab01d12e2d973a830965c24061e449"
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
pruneopts = "NT"
|
||||
revision = "1fd54cf41e6e0e178ffe3c52b0e2260281f603e3"
|
||||
version = "v0.32.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:75d2b55b13298745ec068057251d05d65bbae0a668201fe45ad6986551a55601"
|
||||
name = "github.com/BurntSushi/toml"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
|
||||
version = "v0.3.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:8d13c70d5898b091728540686c696baee0d64013b8e43089da80621a49410391"
|
||||
name = "github.com/bndr/gojenkins"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "de43c03cf849dd63a9737df6e05791c7a176c93d"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4b8b5811da6970495e04d1f4e98bb89518cc3cfc3b3f456bdb876ed7b6c74049"
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
pruneopts = "NT"
|
||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:707c9f4ee70cc3bb941cf5803d9b8e725bc02277a96301ac8e537510a712ec7c"
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digest",
|
||||
"reference"
|
||||
"reference",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
|
||||
version = "v2.6.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e6f888d4be8ec0f05c50e2aba83da4948b58045dee54d03be81fa74ea673302c"
|
||||
name = "github.com/emicklei/go-restful"
|
||||
packages = [
|
||||
".",
|
||||
"log"
|
||||
"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]]
|
||||
branch = "master"
|
||||
digest = "1:dfab391de021809e0041f0ab5648da6b74dd16a685472a1b8c3dc06b3dca1ee2"
|
||||
name = "github.com/go-openapi/spec"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "5bae59e25b21498baea7f9d46e9c147ec106a42e"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:983f95b2fae6fe8fdd361738325ed6090f4f3bd15ce4db745e899fb5b0fdfc46"
|
||||
name = "github.com/go-openapi/swag"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "5899d5c5e619fda5fa86e14795a835f473ca284c"
|
||||
version = "v0.17.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4fb6ac9e2e67130ed8c5db4154684b390c1c0ce213ba3f4532b7edc614f78999"
|
||||
name = "github.com/gobuffalo/envy"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "801d7253ade1f895f74596b9a96147ed2d3b087e"
|
||||
version = "v1.6.11"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2a9d5e367df8c95e780975ca1dd4010bef8e39a3777066d3880ce274b39d4b5a"
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"sortkeys"
|
||||
"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"
|
||||
"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"
|
||||
"extensions",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "7c663266750e7d82587642f65e60bc4083f1f84e"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:2a2caa63899dae26ed3e4510b806549fd416d94db24ad68279daa62881b26488"
|
||||
name = "github.com/gregjones/httpcache"
|
||||
packages = [
|
||||
".",
|
||||
"diskcache"
|
||||
"diskcache",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "9cad4c3443a7200dd6400aef47183728de563a38"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b42cde0e1f3c816dd57f57f7bbcf05ca40263ad96f168714c130c611fc0856a6"
|
||||
name = "github.com/hashicorp/golang-lru"
|
||||
packages = [
|
||||
".",
|
||||
"simplelru"
|
||||
"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:f5b9328966ccea0970b1d15075698eff0ddb3e75889560aad2e9f76b289b536a"
|
||||
name = "github.com/joho/godotenv"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "23d116af351c84513e1946b527c88823e476be13"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1d39c063244ad17c4b18e8da1551163b6ffb52bd1640a49a8ec5c3b7bf4dbd5d"
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "1624edc4454b8682399def8740d46db5e4362ba4"
|
||||
version = "v1.1.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4059c14e87a2de3a434430340521b5feece186c1469eff0834c29a63870de3ed"
|
||||
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:7d9fcac7f1228470c4ea0ee31cdfb662a758c44df691e39b3e76c11d3e12ba8f"
|
||||
name = "github.com/mailru/easyjson"
|
||||
packages = [
|
||||
"buffer",
|
||||
"jlexer",
|
||||
"jwriter"
|
||||
"jwriter",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "60711f1a8329503b04e1c88535f419d0bb440bff"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:56dbf15e091bf7926cb33a57cb6bdfc658fc6d3498d2f76f10a97ce7856f1fde"
|
||||
name = "github.com/markbates/inflect"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "24b83195037b3bc61fcda2d28b7b0518bce293b6"
|
||||
version = "v1.0.4"
|
||||
|
||||
[[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]]
|
||||
digest = "1:f3f95a7e55bd970e2d59af0131202401493016a7a90978cd1c4b7137d128bc1a"
|
||||
name = "github.com/mrtazz/checkmake"
|
||||
packages = ["logger"]
|
||||
pruneopts = "NT"
|
||||
revision = "53de3e70f28d26a6450a845505c43165cb150b72"
|
||||
version = "0.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:121b82bf82f859edc43cc6ce42df4e231881874f576e48ba75b062fb1a2efc80"
|
||||
name = "github.com/operator-framework/operator-sdk"
|
||||
packages = [
|
||||
"internal/util/fileutil",
|
||||
|
|
@ -257,79 +330,109 @@
|
|||
"pkg/scaffold/input",
|
||||
"pkg/test",
|
||||
"pkg/test/e2eutil",
|
||||
"version"
|
||||
"version",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "175a82edae514f57f597110af5447d3f9b1c0fc3"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[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:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
pruneopts = "NT"
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:4e63570205b765959739e2ef37add1d229cab7dbf70d80341a0608816120493b"
|
||||
name = "github.com/rogpeppe/go-internal"
|
||||
packages = [
|
||||
"modfile",
|
||||
"module",
|
||||
"semver"
|
||||
"semver",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "d87f08a7d80821c797ffc8eb8f4e01675f378736"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:cd2f2cba5b7ffafd0412fb647ff4bcff170292de57270f05fbbf391e3eb9566b"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2a7c79c506479dc73c0100982a40bacc89e06d96dc458eb41c9b6aa44d9e0b6d"
|
||||
name = "github.com/spf13/afero"
|
||||
packages = [
|
||||
".",
|
||||
"mem"
|
||||
"mem",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd"
|
||||
version = "v1.1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
pruneopts = "NT"
|
||||
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||
version = "v1.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/sqs/goreturns"
|
||||
packages = ["returns"]
|
||||
revision = "538ac601451833c7c4449f8431d65d53c1c60e41"
|
||||
digest = "1:4af061277c04a7660e082acc2020f4c66d2c21dfc62e0242ffa1d2120cdfb4ec"
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert"]
|
||||
pruneopts = "NT"
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[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 = [
|
||||
".",
|
||||
|
|
@ -337,19 +440,23 @@
|
|||
"internal/bufferpool",
|
||||
"internal/color",
|
||||
"internal/exit",
|
||||
"zapcore"
|
||||
"zapcore",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982"
|
||||
version = "v1.9.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:47924c7ab4b3a18145d150e535525f582a07511e5452c4e1a5b79d883c2a429f"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
pruneopts = "NT"
|
||||
revision = "4d3f4d9ffa16a13f451c3b2999e9c49e9750bf06"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:a7fcf4f3e5247a06ad4c28108f0bc1d4ab980a1a0567e7790260cf2d3d77f37d"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
|
|
@ -359,32 +466,38 @@
|
|||
"http/httpguts",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna"
|
||||
"idna",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "c10e9556a7bc0e7c942242b606f0acf024ad5d6a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:b17011812136abe011d81b40b30470808df923687e831760511d878408d208df"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"google",
|
||||
"internal",
|
||||
"jws",
|
||||
"jwt"
|
||||
"jwt",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "e0f2c55a7fc7d04742e0eef7918aa2389b0e1919"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:04b92b5bc6c1031cc9083fbc2fdeda90f3a69b7c1bf5eed6bbf9a3563d946c6e"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
"windows",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "9b800f95dbbc54abff0acf7ee32d88ba4e328c89"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8c74f97396ed63cc2ef04ebb5fc37bb032871b8fd890a25991ed40974b00cd2a"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
|
|
@ -401,29 +514,35 @@
|
|||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable",
|
||||
"width"
|
||||
"width",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:c9e7a4b4d47c0ed205d257648b0e5b0440880cb728506e318f8ac7cd36270bc4"
|
||||
name = "golang.org/x/time"
|
||||
packages = ["rate"]
|
||||
pruneopts = "NT"
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:d9646d2cb3517e532bcc75614352e589c5f26e6d1b8ae2587eaef0c7c60cea3a"
|
||||
name = "golang.org/x/tools"
|
||||
packages = [
|
||||
"go/ast/astutil",
|
||||
"imports",
|
||||
"internal/fastwalk",
|
||||
"internal/gopathwalk"
|
||||
"internal/gopathwalk",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "92b943e6bff73e0dfe9e975d94043d8f31067b06"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2a4972ee51c3b9dfafbb3451fa0552e7a198d9d12c721bfc492050fe2f72e0f6"
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
".",
|
||||
|
|
@ -435,24 +554,30 @@
|
|||
"internal/modules",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"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",
|
||||
|
|
@ -484,20 +609,24 @@
|
|||
"settings/v1alpha1",
|
||||
"storage/v1",
|
||||
"storage/v1alpha1",
|
||||
"storage/v1beta1"
|
||||
"storage/v1beta1",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "2d6f90ab1293a1fb871cf149423ebb72aa7423aa"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:117a407949aaaad9f7fbe3da8d6c2055f2c223ac0cbebd39f47ff71899622a91"
|
||||
name = "k8s.io/apiextensions-apiserver"
|
||||
packages = [
|
||||
"pkg/apis/apiextensions",
|
||||
"pkg/apis/apiextensions/v1beta1",
|
||||
"pkg/client/clientset/clientset/scheme"
|
||||
"pkg/client/clientset/clientset/scheme",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "408db4a50408e2149acbd657bceb2480c13cb0a4"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b07bf863262aae765494d60f0d524483f211b29f9bb27d445a79c13af8676bf2"
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = [
|
||||
"pkg/api/errors",
|
||||
|
|
@ -541,11 +670,13 @@
|
|||
"pkg/version",
|
||||
"pkg/watch",
|
||||
"third_party/forked/golang/json",
|
||||
"third_party/forked/golang/reflect"
|
||||
"third_party/forked/golang/reflect",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1689a49a3ebc6e379849181f1e0899fccf143cab47586078721818bdcdb712bc"
|
||||
name = "k8s.io/client-go"
|
||||
packages = [
|
||||
"discovery",
|
||||
|
|
@ -613,11 +744,13 @@
|
|||
"util/integer",
|
||||
"util/jsonpath",
|
||||
"util/retry",
|
||||
"util/workqueue"
|
||||
"util/workqueue",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "1f13a808da65775f22cbf47862c4e5898d8f4ca1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8ab487a323486c8bbbaa3b689850487fdccc6cbea8690620e083b2d230a4447e"
|
||||
name = "k8s.io/code-generator"
|
||||
packages = [
|
||||
"cmd/client-gen",
|
||||
|
|
@ -643,12 +776,14 @@
|
|||
"cmd/lister-gen/generators",
|
||||
"cmd/openapi-gen",
|
||||
"cmd/openapi-gen/args",
|
||||
"pkg/util"
|
||||
"pkg/util",
|
||||
]
|
||||
pruneopts = "T"
|
||||
revision = "6702109cc68eb6fe6350b83e14407c8d7309fd1a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:c84b5ef38d786290246a9cc791a48b6ed890cd32468179a51a91492161ec6d65"
|
||||
name = "k8s.io/gengo"
|
||||
packages = [
|
||||
"args",
|
||||
|
|
@ -658,11 +793,13 @@
|
|||
"generator",
|
||||
"namer",
|
||||
"parser",
|
||||
"types"
|
||||
"types",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "7338e4bfd6915369a1375890db1bbda0158c9863"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c48a795cd7048bb1888273bc604b6e69b22f9b8089c3df65f77cc527757b515c"
|
||||
name = "k8s.io/kube-openapi"
|
||||
packages = [
|
||||
"cmd/openapi-gen/args",
|
||||
|
|
@ -670,11 +807,13 @@
|
|||
"pkg/generators",
|
||||
"pkg/generators/rules",
|
||||
"pkg/util/proto",
|
||||
"pkg/util/sets"
|
||||
"pkg/util/sets",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:d1b7a6ed45c957e6308759f31fdbff8063741ecb08b7c3b6d67f0c9f4357b2ae"
|
||||
name = "sigs.k8s.io/controller-runtime"
|
||||
packages = [
|
||||
"pkg/cache",
|
||||
|
|
@ -702,14 +841,57 @@
|
|||
"pkg/source/internal",
|
||||
"pkg/webhook/admission",
|
||||
"pkg/webhook/admission/types",
|
||||
"pkg/webhook/types"
|
||||
"pkg/webhook/types",
|
||||
]
|
||||
pruneopts = "NT"
|
||||
revision = "5fd1e9e9fac5261e9ad9d47c375afc014fc31d21"
|
||||
version = "v0.1.7"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "a223e91cda589ee8ba60969192795e2139d96b046d4aecc35338a4d60e116f61"
|
||||
input-imports = [
|
||||
"github.com/bndr/gojenkins",
|
||||
"github.com/docker/distribution/reference",
|
||||
"github.com/go-logr/logr",
|
||||
"github.com/mrtazz/checkmake/logger",
|
||||
"github.com/operator-framework/operator-sdk/pkg/k8sutil",
|
||||
"github.com/operator-framework/operator-sdk/pkg/leader",
|
||||
"github.com/operator-framework/operator-sdk/pkg/ready",
|
||||
"github.com/operator-framework/operator-sdk/pkg/test",
|
||||
"github.com/operator-framework/operator-sdk/pkg/test/e2eutil",
|
||||
"github.com/operator-framework/operator-sdk/version",
|
||||
"github.com/stretchr/testify/assert",
|
||||
"k8s.io/api/core/v1",
|
||||
"k8s.io/apimachinery/pkg/api/errors",
|
||||
"k8s.io/apimachinery/pkg/api/resource",
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"k8s.io/apimachinery/pkg/labels",
|
||||
"k8s.io/apimachinery/pkg/runtime",
|
||||
"k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"k8s.io/apimachinery/pkg/types",
|
||||
"k8s.io/apimachinery/pkg/util/intstr",
|
||||
"k8s.io/apimachinery/pkg/util/wait",
|
||||
"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",
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config",
|
||||
"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",
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/log",
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme",
|
||||
"sigs.k8s.io/controller-runtime/pkg/runtime/signals",
|
||||
"sigs.k8s.io/controller-runtime/pkg/source",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ spec:
|
|||
containers:
|
||||
- name: jenkins-operator
|
||||
# Replace this with the built image name
|
||||
image: jenkins-operator
|
||||
image: REPLACE_IMAGE
|
||||
ports:
|
||||
- containerPort: 60000
|
||||
name: metrics
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ type JenkinsSpec struct {
|
|||
SeedJobs []SeedJob `json:"seedJobs,omitempty"`
|
||||
}
|
||||
|
||||
// JenkinsMaster defines the Jenkins master pod attributes
|
||||
// JenkinsMaster defines the Jenkins master pod attributes and plugins,
|
||||
// every single change requires Jenkins master pod restart
|
||||
type JenkinsMaster struct {
|
||||
Image string `json:"image,omitempty"`
|
||||
Annotations map[string]string `json:"masterAnnotations,omitempty"`
|
||||
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
Plugins map[string][]string `json:"plugins,omitempty"`
|
||||
}
|
||||
|
||||
// JenkinsStatus defines the observed state of Jenkins
|
||||
|
|
|
|||
|
|
@ -97,6 +97,21 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
|
|||
}
|
||||
}
|
||||
in.Resources.DeepCopyInto(&out.Resources)
|
||||
if in.Plugins != nil {
|
||||
in, out := &in.Plugins, &out.Plugins
|
||||
*out = make(map[string][]string, len(*in))
|
||||
for key, val := range *in {
|
||||
var outVal []string
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
in, out := &val, &outVal
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
(*out)[key] = outVal
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ import (
|
|||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
"github.com/bndr/gojenkins"
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
|
@ -22,6 +24,10 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
)
|
||||
|
||||
const (
|
||||
fetchAllPlugins = 1
|
||||
)
|
||||
|
||||
// ReconcileJenkinsBaseConfiguration defines values required for Jenkins base configuration
|
||||
type ReconcileJenkinsBaseConfiguration struct {
|
||||
client client.Client
|
||||
|
|
@ -46,11 +52,6 @@ func New(client client.Client, scheme *runtime.Scheme, logger logr.Logger,
|
|||
|
||||
// Reconcile takes care of base configuration
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, jenkinsclient.Jenkins, error) {
|
||||
if !r.validate(r.jenkins) {
|
||||
r.logger.V(log.VWarn).Info("Please correct Jenkins CR")
|
||||
return &reconcile.Result{}, nil, nil
|
||||
}
|
||||
|
||||
metaObject := resources.NewResourceObjectMeta(r.jenkins)
|
||||
|
||||
if err := r.createOperatorCredentialsSecret(metaObject); err != nil {
|
||||
|
|
@ -97,9 +98,65 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, jenk
|
|||
}
|
||||
r.logger.V(log.VDebug).Info("Jenkins API client set")
|
||||
|
||||
ok, err := r.verifyBasePlugins(jenkinsClient)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
if !ok {
|
||||
r.logger.V(log.VWarn).Info("Please correct Jenkins CR (spec.master.plugins)")
|
||||
currentJenkinsMasterPod, err := r.getJenkinsMasterPod(metaObject)
|
||||
if err != nil {
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
if err := r.client.Delete(context.TODO(), currentJenkinsMasterPod); err != nil {
|
||||
return &reconcile.Result{}, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, jenkinsClient, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
||||
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var installedPlugins []string
|
||||
for _, jenkinsPlugin := range allPluginsInJenkins.Raw.Plugins {
|
||||
if !jenkinsPlugin.Deleted {
|
||||
installedPlugins = append(installedPlugins, plugin.Plugin{Name: jenkinsPlugin.ShortName, Version: jenkinsPlugin.Version}.String())
|
||||
}
|
||||
}
|
||||
r.logger.V(log.VDebug).Info(fmt.Sprintf("Installed plugins '%+v'", installedPlugins))
|
||||
|
||||
status := true
|
||||
for rootPluginName, p := range plugin.BasePluginsMap {
|
||||
rootPlugin, _ := plugin.New(rootPluginName)
|
||||
if found, ok := isPluginInstalled(allPluginsInJenkins, *rootPlugin); !ok {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Missing plugin '%s', actual '%+v'", rootPlugin, found))
|
||||
status = false
|
||||
}
|
||||
for _, requiredPlugin := range p {
|
||||
if found, ok := isPluginInstalled(allPluginsInJenkins, requiredPlugin); !ok {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Missing plugin '%s', actual '%+v'", requiredPlugin, found))
|
||||
status = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func isPluginInstalled(plugins *gojenkins.Plugins, requiredPlugin plugin.Plugin) (gojenkins.Plugin, bool) {
|
||||
p := plugins.Contains(requiredPlugin.Name)
|
||||
if p == nil {
|
||||
return gojenkins.Plugin{}, false
|
||||
}
|
||||
|
||||
return *p, p.Active && p.Enabled && !p.Deleted
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta metav1.ObjectMeta) error {
|
||||
found := &corev1.Secret{}
|
||||
err := r.client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, found)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,234 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const installPluginsCommand = "install-plugins.sh"
|
||||
|
||||
// bash scripts installs single jenkins plugin with concrete version
|
||||
const installPluginsBashFmt = `#!/bin/bash -eu
|
||||
|
||||
# Resolve dependencies and download plugins given on the command line
|
||||
#
|
||||
# FROM jenkins
|
||||
# RUN install-plugins.sh docker-slaves github-branch-source
|
||||
|
||||
set -o pipefail
|
||||
|
||||
REF_DIR=${REF:-%s/plugins}
|
||||
FAILED="$REF_DIR/failed-plugins.txt"
|
||||
|
||||
. /usr/local/bin/jenkins-support
|
||||
|
||||
getLockFile() {
|
||||
printf '%%s' "$REF_DIR/${1}.lock"
|
||||
}
|
||||
|
||||
getArchiveFilename() {
|
||||
printf '%%s' "$REF_DIR/${1}.jpi"
|
||||
}
|
||||
|
||||
download() {
|
||||
local plugin originalPlugin version lock ignoreLockFile
|
||||
plugin="$1"
|
||||
version="${2:-latest}"
|
||||
ignoreLockFile="${3:-}"
|
||||
lock="$(getLockFile "$plugin")"
|
||||
|
||||
if [[ $ignoreLockFile ]] || mkdir "$lock" &>/dev/null; then
|
||||
if ! doDownload "$plugin" "$version"; then
|
||||
# some plugin don't follow the rules about artifact ID
|
||||
# typically: docker-plugin
|
||||
originalPlugin="$plugin"
|
||||
plugin="${plugin}-plugin"
|
||||
if ! doDownload "$plugin" "$version"; then
|
||||
echo "Failed to download plugin: $originalPlugin or $plugin" >&2
|
||||
echo "Not downloaded: ${originalPlugin}" >> "$FAILED"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! checkIntegrity "$plugin"; then
|
||||
echo "Downloaded file is not a valid ZIP: $(getArchiveFilename "$plugin")" >&2
|
||||
echo "Download integrity: ${plugin}" >> "$FAILED"
|
||||
return 1
|
||||
fi
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
doDownload() {
|
||||
local plugin version url jpi
|
||||
plugin="$1"
|
||||
version="$2"
|
||||
jpi="$(getArchiveFilename "$plugin")"
|
||||
|
||||
# If plugin already exists and is the same version do not download
|
||||
if test -f "$jpi" && unzip -p "$jpi" META-INF/MANIFEST.MF | tr -d '\r' | grep "^Plugin-Version: ${version}$" > /dev/null; then
|
||||
echo "Using provided plugin: $plugin"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$version" == "latest" && -n "$JENKINS_UC_LATEST" ]]; then
|
||||
# If version-specific Update Center is available, which is the case for LTS versions,
|
||||
# use it to resolve latest versions.
|
||||
url="$JENKINS_UC_LATEST/latest/${plugin}.hpi"
|
||||
elif [[ "$version" == "experimental" && -n "$JENKINS_UC_EXPERIMENTAL" ]]; then
|
||||
# Download from the experimental update center
|
||||
url="$JENKINS_UC_EXPERIMENTAL/latest/${plugin}.hpi"
|
||||
elif [[ "$version" == incrementals* ]] ; then
|
||||
# Download from Incrementals repo: https://jenkins.io/blog/2018/05/15/incremental-deployment/
|
||||
# Example URL: https://repo.jenkins-ci.org/incrementals/org/jenkins-ci/plugins/workflow/workflow-support/2.19-rc289.d09828a05a74/workflow-support-2.19-rc289.d09828a05a74.hpi
|
||||
local groupId incrementalsVersion
|
||||
arrIN=(${version//;/ })
|
||||
groupId=${arrIN[1]}
|
||||
incrementalsVersion=${arrIN[2]}
|
||||
url="${JENKINS_INCREMENTALS_REPO_MIRROR}/$(echo "${groupId}" | tr '.' '/')/${plugin}/${incrementalsVersion}/${plugin}-${incrementalsVersion}.hpi"
|
||||
else
|
||||
JENKINS_UC_DOWNLOAD=${JENKINS_UC_DOWNLOAD:-"$JENKINS_UC/download"}
|
||||
url="$JENKINS_UC_DOWNLOAD/plugins/$plugin/$version/${plugin}.hpi"
|
||||
fi
|
||||
|
||||
echo "Downloading plugin: $plugin from $url"
|
||||
retry_command curl "${CURL_OPTIONS:--sSfL}" --connect-timeout "${CURL_CONNECTION_TIMEOUT:-20}" --retry "${CURL_RETRY:-5}" --retry-delay "${CURL_RETRY_DELAY:-0}" --retry-max-time "${CURL_RETRY_MAX_TIME:-60}" "$url" -o "$jpi"
|
||||
return $?
|
||||
}
|
||||
|
||||
checkIntegrity() {
|
||||
local plugin jpi
|
||||
plugin="$1"
|
||||
jpi="$(getArchiveFilename "$plugin")"
|
||||
|
||||
unzip -t -qq "$jpi" >/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
bundledPlugins() {
|
||||
local JENKINS_WAR=/usr/share/jenkins/jenkins.war
|
||||
if [ -f $JENKINS_WAR ]
|
||||
then
|
||||
TEMP_PLUGIN_DIR=/tmp/plugintemp.$$
|
||||
for i in $(jar tf $JENKINS_WAR | grep -E '[^detached-]plugins.*\..pi' | sort)
|
||||
do
|
||||
rm -fr $TEMP_PLUGIN_DIR
|
||||
mkdir -p $TEMP_PLUGIN_DIR
|
||||
PLUGIN=$(basename "$i"|cut -f1 -d'.')
|
||||
(cd $TEMP_PLUGIN_DIR;jar xf "$JENKINS_WAR" "$i";jar xvf "$TEMP_PLUGIN_DIR/$i" META-INF/MANIFEST.MF >/dev/null 2>&1)
|
||||
VER=$(grep -E -i Plugin-Version "$TEMP_PLUGIN_DIR/META-INF/MANIFEST.MF"|cut -d: -f2|sed 's/ //')
|
||||
echo "$PLUGIN:$VER"
|
||||
done
|
||||
rm -fr $TEMP_PLUGIN_DIR
|
||||
else
|
||||
rm -f "$TEMP_ALREADY_INSTALLED"
|
||||
echo "ERROR file not found: $JENKINS_WAR"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
versionFromPlugin() {
|
||||
local plugin=$1
|
||||
if [[ $plugin =~ .*:.* ]]; then
|
||||
echo "${plugin##*:}"
|
||||
else
|
||||
echo "latest"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
installedPlugins() {
|
||||
for f in "$REF_DIR"/*.jpi; do
|
||||
echo "$(basename "$f" | sed -e 's/\.jpi//'):$(get_plugin_version "$f")"
|
||||
done
|
||||
}
|
||||
|
||||
jenkinsMajorMinorVersion() {
|
||||
local JENKINS_WAR
|
||||
JENKINS_WAR=/usr/share/jenkins/jenkins.war
|
||||
if [[ -f "$JENKINS_WAR" ]]; then
|
||||
local version major minor
|
||||
version="$(java -jar /usr/share/jenkins/jenkins.war --version)"
|
||||
major="$(echo "$version" | cut -d '.' -f 1)"
|
||||
minor="$(echo "$version" | cut -d '.' -f 2)"
|
||||
echo "$major.$minor"
|
||||
else
|
||||
echo "ERROR file not found: $JENKINS_WAR"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
local plugin pluginVersion jenkinsVersion
|
||||
local plugins=()
|
||||
|
||||
mkdir -p "$REF_DIR" || exit 1
|
||||
rm -f "$FAILED"
|
||||
|
||||
# Read plugins from stdin or from the command line arguments
|
||||
if [[ ($# -eq 0) ]]; then
|
||||
while read -r line || [ "$line" != "" ]; do
|
||||
# Remove leading/trailing spaces, comments, and empty lines
|
||||
plugin=$(echo "${line}" | tr -d '\r' | sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' -e 's/[ \t]*#.*$//g' -e '/^[ \t]*$/d')
|
||||
|
||||
# Avoid adding empty plugin into array
|
||||
if [ ${#plugin} -ne 0 ]; then
|
||||
plugins+=("${plugin}")
|
||||
fi
|
||||
done
|
||||
else
|
||||
plugins=("$@")
|
||||
fi
|
||||
|
||||
# Create lockfile manually before first run to make sure any explicit version set is used.
|
||||
echo "Creating initial locks..."
|
||||
for plugin in "${plugins[@]}"; do
|
||||
mkdir "$(getLockFile "${plugin%%:*}")"
|
||||
done
|
||||
|
||||
echo "Analyzing war..."
|
||||
bundledPlugins="$(bundledPlugins)"
|
||||
|
||||
echo "Registering preinstalled plugins..."
|
||||
installedPlugins="$(installedPlugins)"
|
||||
|
||||
# Check if there's a version-specific update center, which is the case for LTS versions
|
||||
jenkinsVersion="$(jenkinsMajorMinorVersion)"
|
||||
if curl -fsL -o /dev/null "$JENKINS_UC/$jenkinsVersion"; then
|
||||
JENKINS_UC_LATEST="$JENKINS_UC/$jenkinsVersion"
|
||||
echo "Using version-specific update center: $JENKINS_UC_LATEST..."
|
||||
else
|
||||
JENKINS_UC_LATEST=
|
||||
fi
|
||||
|
||||
echo "Downloading plugins..."
|
||||
for plugin in "${plugins[@]}"; do
|
||||
pluginVersion=""
|
||||
|
||||
if [[ $plugin =~ .*:.* ]]; then
|
||||
pluginVersion=$(versionFromPlugin "${plugin}")
|
||||
plugin="${plugin%%:*}"
|
||||
fi
|
||||
|
||||
download "$plugin" "$pluginVersion" "true" &
|
||||
done
|
||||
wait
|
||||
|
||||
echo
|
||||
echo "WAR bundled plugins:"
|
||||
echo "${bundledPlugins}"
|
||||
echo
|
||||
echo "Installed plugins:"
|
||||
installedPlugins
|
||||
|
||||
if [[ -f $FAILED ]]; then
|
||||
echo "Some plugins failed to download!" "$(<"$FAILED")" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Cleaning up locks"
|
||||
rm -r "$REF_DIR"/*.lock
|
||||
}
|
||||
|
||||
main "$@"
|
||||
`
|
||||
|
||||
var initBashTemplate = template.Must(template.New(initScriptName).Parse(`#!/usr/bin/env bash
|
||||
set -e
|
||||
set -x
|
||||
|
|
@ -19,18 +247,19 @@ set -x
|
|||
mkdir -p {{ .JenkinsHomePath }}/init.groovy.d
|
||||
cp -n {{ .BaseConfigurationPath }}/*.groovy {{ .JenkinsHomePath }}/init.groovy.d
|
||||
|
||||
touch {{ .JenkinsHomePath }}/plugins.txt
|
||||
cat > {{ .JenkinsHomePath }}/plugins.txt <<EOL
|
||||
credentials:2.1.18
|
||||
ssh-credentials:1.14
|
||||
job-dsl:1.70
|
||||
git:3.9.1
|
||||
workflow-cps:2.61
|
||||
workflow-job:2.30
|
||||
workflow-aggregator:2.6
|
||||
EOL
|
||||
mkdir -p {{ .JenkinsHomePath }}/scripts
|
||||
cp {{ .JenkinsScriptsVolumePath }}/*.sh {{ .JenkinsHomePath }}/scripts
|
||||
chmod +x {{ .JenkinsHomePath }}/scripts/*.sh
|
||||
|
||||
/usr/local/bin/install-plugins.sh < {{ .JenkinsHomePath }}/plugins.txt
|
||||
{{- $jenkinsHomePath := .JenkinsHomePath }}
|
||||
{{- $installPluginsCommand := .InstallPluginsCommand }}
|
||||
|
||||
echo "Installing plugins - begin"
|
||||
{{- range $rootPluginName, $plugins := .Plugins }}
|
||||
echo "Installing required plugins for '{{ $rootPluginName }}'"
|
||||
{{ $jenkinsHomePath }}/scripts/{{ $installPluginsCommand }} {{ $rootPluginName }} {{ range $index, $plugin := $plugins }}{{ . }} {{ end }}
|
||||
{{- end }}
|
||||
echo "Installing plugins - end"
|
||||
|
||||
/sbin/tini -s -- /usr/local/bin/jenkins.sh
|
||||
`))
|
||||
|
|
@ -42,13 +271,19 @@ func buildConfigMapTypeMeta() metav1.TypeMeta {
|
|||
}
|
||||
}
|
||||
|
||||
func buildInitBashScript() (*string, error) {
|
||||
func buildInitBashScript(pluginsToInstall map[string][]string) (*string, error) {
|
||||
data := struct {
|
||||
JenkinsHomePath string
|
||||
BaseConfigurationPath string
|
||||
JenkinsHomePath string
|
||||
BaseConfigurationPath string
|
||||
InstallPluginsCommand string
|
||||
JenkinsScriptsVolumePath string
|
||||
Plugins map[string][]string
|
||||
}{
|
||||
JenkinsHomePath: jenkinsHomePath,
|
||||
BaseConfigurationPath: jenkinsBaseConfigurationVolumePath,
|
||||
JenkinsHomePath: jenkinsHomePath,
|
||||
BaseConfigurationPath: jenkinsBaseConfigurationVolumePath,
|
||||
Plugins: pluginsToInstall,
|
||||
InstallPluginsCommand: installPluginsCommand,
|
||||
JenkinsScriptsVolumePath: jenkinsScriptsVolumePath,
|
||||
}
|
||||
|
||||
output, err := render.Render(initBashTemplate, data)
|
||||
|
|
@ -67,7 +302,7 @@ func getScriptsConfigMapName(jenkins *virtuslabv1alpha1.Jenkins) string {
|
|||
func NewScriptsConfigMap(meta metav1.ObjectMeta, jenkins *virtuslabv1alpha1.Jenkins) (*corev1.ConfigMap, error) {
|
||||
meta.Name = getScriptsConfigMapName(jenkins)
|
||||
|
||||
initBashScript, err := buildInitBashScript()
|
||||
initBashScript, err := buildInitBashScript(jenkins.Spec.Master.Plugins)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -76,7 +311,8 @@ func NewScriptsConfigMap(meta metav1.ObjectMeta, jenkins *virtuslabv1alpha1.Jenk
|
|||
TypeMeta: buildConfigMapTypeMeta(),
|
||||
ObjectMeta: meta,
|
||||
Data: map[string]string{
|
||||
initScriptName: *initBashScript,
|
||||
initScriptName: *initBashScript,
|
||||
installPluginsCommand: fmt.Sprintf(installPluginsBashFmt, jenkinsHomePath),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
docker "github.com/docker/distribution/reference"
|
||||
)
|
||||
|
|
@ -12,16 +15,52 @@ var (
|
|||
dockerImageRegexp = regexp.MustCompile(`^` + docker.TagRegexp.String() + `$`)
|
||||
)
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) validate(jenkins *virtuslabv1alpha1.Jenkins) bool {
|
||||
// Validate validates Jenkins CR Spec.master section
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *virtuslabv1alpha1.Jenkins) bool {
|
||||
if jenkins.Spec.Master.Image == "" {
|
||||
r.logger.V(0).Info("Image not set")
|
||||
r.logger.V(log.VWarn).Info("Image not set")
|
||||
return false
|
||||
}
|
||||
|
||||
if !dockerImageRegexp.MatchString(jenkins.Spec.Master.Image) && !docker.ReferenceRegexp.MatchString(jenkins.Spec.Master.Image) {
|
||||
r.logger.V(0).Info("Invalid image")
|
||||
r.logger.V(log.VWarn).Info("Invalid image")
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
if !r.validatePlugins(jenkins.Spec.Master.Plugins) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(plugins map[string][]string) bool {
|
||||
valid := true
|
||||
allPlugins := map[string][]plugin.Plugin{}
|
||||
|
||||
for rootPluginName, dependentPluginNames := range plugins {
|
||||
if _, err := plugin.New(rootPluginName); err != nil {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Invalid root plugin name '%s'", rootPluginName))
|
||||
valid = false
|
||||
}
|
||||
|
||||
dependentPlugins := []plugin.Plugin{}
|
||||
for _, pluginName := range dependentPluginNames {
|
||||
if p, err := plugin.New(pluginName); err != nil {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Invalid dependent plugin name '%s' in root plugin '%s'", pluginName, rootPluginName))
|
||||
valid = false
|
||||
} else {
|
||||
dependentPlugins = append(dependentPlugins, *p)
|
||||
}
|
||||
}
|
||||
|
||||
allPlugins[rootPluginName] = dependentPlugins
|
||||
}
|
||||
|
||||
if valid {
|
||||
return plugin.VerifyDependencies(allPlugins)
|
||||
}
|
||||
|
||||
return valid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
)
|
||||
|
||||
func TestValidatePlugins(t *testing.T) {
|
||||
data := []struct {
|
||||
plugins map[string][]string
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
plugins: map[string][]string{
|
||||
"valid-plugin-name:1.0": {
|
||||
"valid-plugin-name:1.0",
|
||||
},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
plugins: map[string][]string{
|
||||
"invalid-plugin-name": {
|
||||
"invalid-plugin-name",
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
plugins: map[string][]string{
|
||||
"valid-plugin-name:1.0": {
|
||||
"valid-plugin-name:1.0",
|
||||
"valid-plugin-name2:1.0",
|
||||
},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
plugins: map[string][]string{
|
||||
"valid-plugin-name:1.0": {},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
baseReconcileLoop := New(nil, nil, logf.ZapLogger(false),
|
||||
nil, false, false)
|
||||
|
||||
for index, testingData := range data {
|
||||
t.Run(fmt.Sprintf("Testing %d plugins set", index), func(t *testing.T) {
|
||||
result := baseReconcileLoop.validatePlugins(testingData.plugins)
|
||||
assert.Equal(t, testingData.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import (
|
|||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
|
@ -95,8 +96,17 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
|||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
err = r.setDefaults(jenkins)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// Reconcile base configuration
|
||||
baseConfiguration := base.New(r.client, r.scheme, logger, jenkins, r.local, r.minikube)
|
||||
if !baseConfiguration.Validate(jenkins) {
|
||||
logger.V(log.VWarn).Info("Please correct Jenkins CR")
|
||||
return reconcile.Result{}, nil // don't requeue
|
||||
}
|
||||
result, jenkinsClient, err := baseConfiguration.Reconcile()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
|
|
@ -137,3 +147,11 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
|||
func (r *ReconcileJenkins) buildLogger(jenkinsName string) logr.Logger {
|
||||
return log.Log.WithValues("cr", jenkinsName)
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkins) setDefaults(jenkins *virtuslabv1alpha1.Jenkins) error {
|
||||
if len(jenkins.Spec.Master.Plugins) == 0 {
|
||||
jenkins.Spec.Master.Plugins = plugin.BasePlugins()
|
||||
return r.client.Update(context.TODO(), jenkins)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
package plugin
|
||||
|
||||
// BasePlugins returns map of plugins to install by operator
|
||||
func BasePlugins() (plugins map[string][]string) {
|
||||
plugins = map[string][]string{}
|
||||
|
||||
for rootPluginName, dependentPlugins := range BasePluginsMap {
|
||||
plugins[rootPluginName] = []string{}
|
||||
for _, pluginName := range dependentPlugins {
|
||||
plugins[rootPluginName] = append(plugins[rootPluginName], pluginName.String())
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BasePluginsMap contains plugins to install by operator
|
||||
var BasePluginsMap = map[string][]Plugin{
|
||||
Must(New("kubernetes:1.13.8")).String(): {
|
||||
Must(New("apache-httpcomponents-client-4-api:4.5.5-3.0")),
|
||||
Must(New("cloudbees-folder:6.7")),
|
||||
Must(New("credentials:2.1.18")),
|
||||
Must(New("durable-task:1.28")),
|
||||
Must(New("jackson2-api:2.9.8")),
|
||||
Must(New("kubernetes-credentials:0.4.0")),
|
||||
Must(New("plain-credentials:1.5")),
|
||||
Must(New("structs:1.17")),
|
||||
Must(New("variant:1.1")),
|
||||
Must(New("workflow-step-api:2.17")),
|
||||
},
|
||||
Must(New("workflow-job:2.31")).String(): {
|
||||
Must(New("scm-api:2.3.0")),
|
||||
Must(New("script-security:1.49")),
|
||||
Must(New("structs:1.17")),
|
||||
Must(New("workflow-api:2.33")),
|
||||
Must(New("workflow-step-api:2.17")),
|
||||
Must(New("workflow-support:2.24")),
|
||||
},
|
||||
Must(New("workflow-aggregator:2.6")).String(): {
|
||||
Must(New("ace-editor:1.1")),
|
||||
Must(New("apache-httpcomponents-client-4-api:4.5.5-3.0")),
|
||||
Must(New("authentication-tokens:1.3")),
|
||||
Must(New("branch-api:2.1.2")),
|
||||
Must(New("cloudbees-folder:6.7")),
|
||||
Must(New("credentials-binding:1.17")),
|
||||
Must(New("credentials:2.1.18")),
|
||||
Must(New("display-url-api:2.3.0")),
|
||||
Must(New("docker-commons:1.13")),
|
||||
Must(New("docker-workflow:1.17")),
|
||||
Must(New("durable-task:1.28")),
|
||||
Must(New("git-client:2.7.4")),
|
||||
Must(New("git-server:1.7")),
|
||||
Must(New("handlebars:1.1.1")),
|
||||
Must(New("jackson2-api:2.9.8")),
|
||||
Must(New("jquery-detached:1.2.1")),
|
||||
Must(New("jsch:0.1.54.2")),
|
||||
Must(New("junit:1.26.1")),
|
||||
Must(New("lockable-resources:2.3")),
|
||||
Must(New("mailer:1.22")),
|
||||
Must(New("matrix-project:1.13")),
|
||||
Must(New("momentjs:1.1.1")),
|
||||
Must(New("pipeline-build-step:2.7")),
|
||||
Must(New("pipeline-graph-analysis:1.9")),
|
||||
Must(New("pipeline-input-step:2.9")),
|
||||
Must(New("pipeline-milestone-step:1.3.1")),
|
||||
Must(New("pipeline-model-api:1.3.4")),
|
||||
Must(New("pipeline-model-declarative-agent:1.1.1")),
|
||||
Must(New("pipeline-model-definition:1.3.4")),
|
||||
Must(New("pipeline-model-extensions:1.3.4")),
|
||||
Must(New("pipeline-rest-api:2.10")),
|
||||
Must(New("pipeline-stage-step:2.3")),
|
||||
Must(New("pipeline-stage-tags-metadata:1.3.4")),
|
||||
Must(New("pipeline-stage-view:2.10")),
|
||||
Must(New("plain-credentials:1.5")),
|
||||
Must(New("scm-api:2.3.0")),
|
||||
Must(New("script-security:1.49")),
|
||||
Must(New("ssh-credentials:1.14")),
|
||||
Must(New("structs:1.17")),
|
||||
Must(New("workflow-api:2.33")),
|
||||
Must(New("workflow-basic-steps:2.13")),
|
||||
Must(New("workflow-cps-global-lib:2.12")),
|
||||
Must(New("workflow-cps:2.61")),
|
||||
Must(New("workflow-durable-task-step:2.27")),
|
||||
Must(New("workflow-job:2.31")),
|
||||
Must(New("workflow-multibranch:2.20")),
|
||||
Must(New("workflow-scm-step:2.7")),
|
||||
Must(New("workflow-step-api:2.17")),
|
||||
Must(New("workflow-support:2.24")),
|
||||
},
|
||||
Must(New("git:3.9.1")).String(): {
|
||||
Must(New("apache-httpcomponents-client-4-api:4.5.5-3.0")),
|
||||
Must(New("credentials:2.1.18")),
|
||||
Must(New("display-url-api:2.3.0")),
|
||||
Must(New("git-client:2.7.4")),
|
||||
Must(New("jsch:0.1.54.2")),
|
||||
Must(New("junit:1.26.1")),
|
||||
Must(New("mailer:1.22")),
|
||||
Must(New("matrix-project:1.13")),
|
||||
Must(New("scm-api:2.3.0")),
|
||||
Must(New("script-security:1.49")),
|
||||
Must(New("ssh-credentials:1.14")),
|
||||
Must(New("structs:1.17")),
|
||||
Must(New("workflow-api:2.33")),
|
||||
Must(New("workflow-scm-step:2.7")),
|
||||
Must(New("workflow-step-api:2.17")),
|
||||
},
|
||||
Must(New("job-dsl:1.70")).String(): {
|
||||
Must(New("script-security:1.49")),
|
||||
Must(New("structs:1.17")),
|
||||
},
|
||||
Must(New("jobConfigHistory:2.19")).String(): {},
|
||||
Must(New("configuration-as-code:1.4")).String(): {
|
||||
Must(New("configuration-as-code-support:1.4")),
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
)
|
||||
|
||||
// Plugin represents jenkins plugin
|
||||
type Plugin struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
rootPluginNameAndVersion string
|
||||
}
|
||||
|
||||
func (p Plugin) String() string {
|
||||
return fmt.Sprintf("%s:%s", p.Name, p.Version)
|
||||
}
|
||||
|
||||
// New creates plugin from string, for example "name-of-plugin:0.0.1"
|
||||
func New(nameWithVersion string) (*Plugin, error) {
|
||||
val := strings.SplitN(nameWithVersion, ":", 2)
|
||||
if val == nil || len(val) != 2 {
|
||||
return nil, fmt.Errorf("invalid plugin format '%s'", nameWithVersion)
|
||||
}
|
||||
return &Plugin{
|
||||
Name: val[0],
|
||||
Version: val[1],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Must returns plugin from pointer and throws panic when error is set
|
||||
func Must(plugin *Plugin, err error) Plugin {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return *plugin
|
||||
}
|
||||
|
||||
// VerifyDependencies checks if all plugins have compatible versions
|
||||
func VerifyDependencies(values ...map[string][]Plugin) bool {
|
||||
// key - plugin name, value array of versions
|
||||
allPlugins := make(map[string][]Plugin)
|
||||
valid := true
|
||||
|
||||
for _, value := range values {
|
||||
if value != nil {
|
||||
for rootPluginNameAndVersion, plugins := range value {
|
||||
if rootPlugin, err := New(rootPluginNameAndVersion); err != nil {
|
||||
valid = false
|
||||
} else {
|
||||
allPlugins[rootPlugin.Name] = append(allPlugins[rootPlugin.Name], Plugin{
|
||||
Name: rootPlugin.Name,
|
||||
Version: rootPlugin.Version,
|
||||
rootPluginNameAndVersion: rootPluginNameAndVersion})
|
||||
}
|
||||
for _, plugin := range plugins {
|
||||
allPlugins[plugin.Name] = append(allPlugins[plugin.Name], Plugin{
|
||||
Name: plugin.Name,
|
||||
Version: plugin.Version,
|
||||
rootPluginNameAndVersion: rootPluginNameAndVersion})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for pluginName, versions := range allPlugins {
|
||||
if len(versions) == 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, firstVersion := range versions {
|
||||
for _, secondVersion := range versions {
|
||||
if firstVersion.Version != secondVersion.Version {
|
||||
log.Log.V(log.VWarn).Info(fmt.Sprintf("Plugin '%s' requires version '%s' but plugin '%s' requires '%s' for plugin '%s'",
|
||||
firstVersion.rootPluginNameAndVersion,
|
||||
firstVersion.Version,
|
||||
secondVersion.rootPluginNameAndVersion,
|
||||
secondVersion.Version,
|
||||
pluginName,
|
||||
))
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valid
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestVerifyDependencies(t *testing.T) {
|
||||
data := []struct {
|
||||
basePlugins map[string][]Plugin
|
||||
extraPlugins map[string][]Plugin
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"first-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"first-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
"second-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"first-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
},
|
||||
extraPlugins: map[string][]Plugin{
|
||||
"second-root-plugin:2.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"first-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
"first-root-plugin:2.0.0": {
|
||||
Must(New("first-plugin:0.0.2")),
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"first-root-plugin:1.0.0": {
|
||||
Must(New("first-plugin:0.0.1")),
|
||||
},
|
||||
},
|
||||
extraPlugins: map[string][]Plugin{
|
||||
"first-root-plugin:2.0.0": {
|
||||
Must(New("first-plugin:0.0.2")),
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
basePlugins: map[string][]Plugin{
|
||||
"invalid-plugin-name": {},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
debug := false
|
||||
log.SetupLogger(&debug)
|
||||
|
||||
for index, testingData := range data {
|
||||
t.Run(fmt.Sprintf("Testing %d data", index), func(t *testing.T) {
|
||||
result := VerifyDependencies(testingData.basePlugins, testingData.extraPlugins)
|
||||
assert.Equal(t, testingData.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@ import (
|
|||
"testing"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
|
||||
"github.com/bndr/gojenkins"
|
||||
)
|
||||
|
||||
func TestBaseConfiguration(t *testing.T) {
|
||||
|
|
@ -17,7 +20,8 @@ func TestBaseConfiguration(t *testing.T) {
|
|||
waitForJenkinsBaseConfigurationToComplete(t, jenkins)
|
||||
|
||||
verifyJenkinsMasterPodAttributes(t, jenkins)
|
||||
verifyJenkinsAPIConnection(t, jenkins)
|
||||
jenkinsClient := verifyJenkinsAPIConnection(t, jenkins)
|
||||
verifyBasePlugins(t, jenkinsClient)
|
||||
}
|
||||
|
||||
func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *virtuslabv1alpha1.Jenkins) {
|
||||
|
|
@ -39,3 +43,40 @@ func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *virtuslabv1alpha1.J
|
|||
|
||||
t.Log("Jenkins pod attributes are valid")
|
||||
}
|
||||
|
||||
func verifyBasePlugins(t *testing.T, jenkinsClient *gojenkins.Jenkins) {
|
||||
allPluginsInJenkins, err := jenkinsClient.GetPlugins(1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for rootPluginName, p := range plugin.BasePluginsMap {
|
||||
rootPlugin, err := plugin.New(rootPluginName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if found, ok := isPluginValid(t, allPluginsInJenkins, *rootPlugin); !ok {
|
||||
t.Fatalf("Invalid plugin '%s', actual '%+v'", rootPlugin, found)
|
||||
}
|
||||
for _, requiredPlugin := range p {
|
||||
if found, ok := isPluginValid(t, allPluginsInJenkins, requiredPlugin); !ok {
|
||||
t.Fatalf("Invalid plugin '%s', actual '%+v'", requiredPlugin, found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.Log("Base plugins have been installed")
|
||||
}
|
||||
|
||||
func isPluginValid(t *testing.T, plugins *gojenkins.Plugins, requiredPlugin plugin.Plugin) (*gojenkins.Plugin, bool) {
|
||||
p := plugins.Contains(requiredPlugin.Name)
|
||||
if p == nil {
|
||||
return p, false
|
||||
}
|
||||
|
||||
if !p.Active || !p.Enabled || p.Deleted {
|
||||
return p, false
|
||||
}
|
||||
|
||||
return p, requiredPlugin.Version == p.Version
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue