Initial version of jobs API
This commit is contained in:
		
							parent
							
								
									5443152413
								
							
						
					
					
						commit
						fef930791b
					
				|  | @ -2,323 +2,250 @@ | |||
| 
 | ||||
| 
 | ||||
| [[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", | ||||
|  | @ -330,109 +257,85 @@ | |||
|     "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]] | ||||
|   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 = [ | ||||
|     ".", | ||||
|  | @ -440,23 +343,19 @@ | |||
|     "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", | ||||
|  | @ -466,38 +365,32 @@ | |||
|     "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", | ||||
|  | @ -514,35 +407,29 @@ | |||
|     "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 = [ | ||||
|     ".", | ||||
|  | @ -554,30 +441,24 @@ | |||
|     "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", | ||||
|  | @ -609,24 +490,20 @@ | |||
|     "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", | ||||
|  | @ -670,13 +547,11 @@ | |||
|     "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", | ||||
|  | @ -722,6 +597,7 @@ | |||
|     "rest", | ||||
|     "rest/watch", | ||||
|     "restmapper", | ||||
|     "testing", | ||||
|     "third_party/forked/golang/template", | ||||
|     "tools/auth", | ||||
|     "tools/cache", | ||||
|  | @ -744,13 +620,11 @@ | |||
|     "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", | ||||
|  | @ -776,14 +650,12 @@ | |||
|     "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", | ||||
|  | @ -793,13 +665,11 @@ | |||
|     "generator", | ||||
|     "namer", | ||||
|     "parser", | ||||
|     "types", | ||||
|     "types" | ||||
|   ] | ||||
|   pruneopts = "NT" | ||||
|   revision = "7338e4bfd6915369a1375890db1bbda0158c9863" | ||||
| 
 | ||||
| [[projects]] | ||||
|   digest = "1:c48a795cd7048bb1888273bc604b6e69b22f9b8089c3df65f77cc527757b515c" | ||||
|   name = "k8s.io/kube-openapi" | ||||
|   packages = [ | ||||
|     "cmd/openapi-gen/args", | ||||
|  | @ -807,13 +677,11 @@ | |||
|     "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", | ||||
|  | @ -821,6 +689,7 @@ | |||
|     "pkg/client", | ||||
|     "pkg/client/apiutil", | ||||
|     "pkg/client/config", | ||||
|     "pkg/client/fake", | ||||
|     "pkg/controller", | ||||
|     "pkg/controller/controllerutil", | ||||
|     "pkg/event", | ||||
|  | @ -841,57 +710,14 @@ | |||
|     "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 | ||||
|   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", | ||||
|   ] | ||||
|   inputs-digest = "781fe36c1f78cefee37a5abd84f77b3213ed0b33b98b697f379338ef763422b3" | ||||
|   solver-name = "gps-cdcl" | ||||
|   solver-version = 1 | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ Can be found [here][developer_guide]. | |||
|  | ||||
| 
 | ||||
| Common: | ||||
| * VirtusLab docker registry (in-progress) | ||||
| * ~~VirtusLab docker registry~~ https://hub.docker.com/r/virtuslab/jenkins-operator | ||||
| * simple library for sending Kubernetes events using one common format | ||||
| * decorate Jenkins API client and add more functions for handling jobs and builds e.g. Ensure, ~~CreateOrUpdate~~ | ||||
| * documentation [github pages with Hugo](https://gohugo.io/): | ||||
|  | @ -29,11 +29,12 @@ Common: | |||
|         * Base and User configuration | ||||
|     * Contributing  | ||||
| * VirtusLab flavored Jenkins [theme](http://afonsof.com/jenkins-material-theme/) | ||||
| * create Jenkins Jobs View to all jobs managed by the operator | ||||
| 
 | ||||
| Base configuration: | ||||
| * install configuration as a code Jenkins plugin | ||||
| * handle Jenkins restart when base configuration has changed | ||||
| * install and configure Kubernetes plugin (in-progress) | ||||
| * ~~install~~ and configure Kubernetes plugin (in-progress) | ||||
| * e2e pipelines using Kubernetes plugin | ||||
| * Jenkins hardening, disable insecure options | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,18 @@ type JenkinsStatus struct { | |||
| 	// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
 | ||||
| 	BaseConfigurationCompletedTime *metav1.Time `json:"baseConfigurationCompletedTime,omitempty"` | ||||
| 	UserConfigurationCompletedTime *metav1.Time `json:"userConfigurationCompletedTime,omitempty"` | ||||
| 	Builds                         []Build      `json:"builds,omitempty"` | ||||
| } | ||||
| 
 | ||||
| // Build defines Jenkins Build status with corresponding metadata
 | ||||
| type Build struct { | ||||
| 	Name           string       `json:"name,omitempty"` | ||||
| 	Hash           string       `json:"hash,omitempty"` | ||||
| 	Number         int64        `json:"number,omitempty"` | ||||
| 	Status         string       `json:"status,omitempty"` // from https://javadoc.jenkins-ci.org/hudson/model/Result.html
 | ||||
| 	Retires        int          `json:"retries,omitempty"` | ||||
| 	CreateTime     *metav1.Time `json:"createTime,omitempty"` | ||||
| 	LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` | ||||
| } | ||||
| 
 | ||||
| // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | ||||
|  |  | |||
|  | @ -25,6 +25,30 @@ 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 *Build) DeepCopyInto(out *Build) { | ||||
| 	*out = *in | ||||
| 	if in.CreateTime != nil { | ||||
| 		in, out := &in.CreateTime, &out.CreateTime | ||||
| 		*out = (*in).DeepCopy() | ||||
| 	} | ||||
| 	if in.LastUpdateTime != nil { | ||||
| 		in, out := &in.LastUpdateTime, &out.LastUpdateTime | ||||
| 		*out = (*in).DeepCopy() | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Build.
 | ||||
| func (in *Build) DeepCopy() *Build { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(Build) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||
| func (in *Jenkins) DeepCopyInto(out *Jenkins) { | ||||
| 	*out = *in | ||||
|  | @ -160,6 +184,13 @@ func (in *JenkinsStatus) DeepCopyInto(out *JenkinsStatus) { | |||
| 		in, out := &in.UserConfigurationCompletedTime, &out.UserConfigurationCompletedTime | ||||
| 		*out = (*in).DeepCopy() | ||||
| 	} | ||||
| 	if in.Builds != nil { | ||||
| 		in, out := &in.Builds, &out.Builds | ||||
| 		*out = make([]Build, len(*in)) | ||||
| 		for i := range *in { | ||||
| 			(*in)[i].DeepCopyInto(&(*out)[i]) | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,10 +1,12 @@ | |||
| package user | ||||
| 
 | ||||
| import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	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/user/seedjobs" | ||||
| 
 | ||||
| 	"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/jobs" | ||||
| 	"github.com/go-logr/logr" | ||||
| 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||||
|  | @ -31,10 +33,25 @@ func New(k8sClient k8s.Client, jenkinsClient jenkinsclient.Jenkins, logger logr. | |||
| 
 | ||||
| // Reconcile it's a main reconciliation loop for user supplied configuration
 | ||||
| func (r *ReconcileUserConfiguration) Reconcile() (*reconcile.Result, error) { | ||||
| 	err := seedjobs.EnsureSeedJobs(r.jenkinsClient, r.k8sClient, r.jenkins) | ||||
| 	return r.reconcileSeedJobs() | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileUserConfiguration) reconcileSeedJobs() (*reconcile.Result, error) { | ||||
| 	seedJobs := seedjobs.New(r.jenkinsClient, r.k8sClient, r.logger) | ||||
| 	done, err := seedJobs.EnsureSeedJobs(r.jenkins) | ||||
| 	if err != nil { | ||||
| 		if err == jobs.ErrorBuildFailed { | ||||
| 			return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil | ||||
| 		} | ||||
| 
 | ||||
| 		if err == jobs.ErrorEmptyJenkinsCR || err == jobs.ErrorUncoverBuildFailed { | ||||
| 			return nil, nil | ||||
| 		} | ||||
| 
 | ||||
| 		return &reconcile.Result{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	if !done { | ||||
| 		return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil | ||||
| 	} | ||||
| 	return nil, nil | ||||
| } | ||||
|  |  | |||
|  | @ -2,11 +2,15 @@ package seedjobs | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	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/jobs" | ||||
| 	"github.com/go-logr/logr" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||
|  | @ -24,70 +28,88 @@ const ( | |||
| 	displayNameParameterName      = "SEED_JOB_DISPLAY_NAME" | ||||
| ) | ||||
| 
 | ||||
| // SeedJobs defines API for configuring and ensuring Jenkins Seed Jobs and Deploy Keys
 | ||||
| type SeedJobs struct { | ||||
| 	jenkinsClient jenkinsclient.Jenkins | ||||
| 	k8sClient     k8s.Client | ||||
| 	logger        logr.Logger | ||||
| } | ||||
| 
 | ||||
| // New creates seedJobs client
 | ||||
| func New(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, logger logr.Logger) *SeedJobs { | ||||
| 	return &SeedJobs{ | ||||
| 		jenkinsClient: jenkinsClient, | ||||
| 		k8sClient:     k8sClient, | ||||
| 		logger:        logger, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // EnsureSeedJobs configures seed job and runs it for every entry from Jenkins.Spec.SeedJobs
 | ||||
| func EnsureSeedJobs(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	err := configureSeedJob(jenkinsClient) | ||||
| func (s *SeedJobs) EnsureSeedJobs(jenkins *virtuslabv1alpha1.Jenkins) (done bool, err error) { | ||||
| 	err = s.configureSeedJob() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return false, err | ||||
| 	} | ||||
| 	err = buildAndVerifySeedJobs(jenkinsClient, k8sClient, jenkins) | ||||
| 	done, err = s.buildSeedJobs(jenkins) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return done, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SeedJobs) configureSeedJob() error { | ||||
| 	_, err := s.jenkinsClient.CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func configureSeedJob(jenkinsClient jenkinsclient.Jenkins) error { | ||||
| 	_, err := jenkinsClient.CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func buildAndVerifySeedJobs(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| func (s *SeedJobs) buildSeedJobs(jenkins *virtuslabv1alpha1.Jenkins) (done bool, err error) { | ||||
| 	allDone := true | ||||
| 	seedJobs := jenkins.Spec.SeedJobs | ||||
| 	for _, seedJob := range seedJobs { | ||||
| 		privateKey, err := privateKeyFromSecret(k8sClient, jenkins.Namespace, seedJob) | ||||
| 		privateKey, err := s.privateKeyFromSecret(jenkins.Namespace, seedJob) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return false, err | ||||
| 		} | ||||
| 		err = buildAndVerifySeedJob( | ||||
| 			jenkinsClient, | ||||
| 			seedJob.ID, | ||||
| 			privateKey, | ||||
| 			seedJob.RepositoryURL, | ||||
| 			seedJob.RepositoryBranch, seedJob.Targets, fmt.Sprintf("Seed Job from %s", seedJob.ID)) | ||||
| 		parameters := map[string]string{ | ||||
| 			deployKeyIDParameterName:      seedJob.ID, | ||||
| 			privateKeyParameterName:       privateKey, | ||||
| 			repositoryURLParameterName:    seedJob.RepositoryURL, | ||||
| 			repositoryBranchParameterName: seedJob.RepositoryBranch, | ||||
| 			targetsParameterName:          seedJob.Targets, | ||||
| 			displayNameParameterName:      fmt.Sprintf("Seed Job from %s", seedJob.ID), | ||||
| 		} | ||||
| 
 | ||||
| 		hash := sha256.New() | ||||
| 		hash.Write([]byte(parameters[deployKeyIDParameterName])) | ||||
| 		hash.Write([]byte(parameters[privateKeyParameterName])) | ||||
| 		hash.Write([]byte(parameters[repositoryURLParameterName])) | ||||
| 		hash.Write([]byte(parameters[repositoryBranchParameterName])) | ||||
| 		hash.Write([]byte(parameters[targetsParameterName])) | ||||
| 		hash.Write([]byte(parameters[displayNameParameterName])) | ||||
| 		encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil)) | ||||
| 
 | ||||
| 		jobsClient := jobs.New(s.jenkinsClient, s.k8sClient, s.logger) | ||||
| 		done, err := jobsClient.EnsureBuildJob(ConfigureSeedJobsName, encodedHash, parameters, jenkins, true) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return false, err | ||||
| 		} | ||||
| 
 | ||||
| 		if !done { | ||||
| 			allDone = false | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| 
 | ||||
| 	return allDone, nil | ||||
| } | ||||
| 
 | ||||
| func buildAndVerifySeedJob(jenkinsClient jenkinsclient.Jenkins, deployKeyID, privateKey, repositoryURL, repositoryBranch, targets, displayName string) error { | ||||
| 	// FIXME this function should build job and verify job status when finished (state in cr status)
 | ||||
| 	// requeue when job is running and check job status next time
 | ||||
| 	options := map[string]string{ | ||||
| 		deployKeyIDParameterName:      deployKeyID, | ||||
| 		privateKeyParameterName:       privateKey, | ||||
| 		repositoryURLParameterName:    repositoryURL, | ||||
| 		repositoryBranchParameterName: repositoryBranch, | ||||
| 		targetsParameterName:          targets, | ||||
| 		displayNameParameterName:      displayName, | ||||
| 	} | ||||
| 	_, err := jenkinsClient.BuildJob(ConfigureSeedJobsName, options) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func privateKeyFromSecret(k8sClient k8s.Client, namespace string, seedJob virtuslabv1alpha1.SeedJob) (string, error) { | ||||
| func (s *SeedJobs) privateKeyFromSecret(namespace string, seedJob virtuslabv1alpha1.SeedJob) (string, error) { | ||||
| 	if seedJob.PrivateKey.SecretKeyRef != nil { | ||||
| 		deployKeySecret := &v1.Secret{} | ||||
| 		namespaceName := types.NamespacedName{Namespace: namespace, Name: seedJob.PrivateKey.SecretKeyRef.Name} | ||||
| 		err := k8sClient.Get(context.TODO(), namespaceName, deployKeySecret) | ||||
| 		err := s.k8sClient.Get(context.TODO(), namespaceName, deployKeySecret) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| package seedjobs | ||||
|  | @ -0,0 +1,2 @@ | |||
| // Package jobs implements common jenkins jobs operations
 | ||||
| package jobs | ||||
|  | @ -0,0 +1,339 @@ | |||
| package jobs | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" | ||||
| 	"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client" | ||||
| 	"github.com/VirtusLab/jenkins-operator/pkg/log" | ||||
| 	"github.com/go-logr/logr" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// SuccessStatus - the build had no errors
 | ||||
| 	SuccessStatus = "success" | ||||
| 	// UnstableStatus - the build had some errors but they were not fatal. For example, some tests failed
 | ||||
| 	UnstableStatus = "unstable" | ||||
| 	// NotBuildStatus - this status code is used in a multi-stage build (like maven2) where a problem in earlier stage prevented later stages from building
 | ||||
| 	NotBuildStatus = "not_build" | ||||
| 	// FailureStatus - the build had a fatal error
 | ||||
| 	FailureStatus = "failure" | ||||
| 	// AbortedStatus - the build was manually aborted
 | ||||
| 	AbortedStatus = "aborted" | ||||
| 	// RunningStatus - this is custom build status for running build, not present in jenkins build result
 | ||||
| 	RunningStatus = "running" | ||||
| 	// ExpiredStatus - this is custom build status for expired build, not present in jenkins build result
 | ||||
| 	ExpiredStatus = "expired" | ||||
| 	// MaxBuildRetires - determines max amount of retires for failed build
 | ||||
| 	MaxBuildRetires = 3 | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// ErrorEmptyJenkinsCR - this is custom error returned when jenkins custom resource is empty
 | ||||
| 	ErrorEmptyJenkinsCR = errors.New("empty jenkins cr") | ||||
| 	// ErrorUnexpectedBuildStatus - this is custom error returned when jenkins build has unexpected status
 | ||||
| 	ErrorUnexpectedBuildStatus = errors.New("unexpected build status") | ||||
| 	// ErrorBuildFailed - this is custom error returned when jenkins build has failed
 | ||||
| 	ErrorBuildFailed = errors.New("build failed") | ||||
| 	// ErrorAbortBuildFailed - this is custom error returned when jenkins build couldn't be aborted
 | ||||
| 	ErrorAbortBuildFailed = errors.New("build failed") | ||||
| 	// ErrorUncoverBuildFailed - this is custom error returned when jenkins build has failed and cannot be recovered
 | ||||
| 	ErrorUncoverBuildFailed = errors.New("build failed and cannot be recovered") | ||||
| 	// ErrorNotFound - this is error returned when jenkins build couldn't be found
 | ||||
| 	ErrorNotFound = errors.New("404") | ||||
| ) | ||||
| 
 | ||||
| // Jobs defines Jobs API tailored for operator sdk
 | ||||
| type Jobs struct { | ||||
| 	jenkinsClient client.Jenkins | ||||
| 	logger        logr.Logger | ||||
| 	k8sClient     k8s.Client | ||||
| } | ||||
| 
 | ||||
| // New creates jobs client
 | ||||
| func New(jenkinsClient client.Jenkins, k8sClient k8s.Client, logger logr.Logger) *Jobs { | ||||
| 	return &Jobs{ | ||||
| 		jenkinsClient: jenkinsClient, | ||||
| 		k8sClient:     k8sClient, | ||||
| 		logger:        logger, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // EnsureBuildJob function takes care of jenkins build lifecycle according to the lifecycle of reconciliation loop
 | ||||
| // implementation guarantees that jenkins build can be properly handled even after operator pod restart
 | ||||
| // entire state is saved in Jenkins.Status.Builds section
 | ||||
| // function return 'true' when build finished successfully or false when reconciliation loop should requeue this function
 | ||||
| // preserveStatus determines that build won't be removed from Jenkins.Status.Builds section
 | ||||
| func (jobs *Jobs) EnsureBuildJob(name, hash string, parameters map[string]string, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (done bool, err error) { | ||||
| 	jobs.logger.Info(fmt.Sprintf("Ensuring build, name:'%s' hash:'%s'", name, hash)) | ||||
| 
 | ||||
| 	build, err := jobs.getBuildFromStatus(name, hash, jenkins) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if build != nil { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Build exists in status, name:'%s' hash:'%s' status: '%s'", name, hash, build.Status)) | ||||
| 		switch strings.ToLower(build.Status) { | ||||
| 		case SuccessStatus: | ||||
| 			return jobs.ensureSuccessBuild(*build, jenkins, preserveStatus) | ||||
| 		case RunningStatus: | ||||
| 			return jobs.ensureRunningBuild(*build, jenkins, preserveStatus) | ||||
| 		case UnstableStatus, NotBuildStatus, FailureStatus, AbortedStatus: | ||||
| 			return jobs.ensureFailedBuild(*build, jenkins, parameters, preserveStatus) | ||||
| 		case ExpiredStatus: | ||||
| 			return jobs.ensureExpiredBuild(*build, jenkins, preserveStatus) | ||||
| 		default: | ||||
| 			jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Unexpected build status, name:'%s' hash:'%s' status:'%s'", name, hash, build.Status)) | ||||
| 			return false, ErrorUnexpectedBuildStatus | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// build is run first time - build job and update status
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Build doesn't exist, running and updating status, name:'%s' hash:'%s'", name, hash)) | ||||
| 	return jobs.buildJob(name, hash, parameters, jenkins) | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) getBuildFromStatus(name string, hash string, jenkins *virtuslabv1alpha1.Jenkins) (*virtuslabv1alpha1.Build, error) { | ||||
| 	if jenkins != nil { | ||||
| 		builds := jenkins.Status.Builds | ||||
| 		for _, build := range builds { | ||||
| 			if build.Name == name && build.Hash == hash { | ||||
| 				return &build, nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) ensureSuccessBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (bool, error) { | ||||
| 	if jenkins == nil { | ||||
| 		jobs.logger.V(log.VWarn).Info("Jenkins CR is empty") | ||||
| 		return false, ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Ensuring success build, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 
 | ||||
| 	if !preserveStatus { | ||||
| 		err := jobs.removeBuildFromStatus(build, jenkins) | ||||
| 		jobs.logger.Info(fmt.Sprintf("Removing build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		if err != nil { | ||||
| 			jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't remove build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 			return false, err | ||||
| 		} | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) ensureRunningBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (bool, error) { | ||||
| 	if jenkins == nil { | ||||
| 		jobs.logger.V(log.VWarn).Info("Jenkins CR is empty") | ||||
| 		return false, ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Ensuring running build, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 	// FIXME (antoniaklja) implement build expiration
 | ||||
| 
 | ||||
| 	jenkinsBuild, err := jobs.jenkinsClient.GetBuild(build.Name, build.Number) | ||||
| 	if isNotFoundError(err) { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Build still running , name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		return false, nil | ||||
| 	} else if err != nil { | ||||
| 		jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't get jenkins build, name:'%s' number:'%d'", build.Name, build.Number)) | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if jenkinsBuild.GetResult() != "" { | ||||
| 		build.Status = strings.ToLower(jenkinsBuild.GetResult()) | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Updating build status, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status)) | ||||
| 	err = jobs.updateBuildStatus(build, jenkins) | ||||
| 	if err != nil { | ||||
| 		jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't update build status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if build.Status == SuccessStatus { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Build finished successfully, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status)) | ||||
| 		if !preserveStatus { | ||||
| 			jobs.logger.Info(fmt.Sprintf("Removing build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 			err := jobs.removeBuildFromStatus(build, jenkins) | ||||
| 			if err != nil { | ||||
| 				jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't remove build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 				return false, err | ||||
| 			} | ||||
| 		} | ||||
| 		return true, nil | ||||
| 	} | ||||
| 
 | ||||
| 	return false, nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) ensureFailedBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, parameters map[string]string, preserveStatus bool) (bool, error) { | ||||
| 	if jenkins == nil { | ||||
| 		jobs.logger.V(log.VWarn).Info("Jenkins CR is empty") | ||||
| 		return false, ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Ensuring failed build, name:'%s' hash:'%s' status: '%s'", build.Name, build.Hash, build.Status)) | ||||
| 
 | ||||
| 	if build.Retires < MaxBuildRetires { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Retrying build, name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires)) | ||||
| 		_, err := jobs.buildJob(build.Name, build.Hash, parameters, jenkins) | ||||
| 		if err != nil { | ||||
| 			jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't retry build, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 			return false, err | ||||
| 		} | ||||
| 		return false, ErrorBuildFailed | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("The retries limit was reached , name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires)) | ||||
| 
 | ||||
| 	if !preserveStatus { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Removing build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		err := jobs.removeBuildFromStatus(build, jenkins) | ||||
| 		if err != nil { | ||||
| 			jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't remove build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 			return false, err | ||||
| 		} | ||||
| 	} | ||||
| 	return false, ErrorUncoverBuildFailed | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) ensureExpiredBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (bool, error) { | ||||
| 	if jenkins == nil { | ||||
| 		jobs.logger.V(log.VWarn).Info("Jenkins CR is empty") | ||||
| 		return false, ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Ensuring expired build, name:'%s' hash:'%s' status: '%s'", build.Name, build.Hash, build.Status)) | ||||
| 
 | ||||
| 	jenkinsBuild, err := jobs.jenkinsClient.GetBuild(build.Name, build.Number) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = jenkinsBuild.Stop() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	jenkinsBuild, err = jobs.jenkinsClient.GetBuild(build.Name, build.Number) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if jenkinsBuild.GetResult() != AbortedStatus { | ||||
| 		return false, ErrorAbortBuildFailed | ||||
| 	} | ||||
| 
 | ||||
| 	err = jobs.updateBuildStatus(build, jenkins) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO(antoniaklja) clean up k8s resources
 | ||||
| 
 | ||||
| 	if !preserveStatus { | ||||
| 		jobs.logger.Info(fmt.Sprintf("Removing build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		err = jobs.removeBuildFromStatus(build, jenkins) | ||||
| 		if err != nil { | ||||
| 			jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't remove build from status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 			return false, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return true, nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) removeBuildFromStatus(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	if jenkins == nil { | ||||
| 		return ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	builds := make([]virtuslabv1alpha1.Build, len(jenkins.Status.Builds), len(jenkins.Status.Builds)) | ||||
| 	for _, existingBuild := range jenkins.Status.Builds { | ||||
| 		if existingBuild.Name != build.Name && existingBuild.Hash != build.Hash { | ||||
| 			builds = append(builds, existingBuild) | ||||
| 		} | ||||
| 	} | ||||
| 	jenkins.Status.Builds = builds | ||||
| 	err := jobs.k8sClient.Update(context.TODO(), jenkins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) buildJob(name string, hash string, parameters map[string]string, jenkins *virtuslabv1alpha1.Jenkins) (bool, error) { | ||||
| 	if jenkins == nil { | ||||
| 		return false, ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Running build, name:'%s' hash:'%s'", name, hash)) | ||||
| 
 | ||||
| 	number, err := jobs.jenkinsClient.BuildJob(name, parameters) | ||||
| 	if err != nil { | ||||
| 		jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't run build, name:'%s' hash:'%s' number:'%d'", name, hash, number)) | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	build := virtuslabv1alpha1.Build{ | ||||
| 		Name:   name, | ||||
| 		Number: number, | ||||
| 		Hash:   hash, | ||||
| 		Status: RunningStatus, | ||||
| 	} | ||||
| 
 | ||||
| 	jobs.logger.Info(fmt.Sprintf("Updating build status, name:'%s' hash:'%s' status:'%s'", name, hash, build.Status)) | ||||
| 	err = jobs.updateBuildStatus(build, jenkins) | ||||
| 	if err != nil { | ||||
| 		jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't update build status, name:'%s' hash:'%s'", build.Name, build.Hash)) | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return false, nil | ||||
| } | ||||
| 
 | ||||
| func (jobs *Jobs) updateBuildStatus(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	if jenkins == nil { | ||||
| 		return ErrorEmptyJenkinsCR | ||||
| 	} | ||||
| 
 | ||||
| 	// get index of existing build from status if exists
 | ||||
| 	buildIndex := -1 | ||||
| 	for index, existingBuild := range jenkins.Status.Builds { | ||||
| 		if build.Name == existingBuild.Name && build.Hash == existingBuild.Hash { | ||||
| 			buildIndex = index | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// update build status
 | ||||
| 	now := metav1.Now() | ||||
| 	build.LastUpdateTime = &now | ||||
| 	if buildIndex >= 0 { | ||||
| 		jenkins.Status.Builds[buildIndex] = build | ||||
| 	} else { | ||||
| 		build.CreateTime = &now | ||||
| 		jenkins.Status.Builds = append(jenkins.Status.Builds, build) | ||||
| 	} | ||||
| 	err := jobs.k8sClient.Update(context.TODO(), jenkins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func isNotFoundError(err error) bool { | ||||
| 	if err != nil { | ||||
| 		return err.Error() == ErrorNotFound.Error() | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | @ -0,0 +1 @@ | |||
| package jobs | ||||
|  | @ -4,10 +4,15 @@ import ( | |||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" | ||||
| 	"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/seedjobs" | ||||
| 
 | ||||
| 	"github.com/bndr/gojenkins" | ||||
| 	framework "github.com/operator-framework/operator-sdk/pkg/test" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/apimachinery/pkg/util/wait" | ||||
| 
 | ||||
| 	"context" | ||||
| ) | ||||
| 
 | ||||
| func TestUserConfiguration(t *testing.T) { | ||||
|  | @ -16,14 +21,17 @@ func TestUserConfiguration(t *testing.T) { | |||
| 	// Deletes test namespace
 | ||||
| 	defer ctx.Cleanup() | ||||
| 
 | ||||
| 	// base
 | ||||
| 	jenkins := createJenkinsCRWithSeedJob(t, namespace) | ||||
| 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) | ||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | ||||
| 	client := verifyJenkinsAPIConnection(t, jenkins) | ||||
| 	verifyJenkinsSeedJobs(t, client) | ||||
| 
 | ||||
| 	// user
 | ||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | ||||
| 	verifyJenkinsSeedJobs(t, client, jenkins) | ||||
| } | ||||
| 
 | ||||
| func verifyJenkinsSeedJobs(t *testing.T, client *gojenkins.Jenkins) { | ||||
| func verifyJenkinsSeedJobs(t *testing.T, client *gojenkins.Jenkins, jenkins *virtuslabv1alpha1.Jenkins) { | ||||
| 	// check if job has been configured and executed successfully
 | ||||
| 	err := wait.Poll(time.Second*10, time.Minute*2, func() (bool, error) { | ||||
| 		t.Logf("Attempting to get configure seed job status '%v'", seedjobs.ConfigureSeedJobsName) | ||||
|  | @ -54,4 +62,21 @@ func verifyJenkinsSeedJobs(t *testing.T, client *gojenkins.Jenkins) { | |||
| 	if err != nil { | ||||
| 		t.Fatalf("couldn't verify if seed job has been created '%v'", err) | ||||
| 	} | ||||
| 
 | ||||
| 	// verify Jenkins.Status.Builds
 | ||||
| 	// WARNING this use case depends on changes in https://github.com/VirtusLab/jenkins-operator-e2e/tree/master/cicd
 | ||||
| 	namespacedName := types.NamespacedName{Namespace: jenkins.Namespace, Name: jenkins.Name} | ||||
| 	err = framework.Global.Client.Get(context.TODO(), namespacedName, jenkins) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("couldn't get jenkins CR '%v'", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if len(jenkins.Status.Builds) != 1 { | ||||
| 		t.Fatalf("couldn't get build status from cr '%v'", jenkins.Status.Builds) | ||||
| 	} | ||||
| 
 | ||||
| 	build := jenkins.Status.Builds[0] | ||||
| 	if build.Name != seedjobs.ConfigureSeedJobsName { | ||||
| 		t.Fatalf("invalid cr status - wrong seed job name '%v'", build.Name) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue