Merge pull request #411 from fluxcd/gitrepository-reconciler
Rewrite `GitRepositoryReconciler` to new standards
This commit is contained in:
		
						commit
						becd5f824c
					
				
							
								
								
									
										10
									
								
								api/go.mod
								
								
								
								
							
							
						
						
									
										10
									
								
								api/go.mod
								
								
								
								
							| 
						 | 
					@ -3,7 +3,11 @@ module github.com/fluxcd/source-controller/api
 | 
				
			||||||
go 1.16
 | 
					go 1.16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/fluxcd/pkg/apis/meta v0.10.0
 | 
						github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1
 | 
				
			||||||
	k8s.io/apimachinery v0.21.1
 | 
						// TODO(hidde): introduction of the runtime package is temporary, and the dependency should be removed as soon as
 | 
				
			||||||
	sigs.k8s.io/controller-runtime v0.9.0
 | 
						//  all APIs have been updated to the runtime standards (more specifically; have dropped their condition modifying
 | 
				
			||||||
 | 
						//  functions).
 | 
				
			||||||
 | 
						github.com/fluxcd/pkg/runtime v0.13.0-rc.2
 | 
				
			||||||
 | 
						k8s.io/apimachinery v0.21.3
 | 
				
			||||||
 | 
						sigs.k8s.io/controller-runtime v0.9.3
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										72
									
								
								api/go.sum
								
								
								
								
							
							
						
						
									
										72
									
								
								api/go.sum
								
								
								
								
							| 
						 | 
					@ -88,10 +88,13 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
 | 
				
			||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
					github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
				
			||||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
 | 
					github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
 | 
				
			||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 | 
					github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 | 
				
			||||||
 | 
					github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
 | 
				
			||||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 | 
					github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 | 
				
			||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 | 
					github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 | 
				
			||||||
github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSLjG2rlE=
 | 
					github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 h1:RHHrztAFv9wmjM+Pk7Svt1UdD+1SdnQSp76MWFiM7Hg=
 | 
				
			||||||
github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE=
 | 
					github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqBlSPkLk7dxi0UM=
 | 
				
			||||||
 | 
					github.com/fluxcd/pkg/runtime v0.13.0-rc.2 h1:+4uTEg+CU++hlr7NpOP4KYp60MtHDOgYvpz/74tbATg=
 | 
				
			||||||
 | 
					github.com/fluxcd/pkg/runtime v0.13.0-rc.2/go.mod h1:TmvE2cJl1QkgZNmmlr7XUKoWDQwUiM5/wTUxXsQVoc8=
 | 
				
			||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 | 
					github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 | 
				
			||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
					github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
				
			||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 | 
					github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 | 
				
			||||||
| 
						 | 
					@ -110,6 +113,7 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
 | 
				
			||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 | 
					github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 | 
				
			||||||
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
 | 
					github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
 | 
				
			||||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 | 
					github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 | 
				
			||||||
 | 
					github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM=
 | 
				
			||||||
github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
 | 
					github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
 | 
				
			||||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 | 
					github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 | 
				
			||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 | 
					github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 | 
				
			||||||
| 
						 | 
					@ -150,6 +154,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 | 
				
			||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
					github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
				
			||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
					github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
				
			||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 | 
					github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 | 
				
			||||||
 | 
					github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 | 
				
			||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 | 
					github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 | 
				
			||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
					github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
				
			||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
					github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
				
			||||||
| 
						 | 
					@ -158,7 +163,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 | 
				
			||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
					github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
				
			||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					 | 
				
			||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 | 
					github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 | 
				
			||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
| 
						 | 
					@ -178,6 +182,7 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
 | 
				
			||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 | 
					github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 | 
				
			||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 | 
					github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 | 
				
			||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
 | 
					github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
 | 
				
			||||||
 | 
					github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
 | 
				
			||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
 | 
					github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
 | 
				
			||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
					github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
				
			||||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 | 
					github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 | 
				
			||||||
| 
						 | 
					@ -192,9 +197,11 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt
 | 
				
			||||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
 | 
					github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
 | 
				
			||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 | 
					github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 | 
				
			||||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 | 
					github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 | 
				
			||||||
 | 
					github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 | 
				
			||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 | 
					github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 | 
				
			||||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
 | 
					github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
 | 
				
			||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 | 
					github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 | 
				
			||||||
 | 
					github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
 | 
				
			||||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
 | 
					github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
 | 
				
			||||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
 | 
					github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
 | 
				
			||||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
 | 
					github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
 | 
				
			||||||
| 
						 | 
					@ -212,6 +219,7 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
 | 
				
			||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
					github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
				
			||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
					github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
				
			||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 | 
					github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 | 
				
			||||||
 | 
					github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 | 
				
			||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 | 
					github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 | 
				
			||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 | 
					github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 | 
				
			||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 | 
					github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 | 
				
			||||||
| 
						 | 
					@ -297,6 +305,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
 | 
				
			||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 | 
					github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 | 
				
			||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
					github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
					github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
 | 
					github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 | 
				
			||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
					github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
					github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
					github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
				
			||||||
| 
						 | 
					@ -367,6 +376,7 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
 | 
				
			||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 | 
					github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 | 
				
			||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
 | 
					github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
				
			||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
					go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
				
			||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
					go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
				
			||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 | 
					go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 | 
				
			||||||
| 
						 | 
					@ -377,11 +387,14 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 | 
				
			||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 | 
					go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 | 
				
			||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
					go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
				
			||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
					go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
				
			||||||
 | 
					go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 | 
				
			||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
					go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
				
			||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 | 
					go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 | 
				
			||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 | 
					go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 | 
				
			||||||
 | 
					go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 | 
				
			||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 | 
					go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 | 
				
			||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 | 
					go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 | 
				
			||||||
 | 
					go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
 | 
				
			||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 | 
					go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
					golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
					golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
				
			||||||
| 
						 | 
					@ -424,6 +437,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
 | 
				
			||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
 | 
					golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
| 
						 | 
					@ -454,12 +468,15 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
 | 
				
			||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
					golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 | 
				
			||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
					golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
					golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
 | 
					golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
					golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
					golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
 | 
					golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
| 
						 | 
					@ -469,6 +486,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
| 
						 | 
					@ -510,12 +528,16 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
 | 
					golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
					golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
 | 
					golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
 | 
				
			||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
| 
						 | 
					@ -530,6 +552,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
 | 
				
			||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
 | 
					golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs=
 | 
				
			||||||
 | 
					golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
| 
						 | 
					@ -571,6 +595,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
 | 
				
			||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
					golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
| 
						 | 
					@ -592,6 +617,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 | 
				
			||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
					google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
				
			||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 | 
					google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 | 
				
			||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
				
			||||||
 | 
					google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 | 
				
			||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
					google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
				
			||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
					google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
				
			||||||
| 
						 | 
					@ -632,6 +658,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 | 
				
			||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 | 
					google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 | 
				
			||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 | 
					google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 | 
				
			||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
					google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
				
			||||||
 | 
					google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
 | 
				
			||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
					google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
				
			||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
					gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
| 
						 | 
					@ -671,33 +698,40 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
 | 
				
			||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
					honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
				
			||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 | 
					honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 | 
				
			||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 | 
					honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 | 
				
			||||||
k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c=
 | 
					k8s.io/api v0.21.2 h1:vz7DqmRsXTCSa6pNxXwQ1IYeAZgdIsua+DZU+o+SX3Y=
 | 
				
			||||||
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
 | 
					k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
 | 
				
			||||||
k8s.io/apiextensions-apiserver v0.21.1/go.mod h1:KESQFCGjqVcVsZ9g0xX5bacMjyX5emuWcS2arzdEouA=
 | 
					k8s.io/apiextensions-apiserver v0.21.2 h1:+exKMRep4pDrphEafRvpEi79wTnCFMqKf8LBtlA3yrE=
 | 
				
			||||||
k8s.io/apimachinery v0.21.1 h1:Q6XuHGlj2xc+hlMCvqyYfbv3H7SRGn2c8NycxJquDVs=
 | 
					k8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA=
 | 
				
			||||||
k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
 | 
					k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
 | 
				
			||||||
k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY=
 | 
					k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII=
 | 
				
			||||||
k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs=
 | 
					k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=
 | 
				
			||||||
k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q=
 | 
					k8s.io/apiserver v0.21.2/go.mod h1:lN4yBoGyiNT7SC1dmNk0ue6a5Wi6O3SWOIw91TsucQw=
 | 
				
			||||||
k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA=
 | 
					k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0=
 | 
				
			||||||
 | 
					k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
 | 
				
			||||||
 | 
					k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U=
 | 
				
			||||||
 | 
					k8s.io/component-base v0.21.2/go.mod h1:9lvmIThzdlrJj5Hp8Z/TOgIkdfsNARQ1pT+3PByuiuc=
 | 
				
			||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 | 
					k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 | 
				
			||||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 | 
					k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 | 
				
			||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 | 
					k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 | 
				
			||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
 | 
					k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
 | 
				
			||||||
k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts=
 | 
					k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts=
 | 
				
			||||||
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 | 
					k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 | 
				
			||||||
 | 
					k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0=
 | 
				
			||||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
 | 
					k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
 | 
				
			||||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 | 
					k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 | 
				
			||||||
 | 
					k8s.io/utils v0.0.0-20210527160623-6fdb442a123b h1:MSqsVQ3pZvPGTqCjptfimO2WjG7A9un2zcpiHkA6M/s=
 | 
				
			||||||
k8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 | 
					k8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 | 
				
			||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 | 
					rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 | 
				
			||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 | 
					rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 | 
				
			||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 | 
					rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 | 
				
			||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 | 
					sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 | 
				
			||||||
sigs.k8s.io/controller-runtime v0.9.0 h1:ZIZ/dtpboPSbZYY7uUz2OzrkaBTOThx2yekLtpGB+zY=
 | 
					sigs.k8s.io/controller-runtime v0.9.2/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=
 | 
				
			||||||
sigs.k8s.io/controller-runtime v0.9.0/go.mod h1:TgkfvrhhEw3PlI0BRL/5xM+89y3/yc0ZDfdbTl84si8=
 | 
					sigs.k8s.io/controller-runtime v0.9.3 h1:n075bHQ1wb8hpX7C27pNrqsb0fj8mcfCQfNX+oKTbYE=
 | 
				
			||||||
 | 
					sigs.k8s.io/controller-runtime v0.9.3/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=
 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8=
 | 
					 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
				
			||||||
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
 | 
				
			||||||
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 | 
				
			||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 | 
					sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 | 
				
			||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 | 
					sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 | 
				
			||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 | 
					sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,10 @@ limitations under the License.
 | 
				
			||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/apis/meta"
 | 
						"github.com/fluxcd/pkg/apis/meta"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/conditions"
 | 
				
			||||||
	apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
						apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -119,7 +122,7 @@ func BucketProgressing(bucket Bucket) Bucket {
 | 
				
			||||||
	bucket.Status.ObservedGeneration = bucket.Generation
 | 
						bucket.Status.ObservedGeneration = bucket.Generation
 | 
				
			||||||
	bucket.Status.URL = ""
 | 
						bucket.Status.URL = ""
 | 
				
			||||||
	bucket.Status.Conditions = []metav1.Condition{}
 | 
						bucket.Status.Conditions = []metav1.Condition{}
 | 
				
			||||||
	meta.SetResourceCondition(&bucket, meta.ReadyCondition, metav1.ConditionUnknown, meta.ProgressingReason, "reconciliation in progress")
 | 
						conditions.MarkUnknown(&bucket, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
 | 
				
			||||||
	return bucket
 | 
						return bucket
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,14 +132,14 @@ func BucketProgressing(bucket Bucket) Bucket {
 | 
				
			||||||
func BucketReady(bucket Bucket, artifact Artifact, url, reason, message string) Bucket {
 | 
					func BucketReady(bucket Bucket, artifact Artifact, url, reason, message string) Bucket {
 | 
				
			||||||
	bucket.Status.Artifact = &artifact
 | 
						bucket.Status.Artifact = &artifact
 | 
				
			||||||
	bucket.Status.URL = url
 | 
						bucket.Status.URL = url
 | 
				
			||||||
	meta.SetResourceCondition(&bucket, meta.ReadyCondition, metav1.ConditionTrue, reason, message)
 | 
						conditions.MarkTrue(&bucket, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return bucket
 | 
						return bucket
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BucketNotReady sets the meta.ReadyCondition on the Bucket to 'False', with
 | 
					// BucketNotReady sets the meta.ReadyCondition on the Bucket to 'False', with
 | 
				
			||||||
// the given reason and message. It returns the modified Bucket.
 | 
					// the given reason and message. It returns the modified Bucket.
 | 
				
			||||||
func BucketNotReady(bucket Bucket, reason, message string) Bucket {
 | 
					func BucketNotReady(bucket Bucket, reason, message string) Bucket {
 | 
				
			||||||
	meta.SetResourceCondition(&bucket, meta.ReadyCondition, metav1.ConditionFalse, reason, message)
 | 
						conditions.MarkFalse(&bucket, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return bucket
 | 
						return bucket
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,22 +154,38 @@ func BucketReadyMessage(bucket Bucket) string {
 | 
				
			||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetArtifact returns the latest artifact from the source if present in the
 | 
					// GetConditions returns the status conditions of the object.
 | 
				
			||||||
// status sub-resource.
 | 
					func (in Bucket) GetConditions() []metav1.Condition {
 | 
				
			||||||
 | 
						return in.Status.Conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetConditions sets the status conditions on the object.
 | 
				
			||||||
 | 
					func (in *Bucket) SetConditions(conditions []metav1.Condition) {
 | 
				
			||||||
 | 
						in.Status.Conditions = conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetRequeueAfter returns the duration after which the source must be reconciled again.
 | 
				
			||||||
 | 
					func (in Bucket) GetRequeueAfter() time.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetInterval returns the interval at which the source is reconciled.
 | 
				
			||||||
 | 
					// Deprecated: use GetRequeueAfter instead.
 | 
				
			||||||
 | 
					func (in Bucket) GetInterval() metav1.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
 | 
				
			||||||
func (in *Bucket) GetArtifact() *Artifact {
 | 
					func (in *Bucket) GetArtifact() *Artifact {
 | 
				
			||||||
	return in.Status.Artifact
 | 
						return in.Status.Artifact
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStatusConditions returns a pointer to the Status.Conditions slice
 | 
					// GetStatusConditions returns a pointer to the Status.Conditions slice.
 | 
				
			||||||
 | 
					// Deprecated: use GetConditions instead.
 | 
				
			||||||
func (in *Bucket) GetStatusConditions() *[]metav1.Condition {
 | 
					func (in *Bucket) GetStatusConditions() *[]metav1.Condition {
 | 
				
			||||||
	return &in.Status.Conditions
 | 
						return &in.Status.Conditions
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetInterval returns the interval at which the source is updated.
 | 
					 | 
				
			||||||
func (in *Bucket) GetInterval() metav1.Duration {
 | 
					 | 
				
			||||||
	return in.Spec.Interval
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +genclient
 | 
					// +genclient
 | 
				
			||||||
// +genclient:Namespaced
 | 
					// +genclient:Namespaced
 | 
				
			||||||
// +kubebuilder:object:root=true
 | 
					// +kubebuilder:object:root=true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,8 +17,9 @@ limitations under the License.
 | 
				
			||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/apis/meta"
 | 
						"github.com/fluxcd/pkg/apis/meta"
 | 
				
			||||||
	apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
					 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +33,30 @@ const (
 | 
				
			||||||
	LibGit2Implementation = "libgit2"
 | 
						LibGit2Implementation = "libgit2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// ArtifactUnavailableCondition indicates there is no Artifact available for the Source.
 | 
				
			||||||
 | 
						// This is a "negative polarity" or "abnormal-true" type, and is only present on the resource if it is True.
 | 
				
			||||||
 | 
						ArtifactUnavailableCondition string = "ArtifactUnavailable"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CheckoutFailedCondition indicates a transient or persistent checkout failure. If True, observations on the
 | 
				
			||||||
 | 
						// upstream Source revision are not possible, and the Artifact available for the Source may be outdated.
 | 
				
			||||||
 | 
						// This is a "negative polarity" or "abnormal-true" type, and is only present on the resource if it is True.
 | 
				
			||||||
 | 
						CheckoutFailedCondition string = "CheckoutFailed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// SourceVerifiedCondition indicates the integrity of the Source has been verified. If True, the integrity check
 | 
				
			||||||
 | 
						// succeeded. If False, it failed. The Condition is only present on the resource if the integrity has been verified.
 | 
				
			||||||
 | 
						SourceVerifiedCondition string = "SourceVerified"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// IncludeUnavailableCondition indicates one of the includes is not available. For example, because it does not
 | 
				
			||||||
 | 
						// exist, or does not have an Artifact.
 | 
				
			||||||
 | 
						// This is a "negative polarity" or "abnormal-true" type, and is only present on the resource if it is True.
 | 
				
			||||||
 | 
						IncludeUnavailableCondition string = "IncludeUnavailable"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ArtifactOutdatedCondition indicates the current Artifact of the Source is outdated.
 | 
				
			||||||
 | 
						// This is a "negative polarity" or "abnormal-true" type, and is only present on the resource if it is True.
 | 
				
			||||||
 | 
						ArtifactOutdatedCondition string = "ArtifactOutdated"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositorySpec defines the desired state of a Git repository.
 | 
					// GitRepositorySpec defines the desired state of a Git repository.
 | 
				
			||||||
type GitRepositorySpec struct {
 | 
					type GitRepositorySpec struct {
 | 
				
			||||||
	// The repository URL, can be a HTTP/S or SSH address.
 | 
						// The repository URL, can be a HTTP/S or SSH address.
 | 
				
			||||||
| 
						 | 
					@ -40,10 +65,8 @@ type GitRepositorySpec struct {
 | 
				
			||||||
	URL string `json:"url"`
 | 
						URL string `json:"url"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The secret name containing the Git credentials.
 | 
						// The secret name containing the Git credentials.
 | 
				
			||||||
	// For HTTPS repositories the secret must contain username and password
 | 
						// For HTTPS repositories the secret must contain username and password fields.
 | 
				
			||||||
	// fields.
 | 
						// For SSH repositories the secret must contain 'identity', 'identity.pub' and 'known_hosts' fields.
 | 
				
			||||||
	// For SSH repositories the secret must contain identity, identity.pub and
 | 
					 | 
				
			||||||
	// known_hosts fields.
 | 
					 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
 | 
						SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,16 +84,16 @@ type GitRepositorySpec struct {
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Reference *GitRepositoryRef `json:"ref,omitempty"`
 | 
						Reference *GitRepositoryRef `json:"ref,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Verify OpenPGP signature for the Git commit HEAD points to.
 | 
						// Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Verification *GitRepositoryVerification `json:"verify,omitempty"`
 | 
						Verification *GitRepositoryVerification `json:"verify,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Ignore overrides the set of excluded patterns in the .sourceignore format
 | 
						// Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
 | 
				
			||||||
	// (which is the same as .gitignore). If not provided, a default will be used,
 | 
						// If not provided, a default will be used, consult the documentation for your version to find out what those are.
 | 
				
			||||||
	// consult the documentation for your version to find out what those are.
 | 
					 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Ignore *string `json:"ignore,omitempty"`
 | 
						Ignore *string `json:"ignore,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Suspend tells the controller to suspend the reconciliation of this source.
 | 
				
			||||||
	// This flag tells the controller to suspend the reconciliation of this source.
 | 
						// This flag tells the controller to suspend the reconciliation of this source.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Suspend bool `json:"suspend,omitempty"`
 | 
						Suspend bool `json:"suspend,omitempty"`
 | 
				
			||||||
| 
						 | 
					@ -82,13 +105,13 @@ type GitRepositorySpec struct {
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	GitImplementation string `json:"gitImplementation,omitempty"`
 | 
						GitImplementation string `json:"gitImplementation,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// When enabled, after the clone is created, initializes all submodules within,
 | 
						// When enabled, after the clone is created, initializes all submodules within, using their default settings.
 | 
				
			||||||
	// using their default settings.
 | 
					 | 
				
			||||||
	// This option is available only when using the 'go-git' GitImplementation.
 | 
						// This option is available only when using the 'go-git' GitImplementation.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	RecurseSubmodules bool `json:"recurseSubmodules,omitempty"`
 | 
						RecurseSubmodules bool `json:"recurseSubmodules,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Extra git repositories to map into the repository
 | 
						// Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
 | 
				
			||||||
 | 
						// this resource.
 | 
				
			||||||
	Include []GitRepositoryInclude `json:"include,omitempty"`
 | 
						Include []GitRepositoryInclude `json:"include,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,11 +162,11 @@ type GitRepositoryRef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositoryVerification defines the OpenPGP signature verification process.
 | 
					// GitRepositoryVerification defines the OpenPGP signature verification process.
 | 
				
			||||||
type GitRepositoryVerification struct {
 | 
					type GitRepositoryVerification struct {
 | 
				
			||||||
	// Mode describes what git object should be verified, currently ('head').
 | 
						// Mode describes what Git object should be verified, currently ('head').
 | 
				
			||||||
	// +kubebuilder:validation:Enum=head
 | 
						// +kubebuilder:validation:Enum=head
 | 
				
			||||||
	Mode string `json:"mode"`
 | 
						Mode string `json:"mode"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The secret name containing the public keys of all trusted Git authors.
 | 
						// SecretRef containing the public keys of all trusted Git authors.
 | 
				
			||||||
	SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"`
 | 
						SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,8 +180,7 @@ type GitRepositoryStatus struct {
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Conditions []metav1.Condition `json:"conditions,omitempty"`
 | 
						Conditions []metav1.Condition `json:"conditions,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// URL is the download link for the artifact output of the last repository
 | 
						// URL is the download link for the artifact output of the last repository sync.
 | 
				
			||||||
	// sync.
 | 
					 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	URL string `json:"url,omitempty"`
 | 
						URL string `json:"url,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,73 +196,45 @@ type GitRepositoryStatus struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// GitOperationSucceedReason represents the fact that the git clone, pull
 | 
						// GitOperationSucceedReason represents the fact that the git clone, pull and checkout operations succeeded.
 | 
				
			||||||
	// and checkout operations succeeded.
 | 
					 | 
				
			||||||
	GitOperationSucceedReason string = "GitOperationSucceed"
 | 
						GitOperationSucceedReason string = "GitOperationSucceed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// GitOperationFailedReason represents the fact that the git clone, pull or
 | 
						// GitOperationFailedReason represents the fact that the git clone, pull or checkout operations failed.
 | 
				
			||||||
	// checkout operations failed.
 | 
					 | 
				
			||||||
	GitOperationFailedReason string = "GitOperationFailed"
 | 
						GitOperationFailedReason string = "GitOperationFailed"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositoryProgressing resets the conditions of the GitRepository to
 | 
					// GetConditions returns the status conditions of the object.
 | 
				
			||||||
// metav1.Condition of type meta.ReadyCondition with status 'Unknown' and
 | 
					func (in GitRepository) GetConditions() []metav1.Condition {
 | 
				
			||||||
// meta.ProgressingReason reason and message. It returns the modified
 | 
						return in.Status.Conditions
 | 
				
			||||||
// GitRepository.
 | 
					 | 
				
			||||||
func GitRepositoryProgressing(repository GitRepository) GitRepository {
 | 
					 | 
				
			||||||
	repository.Status.ObservedGeneration = repository.Generation
 | 
					 | 
				
			||||||
	repository.Status.URL = ""
 | 
					 | 
				
			||||||
	repository.Status.Conditions = []metav1.Condition{}
 | 
					 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionUnknown, meta.ProgressingReason, "reconciliation in progress")
 | 
					 | 
				
			||||||
	return repository
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositoryReady sets the given Artifact and URL on the GitRepository and
 | 
					// SetConditions sets the status conditions on the object.
 | 
				
			||||||
// sets the meta.ReadyCondition to 'True', with the given reason and message. It
 | 
					func (in *GitRepository) SetConditions(conditions []metav1.Condition) {
 | 
				
			||||||
// returns the modified GitRepository.
 | 
						in.Status.Conditions = conditions
 | 
				
			||||||
func GitRepositoryReady(repository GitRepository, artifact Artifact, includedArtifacts []*Artifact, url, reason, message string) GitRepository {
 | 
					 | 
				
			||||||
	repository.Status.Artifact = &artifact
 | 
					 | 
				
			||||||
	repository.Status.IncludedArtifacts = includedArtifacts
 | 
					 | 
				
			||||||
	repository.Status.URL = url
 | 
					 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionTrue, reason, message)
 | 
					 | 
				
			||||||
	return repository
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositoryNotReady sets the meta.ReadyCondition on the given GitRepository
 | 
					// GetRequeueAfter returns the duration after which the source must be reconciled again.
 | 
				
			||||||
// to 'False', with the given reason and message. It returns the modified
 | 
					func (in GitRepository) GetRequeueAfter() time.Duration {
 | 
				
			||||||
// GitRepository.
 | 
						return in.Spec.Interval.Duration
 | 
				
			||||||
func GitRepositoryNotReady(repository GitRepository, reason, message string) GitRepository {
 | 
					 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionFalse, reason, message)
 | 
					 | 
				
			||||||
	return repository
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GitRepositoryReadyMessage returns the message of the metav1.Condition of type
 | 
					// GetInterval returns the interval at which the source is reconciled.
 | 
				
			||||||
// meta.ReadyCondition with status 'True' if present, or an empty string.
 | 
					// Deprecated: use GetRequeueAfter instead.
 | 
				
			||||||
func GitRepositoryReadyMessage(repository GitRepository) string {
 | 
					func (in GitRepository) GetInterval() metav1.Duration {
 | 
				
			||||||
	if c := apimeta.FindStatusCondition(repository.Status.Conditions, meta.ReadyCondition); c != nil {
 | 
						return in.Spec.Interval
 | 
				
			||||||
		if c.Status == metav1.ConditionTrue {
 | 
					 | 
				
			||||||
			return c.Message
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetArtifact returns the latest artifact from the source if present in the
 | 
					// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
 | 
				
			||||||
// status sub-resource.
 | 
					 | 
				
			||||||
func (in *GitRepository) GetArtifact() *Artifact {
 | 
					func (in *GitRepository) GetArtifact() *Artifact {
 | 
				
			||||||
	return in.Status.Artifact
 | 
						return in.Status.Artifact
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStatusConditions returns a pointer to the Status.Conditions slice
 | 
					// GetStatusConditions returns a pointer to the Status.Conditions slice.
 | 
				
			||||||
 | 
					// Deprecated: use GetConditions instead.
 | 
				
			||||||
func (in *GitRepository) GetStatusConditions() *[]metav1.Condition {
 | 
					func (in *GitRepository) GetStatusConditions() *[]metav1.Condition {
 | 
				
			||||||
	return &in.Status.Conditions
 | 
						return &in.Status.Conditions
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetInterval returns the interval at which the source is updated.
 | 
					 | 
				
			||||||
func (in *GitRepository) GetInterval() metav1.Duration {
 | 
					 | 
				
			||||||
	return in.Spec.Interval
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +genclient
 | 
					// +genclient
 | 
				
			||||||
// +genclient:Namespaced
 | 
					// +genclient:Namespaced
 | 
				
			||||||
// +kubebuilder:object:root=true
 | 
					// +kubebuilder:object:root=true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,10 @@ limitations under the License.
 | 
				
			||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/apis/meta"
 | 
						"github.com/fluxcd/pkg/apis/meta"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/conditions"
 | 
				
			||||||
	apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
						apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -129,7 +132,7 @@ func HelmChartProgressing(chart HelmChart) HelmChart {
 | 
				
			||||||
	chart.Status.ObservedGeneration = chart.Generation
 | 
						chart.Status.ObservedGeneration = chart.Generation
 | 
				
			||||||
	chart.Status.URL = ""
 | 
						chart.Status.URL = ""
 | 
				
			||||||
	chart.Status.Conditions = []metav1.Condition{}
 | 
						chart.Status.Conditions = []metav1.Condition{}
 | 
				
			||||||
	meta.SetResourceCondition(&chart, meta.ReadyCondition, metav1.ConditionUnknown, meta.ProgressingReason, "reconciliation in progress")
 | 
						conditions.MarkUnknown(&chart, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
 | 
				
			||||||
	return chart
 | 
						return chart
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,7 +142,7 @@ func HelmChartProgressing(chart HelmChart) HelmChart {
 | 
				
			||||||
func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message string) HelmChart {
 | 
					func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message string) HelmChart {
 | 
				
			||||||
	chart.Status.Artifact = &artifact
 | 
						chart.Status.Artifact = &artifact
 | 
				
			||||||
	chart.Status.URL = url
 | 
						chart.Status.URL = url
 | 
				
			||||||
	meta.SetResourceCondition(&chart, meta.ReadyCondition, metav1.ConditionTrue, reason, message)
 | 
						conditions.MarkTrue(&chart, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return chart
 | 
						return chart
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +150,7 @@ func HelmChartReady(chart HelmChart, artifact Artifact, url, reason, message str
 | 
				
			||||||
// 'False', with the given reason and message. It returns the modified
 | 
					// 'False', with the given reason and message. It returns the modified
 | 
				
			||||||
// HelmChart.
 | 
					// HelmChart.
 | 
				
			||||||
func HelmChartNotReady(chart HelmChart, reason, message string) HelmChart {
 | 
					func HelmChartNotReady(chart HelmChart, reason, message string) HelmChart {
 | 
				
			||||||
	meta.SetResourceCondition(&chart, meta.ReadyCondition, metav1.ConditionFalse, reason, message)
 | 
						conditions.MarkFalse(&chart, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return chart
 | 
						return chart
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,22 +165,32 @@ func HelmChartReadyMessage(chart HelmChart) string {
 | 
				
			||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetArtifact returns the latest artifact from the source if present in the
 | 
					// GetConditions returns the status conditions of the object.
 | 
				
			||||||
// status sub-resource.
 | 
					func (in HelmChart) GetConditions() []metav1.Condition {
 | 
				
			||||||
 | 
						return in.Status.Conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetConditions sets the status conditions on the object.
 | 
				
			||||||
 | 
					func (in *HelmChart) SetConditions(conditions []metav1.Condition) {
 | 
				
			||||||
 | 
						in.Status.Conditions = conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetRequeueAfter returns the duration after which the source must be reconciled again.
 | 
				
			||||||
 | 
					func (in HelmChart) GetRequeueAfter() time.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetInterval returns the interval at which the source is reconciled.
 | 
				
			||||||
 | 
					// Deprecated: use GetRequeueAfter instead.
 | 
				
			||||||
 | 
					func (in HelmChart) GetInterval() metav1.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
 | 
				
			||||||
func (in *HelmChart) GetArtifact() *Artifact {
 | 
					func (in *HelmChart) GetArtifact() *Artifact {
 | 
				
			||||||
	return in.Status.Artifact
 | 
						return in.Status.Artifact
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStatusConditions returns a pointer to the Status.Conditions slice
 | 
					 | 
				
			||||||
func (in *HelmChart) GetStatusConditions() *[]metav1.Condition {
 | 
					 | 
				
			||||||
	return &in.Status.Conditions
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetInterval returns the interval at which the source is updated.
 | 
					 | 
				
			||||||
func (in *HelmChart) GetInterval() metav1.Duration {
 | 
					 | 
				
			||||||
	return in.Spec.Interval
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetValuesFiles returns a merged list of ValuesFiles.
 | 
					// GetValuesFiles returns a merged list of ValuesFiles.
 | 
				
			||||||
func (in *HelmChart) GetValuesFiles() []string {
 | 
					func (in *HelmChart) GetValuesFiles() []string {
 | 
				
			||||||
	valuesFiles := in.Spec.ValuesFiles
 | 
						valuesFiles := in.Spec.ValuesFiles
 | 
				
			||||||
| 
						 | 
					@ -189,6 +202,12 @@ func (in *HelmChart) GetValuesFiles() []string {
 | 
				
			||||||
	return valuesFiles
 | 
						return valuesFiles
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetStatusConditions returns a pointer to the Status.Conditions slice.
 | 
				
			||||||
 | 
					// Deprecated: use GetConditions instead.
 | 
				
			||||||
 | 
					func (in *HelmChart) GetStatusConditions() *[]metav1.Condition {
 | 
				
			||||||
 | 
						return &in.Status.Conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// +genclient
 | 
					// +genclient
 | 
				
			||||||
// +genclient:Namespaced
 | 
					// +genclient:Namespaced
 | 
				
			||||||
// +kubebuilder:object:root=true
 | 
					// +kubebuilder:object:root=true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,10 @@ limitations under the License.
 | 
				
			||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/apis/meta"
 | 
						"github.com/fluxcd/pkg/apis/meta"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/conditions"
 | 
				
			||||||
	apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
						apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -107,7 +110,7 @@ func HelmRepositoryProgressing(repository HelmRepository) HelmRepository {
 | 
				
			||||||
	repository.Status.ObservedGeneration = repository.Generation
 | 
						repository.Status.ObservedGeneration = repository.Generation
 | 
				
			||||||
	repository.Status.URL = ""
 | 
						repository.Status.URL = ""
 | 
				
			||||||
	repository.Status.Conditions = []metav1.Condition{}
 | 
						repository.Status.Conditions = []metav1.Condition{}
 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionUnknown, meta.ProgressingReason, "reconciliation in progress")
 | 
						conditions.MarkUnknown(&repository, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
 | 
				
			||||||
	return repository
 | 
						return repository
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +120,7 @@ func HelmRepositoryProgressing(repository HelmRepository) HelmRepository {
 | 
				
			||||||
func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reason, message string) HelmRepository {
 | 
					func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reason, message string) HelmRepository {
 | 
				
			||||||
	repository.Status.Artifact = &artifact
 | 
						repository.Status.Artifact = &artifact
 | 
				
			||||||
	repository.Status.URL = url
 | 
						repository.Status.URL = url
 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionTrue, reason, message)
 | 
						conditions.MarkTrue(&repository, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return repository
 | 
						return repository
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,7 +128,7 @@ func HelmRepositoryReady(repository HelmRepository, artifact Artifact, url, reas
 | 
				
			||||||
// HelmRepository to 'False', with the given reason and message. It returns the
 | 
					// HelmRepository to 'False', with the given reason and message. It returns the
 | 
				
			||||||
// modified HelmRepository.
 | 
					// modified HelmRepository.
 | 
				
			||||||
func HelmRepositoryNotReady(repository HelmRepository, reason, message string) HelmRepository {
 | 
					func HelmRepositoryNotReady(repository HelmRepository, reason, message string) HelmRepository {
 | 
				
			||||||
	meta.SetResourceCondition(&repository, meta.ReadyCondition, metav1.ConditionFalse, reason, message)
 | 
						conditions.MarkFalse(&repository, meta.ReadyCondition, reason, message)
 | 
				
			||||||
	return repository
 | 
						return repository
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,22 +143,38 @@ func HelmRepositoryReadyMessage(repository HelmRepository) string {
 | 
				
			||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetArtifact returns the latest artifact from the source if present in the
 | 
					// GetConditions returns the status conditions of the object.
 | 
				
			||||||
// status sub-resource.
 | 
					func (in HelmRepository) GetConditions() []metav1.Condition {
 | 
				
			||||||
 | 
						return in.Status.Conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetConditions sets the status conditions on the object.
 | 
				
			||||||
 | 
					func (in *HelmRepository) SetConditions(conditions []metav1.Condition) {
 | 
				
			||||||
 | 
						in.Status.Conditions = conditions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetRequeueAfter returns the duration after which the source must be reconciled again.
 | 
				
			||||||
 | 
					func (in HelmRepository) GetRequeueAfter() time.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetInterval returns the interval at which the source is reconciled.
 | 
				
			||||||
 | 
					// Deprecated: use GetRequeueAfter instead.
 | 
				
			||||||
 | 
					func (in HelmRepository) GetInterval() metav1.Duration {
 | 
				
			||||||
 | 
						return in.Spec.Interval
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetArtifact returns the latest artifact from the source if present in the status sub-resource.
 | 
				
			||||||
func (in *HelmRepository) GetArtifact() *Artifact {
 | 
					func (in *HelmRepository) GetArtifact() *Artifact {
 | 
				
			||||||
	return in.Status.Artifact
 | 
						return in.Status.Artifact
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStatusConditions returns a pointer to the Status.Conditions slice
 | 
					// GetStatusConditions returns a pointer to the Status.Conditions slice.
 | 
				
			||||||
 | 
					// Deprecated: use GetConditions instead.
 | 
				
			||||||
func (in *HelmRepository) GetStatusConditions() *[]metav1.Condition {
 | 
					func (in *HelmRepository) GetStatusConditions() *[]metav1.Condition {
 | 
				
			||||||
	return &in.Status.Conditions
 | 
						return &in.Status.Conditions
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetInterval returns the interval at which the source is updated.
 | 
					 | 
				
			||||||
func (in *HelmRepository) GetInterval() metav1.Duration {
 | 
					 | 
				
			||||||
	return in.Spec.Interval
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +genclient
 | 
					// +genclient
 | 
				
			||||||
// +genclient:Namespaced
 | 
					// +genclient:Namespaced
 | 
				
			||||||
// +kubebuilder:object:root=true
 | 
					// +kubebuilder:object:root=true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,8 @@ limitations under the License.
 | 
				
			||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,9 +31,12 @@ const (
 | 
				
			||||||
// Source interface must be supported by all API types.
 | 
					// Source interface must be supported by all API types.
 | 
				
			||||||
// +k8s:deepcopy-gen=false
 | 
					// +k8s:deepcopy-gen=false
 | 
				
			||||||
type Source interface {
 | 
					type Source interface {
 | 
				
			||||||
 | 
						// GetRequeueAfter returns the duration after which the source must be reconciled again.
 | 
				
			||||||
 | 
						GetRequeueAfter() time.Duration
 | 
				
			||||||
	// GetArtifact returns the latest artifact from the source if present in the
 | 
						// GetArtifact returns the latest artifact from the source if present in the
 | 
				
			||||||
	// status sub-resource.
 | 
						// status sub-resource.
 | 
				
			||||||
	GetArtifact() *Artifact
 | 
						GetArtifact() *Artifact
 | 
				
			||||||
	// GetInterval returns the interval at which the source is updated.
 | 
						// GetInterval returns the interval at which the source is updated.
 | 
				
			||||||
 | 
						// Deprecated: use GetRequeueAfter instead.
 | 
				
			||||||
	GetInterval() metav1.Duration
 | 
						GetInterval() metav1.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ spec:
 | 
				
			||||||
                description: The name of the secret containing authentication credentials for the Bucket.
 | 
					                description: The name of the secret containing authentication credentials for the Bucket.
 | 
				
			||||||
                properties:
 | 
					                properties:
 | 
				
			||||||
                  name:
 | 
					                  name:
 | 
				
			||||||
                    description: Name of the referent
 | 
					                    description: Name of the referent.
 | 
				
			||||||
                    type: string
 | 
					                    type: string
 | 
				
			||||||
                required:
 | 
					                required:
 | 
				
			||||||
                - name
 | 
					                - name
 | 
				
			||||||
| 
						 | 
					@ -162,7 +162,7 @@ spec:
 | 
				
			||||||
                  type: object
 | 
					                  type: object
 | 
				
			||||||
                type: array
 | 
					                type: array
 | 
				
			||||||
              lastHandledReconcileAt:
 | 
					              lastHandledReconcileAt:
 | 
				
			||||||
                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected.
 | 
					                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected.
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              observedGeneration:
 | 
					              observedGeneration:
 | 
				
			||||||
                description: ObservedGeneration is the last observed generation.
 | 
					                description: ObservedGeneration is the last observed generation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ spec:
 | 
				
			||||||
                description: Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are.
 | 
					                description: Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are.
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              include:
 | 
					              include:
 | 
				
			||||||
                description: Extra git repositories to map into the repository
 | 
					                description: Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for this resource.
 | 
				
			||||||
                items:
 | 
					                items:
 | 
				
			||||||
                  description: GitRepositoryInclude defines a source with a from and to path.
 | 
					                  description: GitRepositoryInclude defines a source with a from and to path.
 | 
				
			||||||
                  properties:
 | 
					                  properties:
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ spec:
 | 
				
			||||||
                      description: Reference to a GitRepository to include.
 | 
					                      description: Reference to a GitRepository to include.
 | 
				
			||||||
                      properties:
 | 
					                      properties:
 | 
				
			||||||
                        name:
 | 
					                        name:
 | 
				
			||||||
                          description: Name of the referent
 | 
					                          description: Name of the referent.
 | 
				
			||||||
                          type: string
 | 
					                          type: string
 | 
				
			||||||
                      required:
 | 
					                      required:
 | 
				
			||||||
                      - name
 | 
					                      - name
 | 
				
			||||||
| 
						 | 
					@ -105,16 +105,16 @@ spec:
 | 
				
			||||||
                    type: string
 | 
					                    type: string
 | 
				
			||||||
                type: object
 | 
					                type: object
 | 
				
			||||||
              secretRef:
 | 
					              secretRef:
 | 
				
			||||||
                description: The secret name containing the Git credentials. For HTTPS repositories the secret must contain username and password fields. For SSH repositories the secret must contain identity, identity.pub and known_hosts fields.
 | 
					                description: The secret name containing the Git credentials. For HTTPS repositories the secret must contain username and password fields. For SSH repositories the secret must contain 'identity', 'identity.pub' and 'known_hosts' fields.
 | 
				
			||||||
                properties:
 | 
					                properties:
 | 
				
			||||||
                  name:
 | 
					                  name:
 | 
				
			||||||
                    description: Name of the referent
 | 
					                    description: Name of the referent.
 | 
				
			||||||
                    type: string
 | 
					                    type: string
 | 
				
			||||||
                required:
 | 
					                required:
 | 
				
			||||||
                - name
 | 
					                - name
 | 
				
			||||||
                type: object
 | 
					                type: object
 | 
				
			||||||
              suspend:
 | 
					              suspend:
 | 
				
			||||||
                description: This flag tells the controller to suspend the reconciliation of this source.
 | 
					                description: Suspend tells the controller to suspend the reconciliation of this source. This flag tells the controller to suspend the reconciliation of this source.
 | 
				
			||||||
                type: boolean
 | 
					                type: boolean
 | 
				
			||||||
              timeout:
 | 
					              timeout:
 | 
				
			||||||
                default: 20s
 | 
					                default: 20s
 | 
				
			||||||
| 
						 | 
					@ -125,18 +125,18 @@ spec:
 | 
				
			||||||
                pattern: ^(http|https|ssh)://
 | 
					                pattern: ^(http|https|ssh)://
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              verify:
 | 
					              verify:
 | 
				
			||||||
                description: Verify OpenPGP signature for the Git commit HEAD points to.
 | 
					                description: Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.
 | 
				
			||||||
                properties:
 | 
					                properties:
 | 
				
			||||||
                  mode:
 | 
					                  mode:
 | 
				
			||||||
                    description: Mode describes what git object should be verified, currently ('head').
 | 
					                    description: Mode describes what Git object should be verified, currently ('head').
 | 
				
			||||||
                    enum:
 | 
					                    enum:
 | 
				
			||||||
                    - head
 | 
					                    - head
 | 
				
			||||||
                    type: string
 | 
					                    type: string
 | 
				
			||||||
                  secretRef:
 | 
					                  secretRef:
 | 
				
			||||||
                    description: The secret name containing the public keys of all trusted Git authors.
 | 
					                    description: SecretRef containing the public keys of all trusted Git authors.
 | 
				
			||||||
                    properties:
 | 
					                    properties:
 | 
				
			||||||
                      name:
 | 
					                      name:
 | 
				
			||||||
                        description: Name of the referent
 | 
					                        description: Name of the referent.
 | 
				
			||||||
                        type: string
 | 
					                        type: string
 | 
				
			||||||
                    required:
 | 
					                    required:
 | 
				
			||||||
                    - name
 | 
					                    - name
 | 
				
			||||||
| 
						 | 
					@ -245,7 +245,7 @@ spec:
 | 
				
			||||||
                  type: object
 | 
					                  type: object
 | 
				
			||||||
                type: array
 | 
					                type: array
 | 
				
			||||||
              lastHandledReconcileAt:
 | 
					              lastHandledReconcileAt:
 | 
				
			||||||
                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected.
 | 
					                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected.
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              observedGeneration:
 | 
					              observedGeneration:
 | 
				
			||||||
                description: ObservedGeneration is the last observed generation.
 | 
					                description: ObservedGeneration is the last observed generation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ spec:
 | 
				
			||||||
                  type: object
 | 
					                  type: object
 | 
				
			||||||
                type: array
 | 
					                type: array
 | 
				
			||||||
              lastHandledReconcileAt:
 | 
					              lastHandledReconcileAt:
 | 
				
			||||||
                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected.
 | 
					                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected.
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              observedGeneration:
 | 
					              observedGeneration:
 | 
				
			||||||
                description: ObservedGeneration is the last observed generation.
 | 
					                description: ObservedGeneration is the last observed generation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ spec:
 | 
				
			||||||
                description: The name of the secret containing authentication credentials for the Helm repository. For HTTP/S basic auth the secret must contain username and password fields. For TLS the secret must contain a certFile and keyFile, and/or caCert fields.
 | 
					                description: The name of the secret containing authentication credentials for the Helm repository. For HTTP/S basic auth the secret must contain username and password fields. For TLS the secret must contain a certFile and keyFile, and/or caCert fields.
 | 
				
			||||||
                properties:
 | 
					                properties:
 | 
				
			||||||
                  name:
 | 
					                  name:
 | 
				
			||||||
                    description: Name of the referent
 | 
					                    description: Name of the referent.
 | 
				
			||||||
                    type: string
 | 
					                    type: string
 | 
				
			||||||
                required:
 | 
					                required:
 | 
				
			||||||
                - name
 | 
					                - name
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ spec:
 | 
				
			||||||
                  type: object
 | 
					                  type: object
 | 
				
			||||||
                type: array
 | 
					                type: array
 | 
				
			||||||
              lastHandledReconcileAt:
 | 
					              lastHandledReconcileAt:
 | 
				
			||||||
                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected.
 | 
					                description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected.
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              observedGeneration:
 | 
					              observedGeneration:
 | 
				
			||||||
                description: ObservedGeneration is the last observed generation.
 | 
					                description: ObservedGeneration is the last observed generation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,39 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Flux authors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package controllers
 | 
					package controllers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
					import sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// hasArtifactUpdated returns true if any of the revisions in the current artifacts
 | 
					type artifactSet []*sourcev1.Artifact
 | 
				
			||||||
// does not match any of the artifacts in the updated artifacts
 | 
					
 | 
				
			||||||
func hasArtifactUpdated(current []*sourcev1.Artifact, updated []*sourcev1.Artifact) bool {
 | 
					// Diff returns true if any of the revisions in the artifactSet does not match any of the given artifacts.
 | 
				
			||||||
	if len(current) != len(updated) {
 | 
					func (s artifactSet) Diff(set artifactSet) bool {
 | 
				
			||||||
 | 
						if len(s) != len(set) {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OUTER:
 | 
					outer:
 | 
				
			||||||
	for _, c := range current {
 | 
						for _, j := range s {
 | 
				
			||||||
		for _, u := range updated {
 | 
							for _, k := range set {
 | 
				
			||||||
			if u.HasRevision(c.Revision) {
 | 
								if k.HasRevision(j.Revision) {
 | 
				
			||||||
				continue OUTER
 | 
									continue outer
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,26 +1,40 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Flux authors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package controllers
 | 
					package controllers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestHasUpdated(t *testing.T) {
 | 
					func Test_artifactSet_Diff(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name     string
 | 
							name     string
 | 
				
			||||||
		current  []*sourcev1.Artifact
 | 
							current  artifactSet
 | 
				
			||||||
		updated  []*sourcev1.Artifact
 | 
							updated  artifactSet
 | 
				
			||||||
		expected bool
 | 
							expected bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "not updated single",
 | 
								name: "one artifact, no diff",
 | 
				
			||||||
			current: []*sourcev1.Artifact{
 | 
								current: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			updated: []*sourcev1.Artifact{
 | 
								updated: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -28,13 +42,13 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
			expected: false,
 | 
								expected: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "updated single",
 | 
								name: "one artifact, diff",
 | 
				
			||||||
			current: []*sourcev1.Artifact{
 | 
								current: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			updated: []*sourcev1.Artifact{
 | 
								updated: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "bar",
 | 
										Revision: "bar",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -42,8 +56,8 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
			expected: true,
 | 
								expected: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "not updated multiple",
 | 
								name: "multiple artifacts, no diff",
 | 
				
			||||||
			current: []*sourcev1.Artifact{
 | 
								current: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -51,7 +65,7 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
					Revision: "bar",
 | 
										Revision: "bar",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			updated: []*sourcev1.Artifact{
 | 
								updated: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -62,8 +76,8 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
			expected: false,
 | 
								expected: false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "updated multiple",
 | 
								name: "multiple artifacts, diff",
 | 
				
			||||||
			current: []*sourcev1.Artifact{
 | 
								current: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -71,7 +85,7 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
					Revision: "bar",
 | 
										Revision: "bar",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			updated: []*sourcev1.Artifact{
 | 
								updated: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -82,8 +96,8 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
			expected: true,
 | 
								expected: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "updated different artifact count",
 | 
								name: "different artifact count",
 | 
				
			||||||
			current: []*sourcev1.Artifact{
 | 
								current: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -91,7 +105,7 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
					Revision: "bar",
 | 
										Revision: "bar",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			updated: []*sourcev1.Artifact{
 | 
								updated: artifactSet{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Revision: "foo",
 | 
										Revision: "foo",
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -101,7 +115,7 @@ func TestHasUpdated(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
			result := hasArtifactUpdated(tt.current, tt.updated)
 | 
								result := tt.current.Diff(tt.updated)
 | 
				
			||||||
			if result != tt.expected {
 | 
								if result != tt.expected {
 | 
				
			||||||
				t.Errorf("Archive() result = %v, wantResult %v", result, tt.expected)
 | 
									t.Errorf("Archive() result = %v, wantResult %v", result, tt.expected)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,10 +169,10 @@ func (r *BucketReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
						log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
				
			||||||
		time.Now().Sub(start).String(),
 | 
							time.Now().Sub(start).String(),
 | 
				
			||||||
		bucket.GetInterval().Duration.String(),
 | 
							bucket.GetRequeueAfter().String(),
 | 
				
			||||||
	))
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ctrl.Result{RequeueAfter: bucket.GetInterval().Duration}, nil
 | 
						return ctrl.Result{RequeueAfter: bucket.GetRequeueAfter()}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *BucketReconciler) reconcile(ctx context.Context, bucket sourcev1.Bucket) (sourcev1.Bucket, error) {
 | 
					func (r *BucketReconciler) reconcile(ctx context.Context, bucket sourcev1.Bucket) (sourcev1.Bucket, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,19 +20,14 @@ import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	securejoin "github.com/cyphar/filepath-securejoin"
 | 
						securejoin "github.com/cyphar/filepath-securejoin"
 | 
				
			||||||
	"github.com/go-logr/logr"
 | 
					 | 
				
			||||||
	corev1 "k8s.io/api/core/v1"
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
	apimeta "k8s.io/apimachinery/pkg/api/meta"
 | 
					 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	kuberecorder "k8s.io/client-go/tools/record"
 | 
						kerrors "k8s.io/apimachinery/pkg/util/errors"
 | 
				
			||||||
	"k8s.io/client-go/tools/reference"
 | 
					 | 
				
			||||||
	ctrl "sigs.k8s.io/controller-runtime"
 | 
						ctrl "sigs.k8s.io/controller-runtime"
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/builder"
 | 
						"sigs.k8s.io/controller-runtime/pkg/builder"
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/client"
 | 
						"sigs.k8s.io/controller-runtime/pkg/client"
 | 
				
			||||||
| 
						 | 
					@ -41,14 +36,16 @@ import (
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/predicate"
 | 
						"sigs.k8s.io/controller-runtime/pkg/predicate"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/apis/meta"
 | 
						"github.com/fluxcd/pkg/apis/meta"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/conditions"
 | 
				
			||||||
 | 
						helper "github.com/fluxcd/pkg/runtime/controller"
 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/events"
 | 
						"github.com/fluxcd/pkg/runtime/events"
 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/metrics"
 | 
						"github.com/fluxcd/pkg/runtime/patch"
 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/predicates"
 | 
						"github.com/fluxcd/pkg/runtime/predicates"
 | 
				
			||||||
 | 
						"github.com/fluxcd/source-controller/pkg/sourceignore"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
						sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
				
			||||||
	"github.com/fluxcd/source-controller/pkg/git"
 | 
						"github.com/fluxcd/source-controller/pkg/git"
 | 
				
			||||||
	"github.com/fluxcd/source-controller/pkg/git/strategy"
 | 
						"github.com/fluxcd/source-controller/pkg/git/strategy"
 | 
				
			||||||
	"github.com/fluxcd/source-controller/pkg/sourceignore"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// +kubebuilder:rbac:groups=source.toolkit.fluxcd.io,resources=gitrepositories,verbs=get;list;watch;create;update;patch;delete
 | 
					// +kubebuilder:rbac:groups=source.toolkit.fluxcd.io,resources=gitrepositories,verbs=get;list;watch;create;update;patch;delete
 | 
				
			||||||
| 
						 | 
					@ -59,12 +56,12 @@ import (
 | 
				
			||||||
// GitRepositoryReconciler reconciles a GitRepository object
 | 
					// GitRepositoryReconciler reconciles a GitRepository object
 | 
				
			||||||
type GitRepositoryReconciler struct {
 | 
					type GitRepositoryReconciler struct {
 | 
				
			||||||
	client.Client
 | 
						client.Client
 | 
				
			||||||
	requeueDependency     time.Duration
 | 
						helper.Events
 | 
				
			||||||
	Scheme                *runtime.Scheme
 | 
						helper.Metrics
 | 
				
			||||||
	Storage               *Storage
 | 
					
 | 
				
			||||||
	EventRecorder         kuberecorder.EventRecorder
 | 
						Storage *Storage
 | 
				
			||||||
	ExternalEventRecorder *events.Recorder
 | 
					
 | 
				
			||||||
	MetricsRecorder       *metrics.Recorder
 | 
						requeueDependency time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GitRepositoryReconcilerOptions struct {
 | 
					type GitRepositoryReconcilerOptions struct {
 | 
				
			||||||
| 
						 | 
					@ -87,410 +84,509 @@ func (r *GitRepositoryReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, o
 | 
				
			||||||
		Complete(r)
 | 
							Complete(r)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 | 
					func (r *GitRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) {
 | 
				
			||||||
	start := time.Now()
 | 
						start := time.Now()
 | 
				
			||||||
	log := logr.FromContext(ctx)
 | 
						log := ctrl.LoggerFrom(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var repository sourcev1.GitRepository
 | 
						// Fetch the GitRepository
 | 
				
			||||||
	if err := r.Get(ctx, req.NamespacedName, &repository); err != nil {
 | 
						obj := &sourcev1.GitRepository{}
 | 
				
			||||||
 | 
						if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
 | 
				
			||||||
		return ctrl.Result{}, client.IgnoreNotFound(err)
 | 
							return ctrl.Result{}, client.IgnoreNotFound(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Record suspended status metric
 | 
						// Record suspended status metric
 | 
				
			||||||
	defer r.recordSuspension(ctx, repository)
 | 
						r.RecordSuspend(ctx, obj, obj.Spec.Suspend)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add our finalizer if it does not exist
 | 
						// Return early if the object is suspended
 | 
				
			||||||
	if !controllerutil.ContainsFinalizer(&repository, sourcev1.SourceFinalizer) {
 | 
						if obj.Spec.Suspend {
 | 
				
			||||||
		controllerutil.AddFinalizer(&repository, sourcev1.SourceFinalizer)
 | 
					 | 
				
			||||||
		if err := r.Update(ctx, &repository); err != nil {
 | 
					 | 
				
			||||||
			log.Error(err, "unable to register finalizer")
 | 
					 | 
				
			||||||
			return ctrl.Result{}, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Examine if the object is under deletion
 | 
					 | 
				
			||||||
	if !repository.ObjectMeta.DeletionTimestamp.IsZero() {
 | 
					 | 
				
			||||||
		return r.reconcileDelete(ctx, repository)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Return early if the object is suspended.
 | 
					 | 
				
			||||||
	if repository.Spec.Suspend {
 | 
					 | 
				
			||||||
		log.Info("Reconciliation is suspended for this object")
 | 
							log.Info("Reconciliation is suspended for this object")
 | 
				
			||||||
		return ctrl.Result{}, nil
 | 
							return ctrl.Result{}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// check dependencies
 | 
						// Initialize the patch helper
 | 
				
			||||||
	if len(repository.Spec.Include) > 0 {
 | 
						patchHelper, err := patch.NewHelper(obj, r.Client)
 | 
				
			||||||
		if err := r.checkDependencies(repository); err != nil {
 | 
						if err != nil {
 | 
				
			||||||
			repository = sourcev1.GitRepositoryNotReady(repository, meta.DependencyNotReadyReason, err.Error())
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
			if err := r.updateStatus(ctx, req, repository.Status); err != nil {
 | 
					 | 
				
			||||||
				log.Error(err, "unable to update status for dependency not ready")
 | 
					 | 
				
			||||||
				return ctrl.Result{Requeue: true}, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// we can't rely on exponential backoff because it will prolong the execution too much,
 | 
					 | 
				
			||||||
			// instead we requeue on a fix interval.
 | 
					 | 
				
			||||||
			msg := fmt.Sprintf("Dependencies do not meet ready condition, retrying in %s", r.requeueDependency.String())
 | 
					 | 
				
			||||||
			log.Info(msg)
 | 
					 | 
				
			||||||
			r.event(ctx, repository, events.EventSeverityInfo, msg)
 | 
					 | 
				
			||||||
			r.recordReadiness(ctx, repository)
 | 
					 | 
				
			||||||
			return ctrl.Result{RequeueAfter: r.requeueDependency}, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log.Info("All dependencies area ready, proceeding with reconciliation")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// record reconciliation duration
 | 
						// Always attempt to patch the object and status after each reconciliation
 | 
				
			||||||
	if r.MetricsRecorder != nil {
 | 
						defer func() {
 | 
				
			||||||
		objRef, err := reference.GetReference(r.Scheme, &repository)
 | 
							// Record the value of the reconciliation request, if any
 | 
				
			||||||
 | 
							if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok {
 | 
				
			||||||
 | 
								obj.Status.SetLastHandledReconcileRequest(v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Summarize the Ready condition based on abnormalities that may have been observed.
 | 
				
			||||||
 | 
							conditions.SetSummary(obj,
 | 
				
			||||||
 | 
								meta.ReadyCondition,
 | 
				
			||||||
 | 
								conditions.WithConditions(
 | 
				
			||||||
 | 
									sourcev1.IncludeUnavailableCondition,
 | 
				
			||||||
 | 
									sourcev1.SourceVerifiedCondition,
 | 
				
			||||||
 | 
									sourcev1.CheckoutFailedCondition,
 | 
				
			||||||
 | 
									sourcev1.ArtifactOutdatedCondition,
 | 
				
			||||||
 | 
									sourcev1.ArtifactUnavailableCondition,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								conditions.WithNegativePolarityConditions(
 | 
				
			||||||
 | 
									sourcev1.ArtifactUnavailableCondition,
 | 
				
			||||||
 | 
									sourcev1.CheckoutFailedCondition,
 | 
				
			||||||
 | 
									sourcev1.SourceVerifiedCondition,
 | 
				
			||||||
 | 
									sourcev1.IncludeUnavailableCondition,
 | 
				
			||||||
 | 
									sourcev1.ArtifactOutdatedCondition,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Patch the object, ignoring conflicts on the conditions owned by this controller
 | 
				
			||||||
 | 
							patchOpts := []patch.Option{
 | 
				
			||||||
 | 
								patch.WithOwnedConditions{
 | 
				
			||||||
 | 
									Conditions: []string{
 | 
				
			||||||
 | 
										sourcev1.ArtifactUnavailableCondition,
 | 
				
			||||||
 | 
										sourcev1.CheckoutFailedCondition,
 | 
				
			||||||
 | 
										sourcev1.IncludeUnavailableCondition,
 | 
				
			||||||
 | 
										sourcev1.ArtifactOutdatedCondition,
 | 
				
			||||||
 | 
										meta.ReadyCondition,
 | 
				
			||||||
 | 
										meta.ReconcilingCondition,
 | 
				
			||||||
 | 
										meta.StalledCondition,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Determine if the resource is still being reconciled, or if it has stalled, and record this observation
 | 
				
			||||||
 | 
							if retErr == nil && (result.IsZero() || !result.Requeue) {
 | 
				
			||||||
 | 
								// We are no longer reconciling
 | 
				
			||||||
 | 
								conditions.Delete(obj, meta.ReconcilingCondition)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// We have now observed this generation
 | 
				
			||||||
 | 
								patchOpts = append(patchOpts, patch.WithStatusObservedGeneration{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								readyCondition := conditions.Get(obj, meta.ReadyCondition)
 | 
				
			||||||
 | 
								switch readyCondition.Status {
 | 
				
			||||||
 | 
								case metav1.ConditionFalse:
 | 
				
			||||||
 | 
									// As we are no longer reconciling and the end-state is not ready, the reconciliation has stalled
 | 
				
			||||||
 | 
									conditions.MarkStalled(obj, readyCondition.Reason, readyCondition.Message)
 | 
				
			||||||
 | 
								case metav1.ConditionTrue:
 | 
				
			||||||
 | 
									// As we are no longer reconciling and the end-state is ready, the reconciliation is no longer stalled
 | 
				
			||||||
 | 
									conditions.Delete(obj, meta.StalledCondition)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Finally, patch the resource
 | 
				
			||||||
 | 
							if err := patchHelper.Patch(ctx, obj, patchOpts...); err != nil {
 | 
				
			||||||
 | 
								retErr = kerrors.NewAggregate([]error{retErr, err})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Always record readiness and duration metrics
 | 
				
			||||||
 | 
							r.Metrics.RecordReadiness(ctx, obj)
 | 
				
			||||||
 | 
							r.Metrics.RecordDuration(ctx, obj, start)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add finalizer first if not exist to avoid the race condition
 | 
				
			||||||
 | 
						// between init and delete
 | 
				
			||||||
 | 
						if !controllerutil.ContainsFinalizer(obj, sourcev1.SourceFinalizer) {
 | 
				
			||||||
 | 
							controllerutil.AddFinalizer(obj, sourcev1.SourceFinalizer)
 | 
				
			||||||
 | 
							return ctrl.Result{Requeue: true}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Examine if the object is under deletion
 | 
				
			||||||
 | 
						if !obj.ObjectMeta.DeletionTimestamp.IsZero() {
 | 
				
			||||||
 | 
							return r.reconcileDelete(ctx, obj)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reconcile actual object
 | 
				
			||||||
 | 
						return r.reconcile(ctx, obj)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reconcile steps through the actual reconciliation tasks for the object, it returns early on the first step that
 | 
				
			||||||
 | 
					// produces an error.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcile(ctx context.Context, obj *sourcev1.GitRepository) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						// Mark the resource as under reconciliation
 | 
				
			||||||
 | 
						conditions.MarkReconciling(obj, meta.ProgressingReason, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reconcile the storage data
 | 
				
			||||||
 | 
						if result, err := r.reconcileStorage(ctx, obj); err != nil || result.IsZero() {
 | 
				
			||||||
 | 
							return result, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create temp dir for Git clone
 | 
				
			||||||
 | 
						tmpDir, err := os.MkdirTemp("", fmt.Sprintf("%s-%s-%s-", obj.Kind, obj.Namespace, obj.Name))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.StorageOperationFailedReason, "Failed to create temporary directory: %s", err)
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer os.RemoveAll(tmpDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reconcile the source from upstream
 | 
				
			||||||
 | 
						var artifact sourcev1.Artifact
 | 
				
			||||||
 | 
						if result, err := r.reconcileSource(ctx, obj, &artifact, tmpDir); err != nil || result.IsZero() {
 | 
				
			||||||
 | 
							return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reconcile includes from the storage
 | 
				
			||||||
 | 
						var includes artifactSet
 | 
				
			||||||
 | 
						if result, err := r.reconcileInclude(ctx, obj, includes, tmpDir); err != nil || result.IsZero() {
 | 
				
			||||||
 | 
							return ctrl.Result{RequeueAfter: r.requeueDependency}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reconcile the artifact to storage
 | 
				
			||||||
 | 
						if result, err := r.reconcileArtifact(ctx, obj, artifact, includes, tmpDir); err != nil || result.IsZero() {
 | 
				
			||||||
 | 
							return result, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reconcileStorage ensures the current state of the storage matches the desired and previously observed state.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// All artifacts for the resource except for the current one are garbage collected from the storage.
 | 
				
			||||||
 | 
					// If the artifact in the Status object of the resource disappeared from storage, it is removed from the object.
 | 
				
			||||||
 | 
					// If the object does not have an artifact in its Status object, a v1beta1.ArtifactUnavailableCondition is set.
 | 
				
			||||||
 | 
					// If the hostname of any of the URLs on the object do not match the current storage server hostname, they are updated.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The caller should assume a failure if an error is returned, or the Result is zero.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcileStorage(ctx context.Context, obj *sourcev1.GitRepository) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						// Garbage collect previous advertised artifact(s) from storage
 | 
				
			||||||
 | 
						_ = r.garbageCollect(ctx, obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Determine if the advertised artifact is still in storage
 | 
				
			||||||
 | 
						if artifact := obj.GetArtifact(); artifact != nil && !r.Storage.ArtifactExist(*artifact) {
 | 
				
			||||||
 | 
							obj.Status.Artifact = nil
 | 
				
			||||||
 | 
							obj.Status.URL = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Record that we do not have an artifact
 | 
				
			||||||
 | 
						if obj.GetArtifact() == nil {
 | 
				
			||||||
 | 
							conditions.MarkTrue(obj, sourcev1.ArtifactUnavailableCondition, "NoArtifact", "No artifact for resource in storage")
 | 
				
			||||||
 | 
							return ctrl.Result{Requeue: true}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conditions.Delete(obj, sourcev1.ArtifactUnavailableCondition)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Always update URLs to ensure hostname is up-to-date
 | 
				
			||||||
 | 
						// TODO(hidde): we may want to send out an event only if we notice the URL has changed
 | 
				
			||||||
 | 
						r.Storage.SetArtifactURL(obj.GetArtifact())
 | 
				
			||||||
 | 
						obj.Status.URL = r.Storage.SetHostname(obj.Status.URL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reconcileSource ensures the upstream Git repository can be reached and checked out using the declared configuration,
 | 
				
			||||||
 | 
					// and observes its state.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The repository is checked out to the given dir using the defined configuration, and in case of an error during the
 | 
				
			||||||
 | 
					// checkout process (including transient errors), it records v1beta1.CheckoutFailedCondition=True and returns early.
 | 
				
			||||||
 | 
					// On a successful checkout it removes v1beta1.CheckoutFailedCondition, and compares the current revision of HEAD to the
 | 
				
			||||||
 | 
					// artifact on the object, and records v1beta1.ArtifactOutdatedCondition if they differ.
 | 
				
			||||||
 | 
					// If instructed, the signature of the commit is verified if and recorded as v1beta1.SourceVerifiedCondition. If the
 | 
				
			||||||
 | 
					// signature can not be verified or the verification fails, the Condition=False and it returns early.
 | 
				
			||||||
 | 
					// If both the checkout and signature verification are successful, the given artifact pointer is set to a new artifact
 | 
				
			||||||
 | 
					// with the available metadata.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The caller should assume a failure if an error is returned, or the Result is zero.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context,
 | 
				
			||||||
 | 
						obj *sourcev1.GitRepository, artifact *sourcev1.Artifact, dir string) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						// Configure authentication strategy to access the source
 | 
				
			||||||
 | 
						auth := &git.Auth{}
 | 
				
			||||||
 | 
						if obj.Spec.SecretRef != nil {
 | 
				
			||||||
 | 
							// Determine the auth strategy
 | 
				
			||||||
 | 
							authStrategy, err := strategy.AuthSecretStrategyForURL(obj.Spec.URL, git.CheckoutOptions{
 | 
				
			||||||
 | 
								GitImplementation: obj.Spec.GitImplementation,
 | 
				
			||||||
 | 
								RecurseSubmodules: obj.Spec.RecurseSubmodules,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								ctrl.LoggerFrom(ctx).Error(err, fmt.Sprintf("Failed to get auth strategy for Git implementation '%s'", obj.Spec.GitImplementation))
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.CheckoutFailedCondition, sourcev1.AuthenticationFailedReason,
 | 
				
			||||||
 | 
									"Failed to get auth strategy for Git implementation '%s': %s", obj.Spec.GitImplementation, err)
 | 
				
			||||||
 | 
								// Do not return error as recovery without changes is impossible
 | 
				
			||||||
 | 
								return ctrl.Result{}, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Attempt to retrieve secret
 | 
				
			||||||
 | 
							name := types.NamespacedName{
 | 
				
			||||||
 | 
								Namespace: obj.GetNamespace(),
 | 
				
			||||||
 | 
								Name:      obj.Spec.SecretRef.Name,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var secret corev1.Secret
 | 
				
			||||||
 | 
							if err = r.Client.Get(ctx, name, &secret); err != nil {
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.CheckoutFailedCondition, sourcev1.AuthenticationFailedReason,
 | 
				
			||||||
 | 
									"Failed to get secret '%s': %s", name.String(), err.Error())
 | 
				
			||||||
 | 
								r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.AuthenticationFailedReason,
 | 
				
			||||||
 | 
									"Failed to get secret '%s': %s", name.String(), err.Error())
 | 
				
			||||||
 | 
								// Return error as the world as observed may change
 | 
				
			||||||
			return ctrl.Result{}, err
 | 
								return ctrl.Result{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		defer r.MetricsRecorder.RecordDuration(*objRef, start)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set initial status
 | 
					 | 
				
			||||||
	if resetRepository, ok := r.resetStatus(repository); ok {
 | 
					 | 
				
			||||||
		repository = resetRepository
 | 
					 | 
				
			||||||
		if err := r.updateStatus(ctx, req, repository.Status); err != nil {
 | 
					 | 
				
			||||||
			log.Error(err, "unable to update status")
 | 
					 | 
				
			||||||
			return ctrl.Result{Requeue: true}, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		r.recordReadiness(ctx, repository)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// record the value of the reconciliation request, if any
 | 
					 | 
				
			||||||
	// TODO(hidde): would be better to defer this in combination with
 | 
					 | 
				
			||||||
	//   always patching the status sub-resource after a reconciliation.
 | 
					 | 
				
			||||||
	if v, ok := meta.ReconcileAnnotationValue(repository.GetAnnotations()); ok {
 | 
					 | 
				
			||||||
		repository.Status.SetLastHandledReconcileRequest(v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// purge old artifacts from storage
 | 
					 | 
				
			||||||
	if err := r.gc(repository); err != nil {
 | 
					 | 
				
			||||||
		log.Error(err, "unable to purge old artifacts")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// reconcile repository by pulling the latest Git commit
 | 
					 | 
				
			||||||
	reconciledRepository, reconcileErr := r.reconcile(ctx, *repository.DeepCopy())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// update status with the reconciliation result
 | 
					 | 
				
			||||||
	if err := r.updateStatus(ctx, req, reconciledRepository.Status); err != nil {
 | 
					 | 
				
			||||||
		log.Error(err, "unable to update status")
 | 
					 | 
				
			||||||
		return ctrl.Result{Requeue: true}, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if reconciliation failed, record the failure and requeue immediately
 | 
					 | 
				
			||||||
	if reconcileErr != nil {
 | 
					 | 
				
			||||||
		r.event(ctx, reconciledRepository, events.EventSeverityError, reconcileErr.Error())
 | 
					 | 
				
			||||||
		r.recordReadiness(ctx, reconciledRepository)
 | 
					 | 
				
			||||||
		return ctrl.Result{Requeue: true}, reconcileErr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// emit revision change event
 | 
					 | 
				
			||||||
	if repository.Status.Artifact == nil || reconciledRepository.Status.Artifact.Revision != repository.Status.Artifact.Revision {
 | 
					 | 
				
			||||||
		r.event(ctx, reconciledRepository, events.EventSeverityInfo, sourcev1.GitRepositoryReadyMessage(reconciledRepository))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.recordReadiness(ctx, reconciledRepository)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
					 | 
				
			||||||
		time.Now().Sub(start).String(),
 | 
					 | 
				
			||||||
		repository.GetInterval().Duration.String(),
 | 
					 | 
				
			||||||
	))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ctrl.Result{RequeueAfter: repository.GetInterval().Duration}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) checkDependencies(repository sourcev1.GitRepository) error {
 | 
					 | 
				
			||||||
	for _, d := range repository.Spec.Include {
 | 
					 | 
				
			||||||
		dName := types.NamespacedName{Name: d.GitRepositoryRef.Name, Namespace: repository.Namespace}
 | 
					 | 
				
			||||||
		var gr sourcev1.GitRepository
 | 
					 | 
				
			||||||
		err := r.Get(context.Background(), dName, &gr)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("unable to get '%s' dependency: %w", dName, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if len(gr.Status.Conditions) == 0 || gr.Generation != gr.Status.ObservedGeneration {
 | 
					 | 
				
			||||||
			return fmt.Errorf("dependency '%s' is not ready", dName)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if !apimeta.IsStatusConditionTrue(gr.Status.Conditions, meta.ReadyCondition) {
 | 
					 | 
				
			||||||
			return fmt.Errorf("dependency '%s' is not ready", dName)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) reconcile(ctx context.Context, repository sourcev1.GitRepository) (sourcev1.GitRepository, error) {
 | 
					 | 
				
			||||||
	// create tmp dir for the Git clone
 | 
					 | 
				
			||||||
	tmpGit, err := os.MkdirTemp("", repository.Name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		err = fmt.Errorf("tmp dir error: %w", err)
 | 
					 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer os.RemoveAll(tmpGit)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// determine auth method
 | 
					 | 
				
			||||||
	auth := &git.Auth{}
 | 
					 | 
				
			||||||
	if repository.Spec.SecretRef != nil {
 | 
					 | 
				
			||||||
		authStrategy, err := strategy.AuthSecretStrategyForURL(
 | 
					 | 
				
			||||||
			repository.Spec.URL,
 | 
					 | 
				
			||||||
			git.CheckoutOptions{
 | 
					 | 
				
			||||||
				GitImplementation: repository.Spec.GitImplementation,
 | 
					 | 
				
			||||||
				RecurseSubmodules: repository.Spec.RecurseSubmodules,
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		name := types.NamespacedName{
 | 
					 | 
				
			||||||
			Namespace: repository.GetNamespace(),
 | 
					 | 
				
			||||||
			Name:      repository.Spec.SecretRef.Name,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var secret corev1.Secret
 | 
					 | 
				
			||||||
		err = r.Client.Get(ctx, name, &secret)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			err = fmt.Errorf("auth secret error: %w", err)
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Configure strategy with secret
 | 
				
			||||||
		auth, err = authStrategy.Method(secret)
 | 
							auth, err = authStrategy.Method(secret)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			err = fmt.Errorf("auth error: %w", err)
 | 
								conditions.MarkTrue(obj, sourcev1.CheckoutFailedCondition, sourcev1.AuthenticationFailedReason,
 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
 | 
									"Failed to configure auth strategy for Git implementation '%s': %s", obj.Spec.GitImplementation, err)
 | 
				
			||||||
 | 
								r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.AuthenticationFailedReason,
 | 
				
			||||||
 | 
									"Failed to configure auth strategy for Git implementation '%s': %s", obj.Spec.GitImplementation, err)
 | 
				
			||||||
 | 
								// Return error as the contents of the secret may change
 | 
				
			||||||
 | 
								return ctrl.Result{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	checkoutStrategy, err := strategy.CheckoutStrategyForRef(
 | 
						// Configure checkout strategy
 | 
				
			||||||
		repository.Spec.Reference,
 | 
						checkoutStrategy, err := strategy.CheckoutStrategyForRef(obj.Spec.Reference, git.CheckoutOptions{
 | 
				
			||||||
		git.CheckoutOptions{
 | 
							GitImplementation: obj.Spec.GitImplementation,
 | 
				
			||||||
			GitImplementation: repository.Spec.GitImplementation,
 | 
							RecurseSubmodules: obj.Spec.RecurseSubmodules,
 | 
				
			||||||
			RecurseSubmodules: repository.Spec.RecurseSubmodules,
 | 
						})
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
 | 
							ctrl.LoggerFrom(ctx).Error(err, fmt.Sprintf("Failed to configure checkout strategy for Git implementation '%s'", obj.Spec.GitImplementation))
 | 
				
			||||||
 | 
							conditions.MarkTrue(obj, sourcev1.CheckoutFailedCondition, sourcev1.GitOperationFailedReason,
 | 
				
			||||||
 | 
								"Failed to configure checkout strategy for Git implementation '%s': %s", obj.Spec.GitImplementation, err)
 | 
				
			||||||
 | 
							// Do not return err as recovery without changes is impossible
 | 
				
			||||||
 | 
							return ctrl.Result{}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gitCtx, cancel := context.WithTimeout(ctx, repository.Spec.Timeout.Duration)
 | 
						// Checkout HEAD of reference in object
 | 
				
			||||||
 | 
						gitCtx, cancel := context.WithTimeout(ctx, obj.Spec.Timeout.Duration)
 | 
				
			||||||
	defer cancel()
 | 
						defer cancel()
 | 
				
			||||||
 | 
						commit, revision, err := checkoutStrategy.Checkout(gitCtx, dir, obj.Spec.URL, auth)
 | 
				
			||||||
	commit, revision, err := checkoutStrategy.Checkout(gitCtx, tmpGit, repository.Spec.URL, auth)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
 | 
							conditions.MarkTrue(obj, sourcev1.CheckoutFailedCondition, sourcev1.GitOperationFailedReason,
 | 
				
			||||||
 | 
								"Failed to checkout and determine revision: %s", err)
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.GitOperationFailedReason,
 | 
				
			||||||
 | 
								"Failed to checkout and determine revision: %s", err)
 | 
				
			||||||
 | 
							// Coin flip on transient or persistent error, return error and hope for the best
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.Eventf(ctx, obj, events.EventSeverityInfo, sourcev1.GitOperationSucceedReason,
 | 
				
			||||||
 | 
							"Cloned repository '%s' and checked out revision '%s'", obj.Spec.URL, revision)
 | 
				
			||||||
 | 
						conditions.Delete(obj, sourcev1.CheckoutFailedCondition)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Verify commit signature
 | 
				
			||||||
 | 
						if result, err := r.verifyCommitSignature(ctx, obj, commit); err != nil || result.IsZero() {
 | 
				
			||||||
 | 
							return result, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	artifact := r.Storage.NewArtifactFor(repository.Kind, repository.GetObjectMeta(), revision, fmt.Sprintf("%s.tar.gz", commit.Hash()))
 | 
						// Create potential new artifact with current available metadata
 | 
				
			||||||
 | 
						*artifact = r.Storage.NewArtifactFor(obj.Kind, obj, revision, fmt.Sprintf("%s.tar.gz", commit.Hash()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// copy all included repository into the artifact
 | 
						// Mark observations about the revision on the object
 | 
				
			||||||
	includedArtifacts := []*sourcev1.Artifact{}
 | 
						if !obj.GetArtifact().HasRevision(revision) {
 | 
				
			||||||
	for _, incl := range repository.Spec.Include {
 | 
							conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "NewRevision", "New upstream revision '%s'", revision)
 | 
				
			||||||
		dName := types.NamespacedName{Name: incl.GitRepositoryRef.Name, Namespace: repository.Namespace}
 | 
						}
 | 
				
			||||||
		var gr sourcev1.GitRepository
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
		err := r.Get(context.Background(), dName, &gr)
 | 
					}
 | 
				
			||||||
		if err != nil {
 | 
					
 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, meta.DependencyNotReadyReason, err.Error()), err
 | 
					// reconcileArtifact archives a new artifact to the storage, if the current observation on the object does not match the
 | 
				
			||||||
 | 
					// given data.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The inspection of the given data to the object is differed, ensuring any stale observations as
 | 
				
			||||||
 | 
					// v1beta1.ArtifactUnavailableCondition and v1beta1.ArtifactOutdatedCondition are always deleted.
 | 
				
			||||||
 | 
					// If the given artifact and/or includes do not differ from the object's current, it returns early.
 | 
				
			||||||
 | 
					// Source ignore patterns are loaded, and the given directory is archived.
 | 
				
			||||||
 | 
					// On a successful archive, the artifact and includes in the status of the given object are set, and the symlink in the
 | 
				
			||||||
 | 
					// storage is updated to its path.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The caller should assume a failure if an error is returned, or the Result is zero.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcileArtifact(ctx context.Context, obj *sourcev1.GitRepository, artifact sourcev1.Artifact, includes artifactSet, dir string) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						// Always restore the Ready condition in case it got removed due to a transient error
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if obj.GetArtifact() != nil {
 | 
				
			||||||
 | 
								conditions.Delete(obj, sourcev1.ArtifactUnavailableCondition)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		includedArtifacts = append(includedArtifacts, gr.GetArtifact())
 | 
							if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) {
 | 
				
			||||||
 | 
								conditions.Delete(obj, sourcev1.ArtifactOutdatedCondition)
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, meta.ReadyCondition, meta.SucceededReason,
 | 
				
			||||||
 | 
									"Stored artifact for revision '%s'", artifact.Revision)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// The artifact is up-to-date
 | 
				
			||||||
 | 
						if obj.GetArtifact().HasRevision(artifact.Revision) && !includes.Diff(obj.Status.IncludedArtifacts) {
 | 
				
			||||||
 | 
							ctrl.LoggerFrom(ctx).Info(fmt.Sprintf("Already up to date, current revision '%s'", artifact.Revision))
 | 
				
			||||||
 | 
							return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// return early on unchanged revision and unchanged included repositories
 | 
						// Ensure target path exists and is a directory
 | 
				
			||||||
	if apimeta.IsStatusConditionTrue(repository.Status.Conditions, meta.ReadyCondition) && repository.GetArtifact().HasRevision(artifact.Revision) && !hasArtifactUpdated(repository.Status.IncludedArtifacts, includedArtifacts) {
 | 
						if f, err := os.Stat(dir); err != nil {
 | 
				
			||||||
		if artifact.URL != repository.GetArtifact().URL {
 | 
							ctrl.LoggerFrom(ctx).Error(err, "failed to stat source path")
 | 
				
			||||||
			r.Storage.SetArtifactURL(repository.GetArtifact())
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
			repository.Status.URL = r.Storage.SetHostname(repository.Status.URL)
 | 
						} else if !f.IsDir() {
 | 
				
			||||||
		}
 | 
							err := fmt.Errorf("source path '%s' is not a directory", dir)
 | 
				
			||||||
		return repository, nil
 | 
							ctrl.LoggerFrom(ctx).Error(err, "invalid target path")
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// verify PGP signature
 | 
						// Ensure artifact directory exists and acquire lock
 | 
				
			||||||
	if repository.Spec.Verification != nil {
 | 
						if err := r.Storage.MkdirAll(artifact); err != nil {
 | 
				
			||||||
		publicKeySecret := types.NamespacedName{
 | 
							ctrl.LoggerFrom(ctx).Error(err, "failed to create artifact directory")
 | 
				
			||||||
			Namespace: repository.Namespace,
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
			Name:      repository.Spec.Verification.SecretRef.Name,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var secret corev1.Secret
 | 
					 | 
				
			||||||
		if err := r.Client.Get(ctx, publicKeySecret, &secret); err != nil {
 | 
					 | 
				
			||||||
			err = fmt.Errorf("PGP public keys secret error: %w", err)
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		err := commit.Verify(secret)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create artifact dir
 | 
					 | 
				
			||||||
	err = r.Storage.MkdirAll(artifact)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		err = fmt.Errorf("mkdir dir error: %w", err)
 | 
					 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i, incl := range repository.Spec.Include {
 | 
					 | 
				
			||||||
		toPath, err := securejoin.SecureJoin(tmpGit, incl.GetToPath())
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, meta.DependencyNotReadyReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = r.Storage.CopyToPath(includedArtifacts[i], incl.GetFromPath(), toPath)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return sourcev1.GitRepositoryNotReady(repository, meta.DependencyNotReadyReason, err.Error()), err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// acquire lock
 | 
					 | 
				
			||||||
	unlock, err := r.Storage.Lock(artifact)
 | 
						unlock, err := r.Storage.Lock(artifact)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = fmt.Errorf("unable to acquire lock: %w", err)
 | 
							ctrl.LoggerFrom(ctx).Error(err, "failed to acquire lock for artifact")
 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer unlock()
 | 
						defer unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// archive artifact and check integrity
 | 
						// Load ignore rules for archiving
 | 
				
			||||||
	ignoreDomain := strings.Split(tmpGit, string(filepath.Separator))
 | 
						ps, err := sourceignore.LoadIgnorePatterns(dir, nil)
 | 
				
			||||||
	ps, err := sourceignore.LoadIgnorePatterns(tmpGit, ignoreDomain)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = fmt.Errorf(".sourceignore error: %w", err)
 | 
							r.Eventf(ctx, obj, events.EventSeverityError,
 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
								"SourceIgnoreError", "Failed to load source ignore patterns from repository: %s", err)
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if repository.Spec.Ignore != nil {
 | 
						if obj.Spec.Ignore != nil {
 | 
				
			||||||
		ps = append(ps, sourceignore.ReadPatterns(strings.NewReader(*repository.Spec.Ignore), ignoreDomain)...)
 | 
							ps = append(ps, sourceignore.ReadPatterns(strings.NewReader(*obj.Spec.Ignore), nil)...)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := r.Storage.Archive(&artifact, tmpGit, SourceIgnoreFilter(ps, ignoreDomain)); err != nil {
 | 
					 | 
				
			||||||
		err = fmt.Errorf("storage archive error: %w", err)
 | 
					 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// update latest symlink
 | 
						// Archive directory to storage
 | 
				
			||||||
 | 
						if err := r.Storage.Archive(&artifact, dir, SourceIgnoreFilter(ps, nil)); err != nil {
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.StorageOperationFailedReason,
 | 
				
			||||||
 | 
								"Unable to archive artifact to storage: %s", err)
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.Events.EventWithMetaf(ctx, obj, map[string]string{
 | 
				
			||||||
 | 
							"revision": artifact.Revision,
 | 
				
			||||||
 | 
							"checksum": artifact.Checksum,
 | 
				
			||||||
 | 
						}, events.EventSeverityInfo, "NewArtifact", "Stored artifact for revision '%s'", artifact.Revision)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Record it on the object
 | 
				
			||||||
 | 
						obj.Status.Artifact = artifact.DeepCopy()
 | 
				
			||||||
 | 
						obj.Status.IncludedArtifacts = includes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update symlink on a "best effort" basis
 | 
				
			||||||
	url, err := r.Storage.Symlink(artifact, "latest.tar.gz")
 | 
						url, err := r.Storage.Symlink(artifact, "latest.tar.gz")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = fmt.Errorf("storage symlink error: %w", err)
 | 
							r.Events.Eventf(ctx, obj, events.EventSeverityError, sourcev1.StorageOperationFailedReason,
 | 
				
			||||||
		return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
 | 
								"Failed to update status URL symlink: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if url != "" {
 | 
				
			||||||
	message := fmt.Sprintf("Fetched revision: %s", artifact.Revision)
 | 
							obj.Status.URL = url
 | 
				
			||||||
	return sourcev1.GitRepositoryReady(repository, artifact, includedArtifacts, url, sourcev1.GitOperationSucceedReason, message), nil
 | 
						}
 | 
				
			||||||
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *GitRepositoryReconciler) reconcileDelete(ctx context.Context, repository sourcev1.GitRepository) (ctrl.Result, error) {
 | 
					// reconcileInclude reconciles the declared includes from the object by copying their artifact (sub)contents to the
 | 
				
			||||||
	if err := r.gc(repository); err != nil {
 | 
					// declared paths in the given directory.
 | 
				
			||||||
		r.event(ctx, repository, events.EventSeverityError,
 | 
					//
 | 
				
			||||||
			fmt.Sprintf("garbage collection for deleted resource failed: %s", err.Error()))
 | 
					// If an include is unavailable, it marks the object with v1beta1.IncludeUnavailableCondition and returns early.
 | 
				
			||||||
 | 
					// If the copy operations are successful, it deletes the v1beta1.IncludeUnavailableCondition from the object.
 | 
				
			||||||
 | 
					// If the artifactSet differs from the current set, it marks the object with v1beta1.ArtifactOutdatedCondition.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The caller should assume a failure if an error is returned, or the Result is zero.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcileInclude(ctx context.Context, obj *sourcev1.GitRepository, artifacts artifactSet, dir string) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						artifacts = make(artifactSet, len(obj.Spec.Include))
 | 
				
			||||||
 | 
						for i, incl := range obj.Spec.Include {
 | 
				
			||||||
 | 
							// Do this first as it is much cheaper than copy operations
 | 
				
			||||||
 | 
							toPath, err := securejoin.SecureJoin(dir, incl.GetToPath())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.IncludeUnavailableCondition, "IllegalPath",
 | 
				
			||||||
 | 
									"Path calculation for include '%s' failed: %s", incl.GitRepositoryRef.Name, err.Error())
 | 
				
			||||||
 | 
								return ctrl.Result{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Retrieve the included GitRepository
 | 
				
			||||||
 | 
							dep := &sourcev1.GitRepository{}
 | 
				
			||||||
 | 
							if err := r.Get(ctx, types.NamespacedName{Namespace: obj.Namespace, Name: incl.GitRepositoryRef.Name}, dep); err != nil {
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.IncludeUnavailableCondition, "NotFound",
 | 
				
			||||||
 | 
									"Could not get resource for include '%s': %s", incl.GitRepositoryRef.Name, err.Error())
 | 
				
			||||||
 | 
								return ctrl.Result{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Confirm include has an artifact
 | 
				
			||||||
 | 
							if dep.GetArtifact() == nil {
 | 
				
			||||||
 | 
								ctrl.LoggerFrom(ctx).Error(nil, fmt.Sprintf("No artifact available for include '%s'", incl.GitRepositoryRef.Name))
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.IncludeUnavailableCondition, "NoArtifact",
 | 
				
			||||||
 | 
									"No artifact available for include '%s'", incl.GitRepositoryRef.Name)
 | 
				
			||||||
 | 
								return ctrl.Result{}, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Copy artifact (sub)contents to configured directory
 | 
				
			||||||
 | 
							if err := r.Storage.CopyToPath(dep.GetArtifact(), incl.GetFromPath(), toPath); err != nil {
 | 
				
			||||||
 | 
								conditions.MarkTrue(obj, sourcev1.IncludeUnavailableCondition, "CopyFailure",
 | 
				
			||||||
 | 
									"Failed to copy '%s' include from %s to %s: %s", incl.GitRepositoryRef.Name, incl.GetFromPath(), incl.GetToPath(), err.Error())
 | 
				
			||||||
 | 
								r.Eventf(ctx, obj, events.EventSeverityError, sourcev1.IncludeUnavailableCondition,
 | 
				
			||||||
 | 
									"Failed to copy '%s' include from %s to %s: %s", incl.GitRepositoryRef.Name, incl.GetFromPath(), incl.GetToPath(), err.Error())
 | 
				
			||||||
 | 
								return ctrl.Result{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							artifacts[i] = dep.GetArtifact().DeepCopy()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We now know all includes are available
 | 
				
			||||||
 | 
						conditions.Delete(obj, sourcev1.IncludeUnavailableCondition)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Observe if the artifacts still match the previous included ones
 | 
				
			||||||
 | 
						if artifacts.Diff(obj.Status.IncludedArtifacts) {
 | 
				
			||||||
 | 
							conditions.MarkTrue(obj, sourcev1.ArtifactOutdatedCondition, "IncludeChange", "Included artifacts differ from last observed includes")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reconcileDelete handles the delete of an object. It first garbage collects all artifacts for the object from the
 | 
				
			||||||
 | 
					// artifact storage, if successful, the finalizer is removed from the object.
 | 
				
			||||||
 | 
					func (r *GitRepositoryReconciler) reconcileDelete(ctx context.Context, obj *sourcev1.GitRepository) (ctrl.Result, error) {
 | 
				
			||||||
 | 
						// Garbage collect the resource's artifacts
 | 
				
			||||||
 | 
						if err := r.garbageCollect(ctx, obj); err != nil {
 | 
				
			||||||
		// Return the error so we retry the failed garbage collection
 | 
							// Return the error so we retry the failed garbage collection
 | 
				
			||||||
		return ctrl.Result{}, err
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Record deleted status
 | 
						// Remove our finalizer from the list
 | 
				
			||||||
	r.recordReadiness(ctx, repository)
 | 
						controllerutil.RemoveFinalizer(obj, sourcev1.SourceFinalizer)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove our finalizer from the list and update it
 | 
					 | 
				
			||||||
	controllerutil.RemoveFinalizer(&repository, sourcev1.SourceFinalizer)
 | 
					 | 
				
			||||||
	if err := r.Update(ctx, &repository); err != nil {
 | 
					 | 
				
			||||||
		return ctrl.Result{}, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Stop reconciliation as the object is being deleted
 | 
						// Stop reconciliation as the object is being deleted
 | 
				
			||||||
	return ctrl.Result{}, nil
 | 
						return ctrl.Result{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// resetStatus returns a modified v1beta1.GitRepository and a boolean indicating
 | 
					// verifyCommitSignature verifies the signature of the given commit if a verification mode is configured on the object.
 | 
				
			||||||
// if the status field has been reset.
 | 
					func (r *GitRepositoryReconciler) verifyCommitSignature(ctx context.Context, obj *sourcev1.GitRepository, commit git.Commit) (ctrl.Result, error) {
 | 
				
			||||||
func (r *GitRepositoryReconciler) resetStatus(repository sourcev1.GitRepository) (sourcev1.GitRepository, bool) {
 | 
						// Check if there is a commit verification is configured and remove any old observations if there is none
 | 
				
			||||||
	// We do not have an artifact, or it does no longer exist
 | 
						if obj.Spec.Verification == nil || obj.Spec.Verification.Mode == "" {
 | 
				
			||||||
	if repository.GetArtifact() == nil || !r.Storage.ArtifactExist(*repository.GetArtifact()) {
 | 
							conditions.Delete(obj, sourcev1.SourceVerifiedCondition)
 | 
				
			||||||
		repository = sourcev1.GitRepositoryProgressing(repository)
 | 
							return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
		repository.Status.Artifact = nil
 | 
					 | 
				
			||||||
		return repository, true
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if repository.Generation != repository.Status.ObservedGeneration {
 | 
					
 | 
				
			||||||
		return sourcev1.GitRepositoryProgressing(repository), true
 | 
						// Get secret with GPG data
 | 
				
			||||||
 | 
						publicKeySecret := types.NamespacedName{
 | 
				
			||||||
 | 
							Namespace: obj.Namespace,
 | 
				
			||||||
 | 
							Name:      obj.Spec.Verification.SecretRef.Name,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return repository, false
 | 
						var secret corev1.Secret
 | 
				
			||||||
 | 
						if err := r.Client.Get(ctx, publicKeySecret, &secret); err != nil {
 | 
				
			||||||
 | 
							conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, meta.FailedReason, "PGP public keys secret error: %s", err.Error())
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityError, "VerificationError", "PGP public keys secret error: %s", err.Error())
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Verify commit with GPG data from secret
 | 
				
			||||||
 | 
						if err := commit.Verify(secret); err != nil {
 | 
				
			||||||
 | 
							conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, meta.FailedReason, "Signature verification of commit '%s' failed: %s", commit.Hash(), err)
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityError, "InvalidCommitSignature", "Signature verification of commit '%s' failed: %s", commit.Hash(), err)
 | 
				
			||||||
 | 
							// Return error in the hope the secret changes
 | 
				
			||||||
 | 
							return ctrl.Result{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, meta.SucceededReason, "Verified signature of commit '%s'", commit.Hash())
 | 
				
			||||||
 | 
						r.Eventf(ctx, obj, events.EventSeverityInfo, "VerifiedCommit", "Verified signature of commit '%s'", commit.Hash())
 | 
				
			||||||
 | 
						return ctrl.Result{RequeueAfter: obj.GetRequeueAfter()}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// gc performs a garbage collection for the given v1beta1.GitRepository.
 | 
					// garbageCollect performs a garbage collection for the given v1beta1.GitRepository. It removes all but the current
 | 
				
			||||||
// It removes all but the current artifact except for when the
 | 
					// artifact except for when the deletion timestamp is set, which will result in the removal of all artifacts for the
 | 
				
			||||||
// deletion timestamp is set, which will result in the removal of
 | 
					// resource.
 | 
				
			||||||
// all artifacts for the resource.
 | 
					func (r *GitRepositoryReconciler) garbageCollect(ctx context.Context, obj *sourcev1.GitRepository) error {
 | 
				
			||||||
func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error {
 | 
						if !obj.DeletionTimestamp.IsZero() {
 | 
				
			||||||
	if !repository.DeletionTimestamp.IsZero() {
 | 
							if err := r.Storage.RemoveAll(r.Storage.NewArtifactFor(obj.Kind, obj.GetObjectMeta(), "", "*")); err != nil {
 | 
				
			||||||
		return r.Storage.RemoveAll(r.Storage.NewArtifactFor(repository.Kind, repository.GetObjectMeta(), "", "*"))
 | 
								r.Eventf(ctx, obj, events.EventSeverityError, "GarbageCollectionFailed",
 | 
				
			||||||
 | 
									"Garbage collection for deleted resource failed: %s", err)
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							obj.Status.Artifact = nil
 | 
				
			||||||
 | 
							// TODO(hidde): we should only push this event if we actually garbage collected something
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityInfo, "GarbageCollectionSucceeded",
 | 
				
			||||||
 | 
								"Garbage collected artifacts for deleted resource")
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if repository.GetArtifact() != nil {
 | 
						if obj.GetArtifact() != nil {
 | 
				
			||||||
		return r.Storage.RemoveAllButCurrent(*repository.GetArtifact())
 | 
							if err := r.Storage.RemoveAllButCurrent(*obj.GetArtifact()); err != nil {
 | 
				
			||||||
 | 
								r.Eventf(ctx, obj, events.EventSeverityError, "GarbageCollectionFailed", "Garbage collection of old artifacts failed: %s", err)
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// TODO(hidde): we should only push this event if we actually garbage collected something
 | 
				
			||||||
 | 
							r.Eventf(ctx, obj, events.EventSeverityInfo, "GarbageCollectionSucceeded", "Garbage collected old artifacts")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// event emits a Kubernetes event and forwards the event to notification controller if configured
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) event(ctx context.Context, repository sourcev1.GitRepository, severity, msg string) {
 | 
					 | 
				
			||||||
	log := logr.FromContext(ctx)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r.EventRecorder != nil {
 | 
					 | 
				
			||||||
		r.EventRecorder.Eventf(&repository, "Normal", severity, msg)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if r.ExternalEventRecorder != nil {
 | 
					 | 
				
			||||||
		objRef, err := reference.GetReference(r.Scheme, &repository)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			log.Error(err, "unable to send event")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err := r.ExternalEventRecorder.Eventf(*objRef, nil, severity, severity, msg); err != nil {
 | 
					 | 
				
			||||||
			log.Error(err, "unable to send event")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) recordReadiness(ctx context.Context, repository sourcev1.GitRepository) {
 | 
					 | 
				
			||||||
	log := logr.FromContext(ctx)
 | 
					 | 
				
			||||||
	if r.MetricsRecorder == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	objRef, err := reference.GetReference(r.Scheme, &repository)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Error(err, "unable to record readiness metric")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if rc := apimeta.FindStatusCondition(repository.Status.Conditions, meta.ReadyCondition); rc != nil {
 | 
					 | 
				
			||||||
		r.MetricsRecorder.RecordCondition(*objRef, *rc, !repository.DeletionTimestamp.IsZero())
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		r.MetricsRecorder.RecordCondition(*objRef, metav1.Condition{
 | 
					 | 
				
			||||||
			Type:   meta.ReadyCondition,
 | 
					 | 
				
			||||||
			Status: metav1.ConditionUnknown,
 | 
					 | 
				
			||||||
		}, !repository.DeletionTimestamp.IsZero())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) recordSuspension(ctx context.Context, gitrepository sourcev1.GitRepository) {
 | 
					 | 
				
			||||||
	if r.MetricsRecorder == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	log := logr.FromContext(ctx)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	objRef, err := reference.GetReference(r.Scheme, &gitrepository)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Error(err, "unable to record suspended metric")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !gitrepository.DeletionTimestamp.IsZero() {
 | 
					 | 
				
			||||||
		r.MetricsRecorder.RecordSuspend(*objRef, false)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		r.MetricsRecorder.RecordSuspend(*objRef, gitrepository.Spec.Suspend)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *GitRepositoryReconciler) updateStatus(ctx context.Context, req ctrl.Request, newStatus sourcev1.GitRepositoryStatus) error {
 | 
					 | 
				
			||||||
	var repository sourcev1.GitRepository
 | 
					 | 
				
			||||||
	if err := r.Get(ctx, req.NamespacedName, &repository); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	patch := client.MergeFrom(repository.DeepCopy())
 | 
					 | 
				
			||||||
	repository.Status = newStatus
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return r.Status().Patch(ctx, &repository, patch)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -252,9 +252,9 @@ func (r *HelmChartReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
						log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
				
			||||||
		time.Now().Sub(start).String(),
 | 
							time.Now().Sub(start).String(),
 | 
				
			||||||
		chart.GetInterval().Duration.String(),
 | 
							chart.GetRequeueAfter().String(),
 | 
				
			||||||
	))
 | 
						))
 | 
				
			||||||
	return ctrl.Result{RequeueAfter: chart.GetInterval().Duration}, nil
 | 
						return ctrl.Result{RequeueAfter: chart.GetRequeueAfter()}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type HelmChartReconcilerOptions struct {
 | 
					type HelmChartReconcilerOptions struct {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,9 +130,9 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
			got := &sourcev1.HelmChart{}
 | 
								got := &sourcev1.HelmChart{}
 | 
				
			||||||
			Eventually(func() bool {
 | 
								Eventually(func() bool {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil && storage.ArtifactExist(*got.Status.Artifact)
 | 
									return got.Status.Artifact != nil && ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
			helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
								helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
			Expect(err).NotTo(HaveOccurred())
 | 
								Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
			Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
								Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
			Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
								Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, now)
 | 
									_ = k8sClient.Get(context.Background(), key, now)
 | 
				
			||||||
				// Test revision change and garbage collection
 | 
									// Test revision change and garbage collection
 | 
				
			||||||
				return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
									return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
				
			||||||
					!storage.ArtifactExist(*got.Status.Artifact)
 | 
										!ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			When("Setting valid valuesFiles attribute", func() {
 | 
								When("Setting valid valuesFiles attribute", func() {
 | 
				
			||||||
| 
						 | 
					@ -162,12 +162,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -185,12 +185,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -208,12 +208,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -229,12 +229,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				_, exists := helmChart.Values["testDefault"]
 | 
									_, exists := helmChart.Values["testDefault"]
 | 
				
			||||||
				Expect(exists).To(BeFalse())
 | 
									Expect(exists).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -251,12 +251,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -272,12 +272,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -683,7 +683,7 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
			Eventually(func() bool {
 | 
								Eventually(func() bool {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil &&
 | 
									return got.Status.Artifact != nil &&
 | 
				
			||||||
					storage.ArtifactExist(*got.Status.Artifact)
 | 
										ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			By("Committing a new version in the chart metadata")
 | 
								By("Committing a new version in the chart metadata")
 | 
				
			||||||
| 
						 | 
					@ -728,9 +728,9 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, now)
 | 
									_ = k8sClient.Get(context.Background(), key, now)
 | 
				
			||||||
				// Test revision change and garbage collection
 | 
									// Test revision change and garbage collection
 | 
				
			||||||
				return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
									return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
				
			||||||
					!storage.ArtifactExist(*got.Status.Artifact)
 | 
										!ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
			helmChart, err := loader.Load(storage.LocalPath(*now.Status.Artifact))
 | 
								helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*now.Status.Artifact))
 | 
				
			||||||
			Expect(err).NotTo(HaveOccurred())
 | 
								Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
			Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
								Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
			Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
								Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -747,12 +747,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -770,12 +770,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -793,12 +793,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -814,12 +814,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				_, exists := helmChart.Values["testDefault"]
 | 
									_, exists := helmChart.Values["testDefault"]
 | 
				
			||||||
				Expect(exists).To(BeFalse())
 | 
									Expect(exists).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -836,12 +836,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				_, exists := helmChart.Values["testDefault"]
 | 
									_, exists := helmChart.Values["testDefault"]
 | 
				
			||||||
				Expect(exists).To(BeFalse())
 | 
									Expect(exists).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -946,7 +946,7 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
			Eventually(func() bool {
 | 
								Eventually(func() bool {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil &&
 | 
									return got.Status.Artifact != nil &&
 | 
				
			||||||
					storage.ArtifactExist(*got.Status.Artifact)
 | 
										ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
| 
						 | 
					@ -1189,9 +1189,9 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
			Eventually(func() bool {
 | 
								Eventually(func() bool {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil &&
 | 
									return got.Status.Artifact != nil &&
 | 
				
			||||||
					storage.ArtifactExist(*got.Status.Artifact)
 | 
										ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
			helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
								helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
			Expect(err).NotTo(HaveOccurred())
 | 
								Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
			Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
								Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
			Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
								Expect(helmChart.Values["testOverride"]).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -1208,12 +1208,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -1231,12 +1231,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -1254,12 +1254,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testDefault"]).To(BeTrue())
 | 
				
			||||||
				Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
									Expect(helmChart.Values["testOverride"]).To(BeTrue())
 | 
				
			||||||
| 
						 | 
					@ -1275,12 +1275,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
										return got.Status.Artifact.Checksum != updated.Status.Artifact.Checksum &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				_, exists := helmChart.Values["testDefault"]
 | 
									_, exists := helmChart.Values["testDefault"]
 | 
				
			||||||
				Expect(exists).To(BeFalse())
 | 
									Expect(exists).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					@ -1297,12 +1297,12 @@ var _ = Describe("HelmChartReconciler", func() {
 | 
				
			||||||
				Eventually(func() bool {
 | 
									Eventually(func() bool {
 | 
				
			||||||
					_ = k8sClient.Get(context.Background(), key, got)
 | 
										_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
					return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
										return got.Status.ObservedGeneration > updated.Status.ObservedGeneration &&
 | 
				
			||||||
						storage.ArtifactExist(*got.Status.Artifact)
 | 
											ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
				}, timeout, interval).Should(BeTrue())
 | 
									}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
				f, err := os.Stat(storage.LocalPath(*got.Status.Artifact))
 | 
									f, err := os.Stat(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				Expect(f.Size()).To(BeNumerically(">", 0))
 | 
									Expect(f.Size()).To(BeNumerically(">", 0))
 | 
				
			||||||
				helmChart, err := loader.Load(storage.LocalPath(*got.Status.Artifact))
 | 
									helmChart, err := loader.Load(ginkgoTestStorage.LocalPath(*got.Status.Artifact))
 | 
				
			||||||
				Expect(err).NotTo(HaveOccurred())
 | 
									Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
				_, exists := helmChart.Values["testDefault"]
 | 
									_, exists := helmChart.Values["testDefault"]
 | 
				
			||||||
				Expect(exists).To(BeFalse())
 | 
									Expect(exists).To(BeFalse())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,10 +164,10 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
						log.Info(fmt.Sprintf("Reconciliation finished in %s, next run in %s",
 | 
				
			||||||
		time.Now().Sub(start).String(),
 | 
							time.Now().Sub(start).String(),
 | 
				
			||||||
		repository.GetInterval().Duration.String(),
 | 
							repository.GetRequeueAfter().String(),
 | 
				
			||||||
	))
 | 
						))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ctrl.Result{RequeueAfter: repository.GetInterval().Duration}, nil
 | 
						return ctrl.Result{RequeueAfter: repository.GetRequeueAfter()}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, repository sourcev1.HelmRepository) (sourcev1.HelmRepository, error) {
 | 
					func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, repository sourcev1.HelmRepository) (sourcev1.HelmRepository, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ var _ = Describe("HelmRepositoryReconciler", func() {
 | 
				
			||||||
			got := &sourcev1.HelmRepository{}
 | 
								got := &sourcev1.HelmRepository{}
 | 
				
			||||||
			Eventually(func() bool {
 | 
								Eventually(func() bool {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil && storage.ArtifactExist(*got.Status.Artifact)
 | 
									return got.Status.Artifact != nil && ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			By("Updating the chart index")
 | 
								By("Updating the chart index")
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ var _ = Describe("HelmRepositoryReconciler", func() {
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, now)
 | 
									_ = k8sClient.Get(context.Background(), key, now)
 | 
				
			||||||
				// Test revision change and garbage collection
 | 
									// Test revision change and garbage collection
 | 
				
			||||||
				return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
									return now.Status.Artifact.Revision != got.Status.Artifact.Revision &&
 | 
				
			||||||
					!storage.ArtifactExist(*got.Status.Artifact)
 | 
										!ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			updated := &sourcev1.HelmRepository{}
 | 
								updated := &sourcev1.HelmRepository{}
 | 
				
			||||||
| 
						 | 
					@ -296,7 +296,7 @@ var _ = Describe("HelmRepositoryReconciler", func() {
 | 
				
			||||||
				got := &sourcev1.HelmRepository{}
 | 
									got := &sourcev1.HelmRepository{}
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil &&
 | 
									return got.Status.Artifact != nil &&
 | 
				
			||||||
					storage.ArtifactExist(*got.Status.Artifact)
 | 
										ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			By("Expecting missing secret error")
 | 
								By("Expecting missing secret error")
 | 
				
			||||||
| 
						 | 
					@ -390,7 +390,7 @@ var _ = Describe("HelmRepositoryReconciler", func() {
 | 
				
			||||||
				got := &sourcev1.HelmRepository{}
 | 
									got := &sourcev1.HelmRepository{}
 | 
				
			||||||
				_ = k8sClient.Get(context.Background(), key, got)
 | 
									_ = k8sClient.Get(context.Background(), key, got)
 | 
				
			||||||
				return got.Status.Artifact != nil &&
 | 
									return got.Status.Artifact != nil &&
 | 
				
			||||||
					storage.ArtifactExist(*got.Status.Artifact)
 | 
										ginkgoTestStorage.ArtifactExist(*got.Status.Artifact)
 | 
				
			||||||
			}, timeout, interval).Should(BeTrue())
 | 
								}, timeout, interval).Should(BeTrue())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			By("Expecting missing secret error")
 | 
								By("Expecting missing secret error")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,193 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2020 The Flux authors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package controllers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/controller"
 | 
				
			||||||
 | 
						. "github.com/onsi/ginkgo"
 | 
				
			||||||
 | 
						. "github.com/onsi/gomega"
 | 
				
			||||||
 | 
						"helm.sh/helm/v3/pkg/getter"
 | 
				
			||||||
 | 
						"k8s.io/client-go/kubernetes/scheme"
 | 
				
			||||||
 | 
						"k8s.io/client-go/rest"
 | 
				
			||||||
 | 
						ctrl "sigs.k8s.io/controller-runtime"
 | 
				
			||||||
 | 
						"sigs.k8s.io/controller-runtime/pkg/client"
 | 
				
			||||||
 | 
						"sigs.k8s.io/controller-runtime/pkg/envtest"
 | 
				
			||||||
 | 
						"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
 | 
				
			||||||
 | 
						logf "sigs.k8s.io/controller-runtime/pkg/log"
 | 
				
			||||||
 | 
						"sigs.k8s.io/controller-runtime/pkg/log/zap"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
				
			||||||
 | 
						// +kubebuilder:scaffold:imports
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// These tests use Ginkgo (BDD-style Go testing framework). Refer to
 | 
				
			||||||
 | 
					// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var cfg *rest.Config
 | 
				
			||||||
 | 
					var k8sClient client.Client
 | 
				
			||||||
 | 
					var k8sManager ctrl.Manager
 | 
				
			||||||
 | 
					var ginkgoTestEnv *envtest.Environment
 | 
				
			||||||
 | 
					var ginkgoTestStorage *Storage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var examplePublicKey []byte
 | 
				
			||||||
 | 
					var examplePrivateKey []byte
 | 
				
			||||||
 | 
					var exampleCA []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIs(t *testing.T) {
 | 
				
			||||||
 | 
						RegisterFailHandler(Fail)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						RunSpecsWithDefaultAndCustomReporters(t,
 | 
				
			||||||
 | 
							"Controller Suite",
 | 
				
			||||||
 | 
							[]Reporter{printer.NewlineReporter{}})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = BeforeSuite(func(done Done) {
 | 
				
			||||||
 | 
						logf.SetLogger(
 | 
				
			||||||
 | 
							zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						By("bootstrapping test environment")
 | 
				
			||||||
 | 
						t := true
 | 
				
			||||||
 | 
						if os.Getenv("TEST_USE_EXISTING_CLUSTER") == "true" {
 | 
				
			||||||
 | 
							ginkgoTestEnv = &envtest.Environment{
 | 
				
			||||||
 | 
								UseExistingCluster: &t,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ginkgoTestEnv = &envtest.Environment{
 | 
				
			||||||
 | 
								CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						cfg, err = ginkgoTestEnv.Start()
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred())
 | 
				
			||||||
 | 
						Expect(cfg).ToNot(BeNil())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sourcev1.AddToScheme(scheme.Scheme)
 | 
				
			||||||
 | 
						Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sourcev1.AddToScheme(scheme.Scheme)
 | 
				
			||||||
 | 
						Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sourcev1.AddToScheme(scheme.Scheme)
 | 
				
			||||||
 | 
						Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// +kubebuilder:scaffold:scheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Expect(loadExampleKeys()).To(Succeed())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmpStoragePath, err := os.MkdirTemp("", "source-controller-storage-")
 | 
				
			||||||
 | 
						Expect(err).NotTo(HaveOccurred(), "failed to create tmp storage dir")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ginkgoTestStorage, err = NewStorage(tmpStoragePath, "localhost:5050", time.Second*30)
 | 
				
			||||||
 | 
						Expect(err).NotTo(HaveOccurred(), "failed to create tmp storage")
 | 
				
			||||||
 | 
						// serve artifacts from the filesystem, as done in main.go
 | 
				
			||||||
 | 
						fs := http.FileServer(http.Dir(tmpStoragePath))
 | 
				
			||||||
 | 
						http.Handle("/", fs)
 | 
				
			||||||
 | 
						go http.ListenAndServe(":5050", nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k8sManager, err = ctrl.NewManager(cfg, ctrl.Options{
 | 
				
			||||||
 | 
							MetricsBindAddress: "0",
 | 
				
			||||||
 | 
							Scheme:             scheme.Scheme,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testEventsH = controller.MakeEvents(k8sManager, "source-controller-test", nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = (&GitRepositoryReconciler{
 | 
				
			||||||
 | 
							Client:  k8sManager.GetClient(),
 | 
				
			||||||
 | 
							Events:  testEventsH,
 | 
				
			||||||
 | 
							Storage: ginkgoTestStorage,
 | 
				
			||||||
 | 
						}).SetupWithManager(k8sManager)
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred(), "failed to setup GitRepositoryReconciler")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = (&HelmRepositoryReconciler{
 | 
				
			||||||
 | 
							Client:  k8sManager.GetClient(),
 | 
				
			||||||
 | 
							Scheme:  scheme.Scheme,
 | 
				
			||||||
 | 
							Storage: ginkgoTestStorage,
 | 
				
			||||||
 | 
							Getters: getter.Providers{getter.Provider{
 | 
				
			||||||
 | 
								Schemes: []string{"http", "https"},
 | 
				
			||||||
 | 
								New:     getter.NewHTTPGetter,
 | 
				
			||||||
 | 
							}},
 | 
				
			||||||
 | 
						}).SetupWithManager(k8sManager)
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred(), "failed to setup HelmRepositoryReconciler")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = (&HelmChartReconciler{
 | 
				
			||||||
 | 
							Client:  k8sManager.GetClient(),
 | 
				
			||||||
 | 
							Scheme:  scheme.Scheme,
 | 
				
			||||||
 | 
							Storage: ginkgoTestStorage,
 | 
				
			||||||
 | 
							Getters: getter.Providers{getter.Provider{
 | 
				
			||||||
 | 
								Schemes: []string{"http", "https"},
 | 
				
			||||||
 | 
								New:     getter.NewHTTPGetter,
 | 
				
			||||||
 | 
							}},
 | 
				
			||||||
 | 
						}).SetupWithManager(k8sManager)
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred(), "failed to setup HelmChartReconciler")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							err = k8sManager.Start(ctx)
 | 
				
			||||||
 | 
							Expect(err).ToNot(HaveOccurred())
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						k8sClient = k8sManager.GetClient()
 | 
				
			||||||
 | 
						Expect(k8sClient).ToNot(BeNil())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close(done)
 | 
				
			||||||
 | 
					}, 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = AfterSuite(func() {
 | 
				
			||||||
 | 
						By("tearing down the test environment")
 | 
				
			||||||
 | 
						if ginkgoTestStorage != nil {
 | 
				
			||||||
 | 
							err := os.RemoveAll(ginkgoTestStorage.BasePath)
 | 
				
			||||||
 | 
							Expect(err).NotTo(HaveOccurred())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := ginkgoTestEnv.Stop()
 | 
				
			||||||
 | 
						Expect(err).ToNot(HaveOccurred())
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						rand.Seed(time.Now().UnixNano())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadExampleKeys() (err error) {
 | 
				
			||||||
 | 
						examplePublicKey, err = os.ReadFile("testdata/certs/server.pem")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						examplePrivateKey, err = os.ReadFile("testdata/certs/server-key.pem")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						exampleCA, err = os.ReadFile("testdata/certs/ca.pem")
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func randStringRunes(n int) string {
 | 
				
			||||||
 | 
						b := make([]rune, n)
 | 
				
			||||||
 | 
						for i := range b {
 | 
				
			||||||
 | 
							b[i] = letterRunes[rand.Intn(len(letterRunes))]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return string(b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						securejoin "github.com/cyphar/filepath-securejoin"
 | 
				
			||||||
	"github.com/go-git/go-git/v5/plumbing/format/gitignore"
 | 
						"github.com/go-git/go-git/v5/plumbing/format/gitignore"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +53,7 @@ type Storage struct {
 | 
				
			||||||
	Timeout time.Duration `json:"timeout"`
 | 
						Timeout time.Duration `json:"timeout"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewStorage creates the storage helper for a given path and hostname
 | 
					// NewStorage creates the storage helper for a given path and hostname.
 | 
				
			||||||
func NewStorage(basePath string, hostname string, timeout time.Duration) (*Storage, error) {
 | 
					func NewStorage(basePath string, hostname string, timeout time.Duration) (*Storage, error) {
 | 
				
			||||||
	if f, err := os.Stat(basePath); os.IsNotExist(err) || !f.IsDir() {
 | 
						if f, err := os.Stat(basePath); os.IsNotExist(err) || !f.IsDir() {
 | 
				
			||||||
		return nil, fmt.Errorf("invalid dir path: %s", basePath)
 | 
							return nil, fmt.Errorf("invalid dir path: %s", basePath)
 | 
				
			||||||
| 
						 | 
					@ -80,11 +81,14 @@ func (s Storage) SetArtifactURL(artifact *sourcev1.Artifact) {
 | 
				
			||||||
	if artifact.Path == "" {
 | 
						if artifact.Path == "" {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	artifact.URL = fmt.Sprintf("http://%s/%s", s.Hostname, artifact.Path)
 | 
						format := "http://%s/%s"
 | 
				
			||||||
 | 
						if strings.HasPrefix(s.Hostname, "http://") || strings.HasPrefix(s.Hostname, "https://") {
 | 
				
			||||||
 | 
							format = "%s/%s"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						artifact.URL = fmt.Sprintf(format, s.Hostname, strings.TrimLeft(artifact.Path, "/"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetHostname sets the hostname of the given URL string to the current Storage.Hostname
 | 
					// SetHostname sets the hostname of the given URL string to the current Storage.Hostname and returns the result.
 | 
				
			||||||
// and returns the result.
 | 
					 | 
				
			||||||
func (s Storage) SetHostname(URL string) string {
 | 
					func (s Storage) SetHostname(URL string) string {
 | 
				
			||||||
	u, err := url.Parse(URL)
 | 
						u, err := url.Parse(URL)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -106,8 +110,7 @@ func (s *Storage) RemoveAll(artifact sourcev1.Artifact) error {
 | 
				
			||||||
	return os.RemoveAll(dir)
 | 
						return os.RemoveAll(dir)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RemoveAllButCurrent removes all files for the given v1beta1.Artifact base dir,
 | 
					// RemoveAllButCurrent removes all files for the given v1beta1.Artifact base dir, excluding the current one.
 | 
				
			||||||
// excluding the current one.
 | 
					 | 
				
			||||||
func (s *Storage) RemoveAllButCurrent(artifact sourcev1.Artifact) error {
 | 
					func (s *Storage) RemoveAllButCurrent(artifact sourcev1.Artifact) error {
 | 
				
			||||||
	localPath := s.LocalPath(artifact)
 | 
						localPath := s.LocalPath(artifact)
 | 
				
			||||||
	dir := filepath.Dir(localPath)
 | 
						dir := filepath.Dir(localPath)
 | 
				
			||||||
| 
						 | 
					@ -132,8 +135,7 @@ func (s *Storage) RemoveAllButCurrent(artifact sourcev1.Artifact) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ArtifactExist returns a boolean indicating whether the v1beta1.Artifact exists in storage
 | 
					// ArtifactExist returns a boolean indicating whether the v1beta1.Artifact exists in storage and is a regular file.
 | 
				
			||||||
// and is a regular file.
 | 
					 | 
				
			||||||
func (s *Storage) ArtifactExist(artifact sourcev1.Artifact) bool {
 | 
					func (s *Storage) ArtifactExist(artifact sourcev1.Artifact) bool {
 | 
				
			||||||
	fi, err := os.Lstat(s.LocalPath(artifact))
 | 
						fi, err := os.Lstat(s.LocalPath(artifact))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -142,14 +144,13 @@ func (s *Storage) ArtifactExist(artifact sourcev1.Artifact) bool {
 | 
				
			||||||
	return fi.Mode().IsRegular()
 | 
						return fi.Mode().IsRegular()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ArchiveFileFilter must return true if a file should not be included
 | 
					// ArchiveFileFilter must return true if a file should not be included in the archive after inspecting the given path
 | 
				
			||||||
// in the archive after inspecting the given path and/or os.FileInfo.
 | 
					// and/or os.FileInfo.
 | 
				
			||||||
type ArchiveFileFilter func(p string, fi os.FileInfo) bool
 | 
					type ArchiveFileFilter func(p string, fi os.FileInfo) bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SourceIgnoreFilter returns an ArchiveFileFilter that filters out
 | 
					// SourceIgnoreFilter returns an ArchiveFileFilter that filters out files matching sourceignore.VCSPatterns and any of
 | 
				
			||||||
// files matching sourceignore.VCSPatterns and any of the provided
 | 
					// the provided patterns.
 | 
				
			||||||
// patterns. If an empty gitignore.Pattern slice is given, the matcher
 | 
					// If an empty gitignore.Pattern slice is given, the matcher is set to sourceignore.NewDefaultMatcher.
 | 
				
			||||||
// is set to sourceignore.NewDefaultMatcher.
 | 
					 | 
				
			||||||
func SourceIgnoreFilter(ps []gitignore.Pattern, domain []string) ArchiveFileFilter {
 | 
					func SourceIgnoreFilter(ps []gitignore.Pattern, domain []string) ArchiveFileFilter {
 | 
				
			||||||
	matcher := sourceignore.NewDefaultMatcher(ps, domain)
 | 
						matcher := sourceignore.NewDefaultMatcher(ps, domain)
 | 
				
			||||||
	if len(ps) > 0 {
 | 
						if len(ps) > 0 {
 | 
				
			||||||
| 
						 | 
					@ -163,10 +164,10 @@ func SourceIgnoreFilter(ps []gitignore.Pattern, domain []string) ArchiveFileFilt
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Archive atomically archives the given directory as a tarball to the
 | 
					// Archive atomically archives the given directory as a tarball to the given v1beta1.Artifact path, excluding
 | 
				
			||||||
// given v1beta1.Artifact path, excluding directories and any
 | 
					// directories and any ArchiveFileFilter matches. While archiving, any environment specific data (for example,
 | 
				
			||||||
// ArchiveFileFilter matches. If successful, it sets the checksum and
 | 
					// the user and group name) is stripped from file headers.
 | 
				
			||||||
// last update time on the artifact.
 | 
					// If successful, it sets the checksum and last update time on the artifact.
 | 
				
			||||||
func (s *Storage) Archive(artifact *sourcev1.Artifact, dir string, filter ArchiveFileFilter) (err error) {
 | 
					func (s *Storage) Archive(artifact *sourcev1.Artifact, dir string, filter ArchiveFileFilter) (err error) {
 | 
				
			||||||
	if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
 | 
						if f, err := os.Stat(dir); os.IsNotExist(err) || !f.IsDir() {
 | 
				
			||||||
		return fmt.Errorf("invalid dir path: %s", dir)
 | 
							return fmt.Errorf("invalid dir path: %s", dir)
 | 
				
			||||||
| 
						 | 
					@ -220,6 +221,16 @@ func (s *Storage) Archive(artifact *sourcev1.Artifact, dir string, filter Archiv
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		header.Name = relFilePath
 | 
							header.Name = relFilePath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// We want to remove any environment specific data as well, this
 | 
				
			||||||
 | 
							// ensures the checksum is purely content based.
 | 
				
			||||||
 | 
							header.Gid = 0
 | 
				
			||||||
 | 
							header.Uid = 0
 | 
				
			||||||
 | 
							header.Uname = ""
 | 
				
			||||||
 | 
							header.Gname = ""
 | 
				
			||||||
 | 
							header.ModTime = time.Time{}
 | 
				
			||||||
 | 
							header.AccessTime = time.Time{}
 | 
				
			||||||
 | 
							header.ChangeTime = time.Time{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := tw.WriteHeader(header); err != nil {
 | 
							if err := tw.WriteHeader(header); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -341,9 +352,8 @@ func (s *Storage) Copy(artifact *sourcev1.Artifact, reader io.Reader) (err error
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CopyFromPath atomically copies the contents of the given path to the path of
 | 
					// CopyFromPath atomically copies the contents of the given path to the path of the v1beta1.Artifact.
 | 
				
			||||||
// the v1beta1.Artifact. If successful, the checksum and last update time on the
 | 
					// If successful, the checksum and last update time on the artifact is set.
 | 
				
			||||||
// artifact is set.
 | 
					 | 
				
			||||||
func (s *Storage) CopyFromPath(artifact *sourcev1.Artifact, path string) (err error) {
 | 
					func (s *Storage) CopyFromPath(artifact *sourcev1.Artifact, path string) (err error) {
 | 
				
			||||||
	f, err := os.Open(path)
 | 
						f, err := os.Open(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -353,10 +363,10 @@ func (s *Storage) CopyFromPath(artifact *sourcev1.Artifact, path string) (err er
 | 
				
			||||||
	return s.Copy(artifact, f)
 | 
						return s.Copy(artifact, f)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CopyToPath copies the contents of the given artifact to the path.
 | 
					// CopyToPath copies the contents in the (sub)path of the given artifact to the given path.
 | 
				
			||||||
func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string) error {
 | 
					func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string) error {
 | 
				
			||||||
	// create a tmp directory to store artifact
 | 
						// create a tmp directory to store artifact
 | 
				
			||||||
	tmp, err := os.MkdirTemp("", "flux-include")
 | 
						tmp, err := os.MkdirTemp("", "flux-include-")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -371,7 +381,7 @@ func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string
 | 
				
			||||||
	defer f.Close()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// untar the artifact
 | 
						// untar the artifact
 | 
				
			||||||
	untarPath := filepath.Join(tmp, "tar")
 | 
						untarPath := filepath.Join(tmp, "unpack")
 | 
				
			||||||
	if _, err = untar.Untar(f, untarPath); err != nil {
 | 
						if _, err = untar.Untar(f, untarPath); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -382,15 +392,17 @@ func (s *Storage) CopyToPath(artifact *sourcev1.Artifact, subPath, toPath string
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// copy the artifact content to the destination dir
 | 
						// copy the artifact content to the destination dir
 | 
				
			||||||
	fromPath := filepath.Join(untarPath, subPath)
 | 
						fromPath, err := securejoin.SecureJoin(untarPath, subPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := fs.RenameWithFallback(fromPath, toPath); err != nil {
 | 
						if err := fs.RenameWithFallback(fromPath, toPath); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Symlink creates or updates a symbolic link for the given v1beta1.Artifact
 | 
					// Symlink creates or updates a symbolic link for the given v1beta1.Artifact and returns the URL for the symlink.
 | 
				
			||||||
// and returns the URL for the symlink.
 | 
					 | 
				
			||||||
func (s *Storage) Symlink(artifact sourcev1.Artifact, linkName string) (string, error) {
 | 
					func (s *Storage) Symlink(artifact sourcev1.Artifact, linkName string) (string, error) {
 | 
				
			||||||
	localPath := s.LocalPath(artifact)
 | 
						localPath := s.LocalPath(artifact)
 | 
				
			||||||
	dir := filepath.Dir(localPath)
 | 
						dir := filepath.Dir(localPath)
 | 
				
			||||||
| 
						 | 
					@ -427,13 +439,16 @@ func (s *Storage) Lock(artifact sourcev1.Artifact) (unlock func(), err error) {
 | 
				
			||||||
	return mutex.Lock()
 | 
						return mutex.Lock()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LocalPath returns the local path of the given artifact (that is: relative to
 | 
					// LocalPath returns the secure local path of the given artifact (that is: relative to the Storage.BasePath).
 | 
				
			||||||
// the Storage.BasePath).
 | 
					 | 
				
			||||||
func (s *Storage) LocalPath(artifact sourcev1.Artifact) string {
 | 
					func (s *Storage) LocalPath(artifact sourcev1.Artifact) string {
 | 
				
			||||||
	if artifact.Path == "" {
 | 
						if artifact.Path == "" {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return filepath.Join(s.BasePath, artifact.Path)
 | 
						path, err := securejoin.SecureJoin(s.BasePath, artifact.Path)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return path
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// newHash returns a new SHA1 hash.
 | 
					// newHash returns a new SHA1 hash.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,173 +17,131 @@ limitations under the License.
 | 
				
			||||||
package controllers
 | 
					package controllers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"math/rand"
 | 
						"math/rand"
 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	. "github.com/onsi/ginkgo"
 | 
						utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
				
			||||||
	. "github.com/onsi/gomega"
 | 
					 | 
				
			||||||
	"helm.sh/helm/v3/pkg/getter"
 | 
					 | 
				
			||||||
	"k8s.io/client-go/kubernetes/scheme"
 | 
						"k8s.io/client-go/kubernetes/scheme"
 | 
				
			||||||
	"k8s.io/client-go/rest"
 | 
					 | 
				
			||||||
	ctrl "sigs.k8s.io/controller-runtime"
 | 
						ctrl "sigs.k8s.io/controller-runtime"
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/client"
 | 
					
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/envtest"
 | 
						"github.com/fluxcd/pkg/runtime/controller"
 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
 | 
						"github.com/fluxcd/pkg/testserver"
 | 
				
			||||||
	logf "sigs.k8s.io/controller-runtime/pkg/log"
 | 
					 | 
				
			||||||
	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
						sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
				
			||||||
	// +kubebuilder:scaffold:imports
 | 
						// +kubebuilder:scaffold:imports
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/testenv"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
 | 
					// These tests make use of plain Go using Gomega for assertions.
 | 
				
			||||||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
 | 
					// At the beginning of every (sub)test Gomega can be initialized
 | 
				
			||||||
 | 
					// using gomega.NewWithT.
 | 
				
			||||||
 | 
					// Refer to http://onsi.github.io/gomega/ to learn more about
 | 
				
			||||||
 | 
					// Gomega.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var cfg *rest.Config
 | 
					const (
 | 
				
			||||||
var k8sClient client.Client
 | 
						timeout  = 10 * time.Second
 | 
				
			||||||
var k8sManager ctrl.Manager
 | 
						interval = 1 * time.Second
 | 
				
			||||||
var testEnv *envtest.Environment
 | 
					)
 | 
				
			||||||
var storage *Storage
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
var examplePublicKey []byte
 | 
					var (
 | 
				
			||||||
var examplePrivateKey []byte
 | 
						testEnv      *testenv.Environment
 | 
				
			||||||
var exampleCA []byte
 | 
						testStorage  *Storage
 | 
				
			||||||
 | 
						testServer   *testserver.ArtifactServer
 | 
				
			||||||
 | 
						testEventsH  controller.Events
 | 
				
			||||||
 | 
						testMetricsH controller.Metrics
 | 
				
			||||||
 | 
						ctx          = ctrl.SetupSignalHandler()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAPIs(t *testing.T) {
 | 
					var (
 | 
				
			||||||
	RegisterFailHandler(Fail)
 | 
						tlsPublicKey  []byte
 | 
				
			||||||
 | 
						tlsPrivateKey []byte
 | 
				
			||||||
	RunSpecsWithDefaultAndCustomReporters(t,
 | 
						tlsCA         []byte
 | 
				
			||||||
		"Controller Suite",
 | 
					)
 | 
				
			||||||
		[]Reporter{printer.NewlineReporter{}})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ = BeforeSuite(func(done Done) {
 | 
					 | 
				
			||||||
	logf.SetLogger(
 | 
					 | 
				
			||||||
		zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	By("bootstrapping test environment")
 | 
					 | 
				
			||||||
	t := true
 | 
					 | 
				
			||||||
	if os.Getenv("TEST_USE_EXISTING_CLUSTER") == "true" {
 | 
					 | 
				
			||||||
		testEnv = &envtest.Environment{
 | 
					 | 
				
			||||||
			UseExistingCluster: &t,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		testEnv = &envtest.Environment{
 | 
					 | 
				
			||||||
			CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	cfg, err = testEnv.Start()
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred())
 | 
					 | 
				
			||||||
	Expect(cfg).ToNot(BeNil())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = sourcev1.AddToScheme(scheme.Scheme)
 | 
					 | 
				
			||||||
	Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = sourcev1.AddToScheme(scheme.Scheme)
 | 
					 | 
				
			||||||
	Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = sourcev1.AddToScheme(scheme.Scheme)
 | 
					 | 
				
			||||||
	Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// +kubebuilder:scaffold:scheme
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Expect(loadExampleKeys()).To(Succeed())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tmpStoragePath, err := os.MkdirTemp("", "source-controller-storage-")
 | 
					 | 
				
			||||||
	Expect(err).NotTo(HaveOccurred(), "failed to create tmp storage dir")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	storage, err = NewStorage(tmpStoragePath, "localhost:5050", time.Second*30)
 | 
					 | 
				
			||||||
	Expect(err).NotTo(HaveOccurred(), "failed to create tmp storage")
 | 
					 | 
				
			||||||
	// serve artifacts from the filesystem, as done in main.go
 | 
					 | 
				
			||||||
	fs := http.FileServer(http.Dir(tmpStoragePath))
 | 
					 | 
				
			||||||
	http.Handle("/", fs)
 | 
					 | 
				
			||||||
	go http.ListenAndServe(":5050", nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	k8sManager, err = ctrl.NewManager(cfg, ctrl.Options{
 | 
					 | 
				
			||||||
		Scheme: scheme.Scheme,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = (&GitRepositoryReconciler{
 | 
					 | 
				
			||||||
		Client:  k8sManager.GetClient(),
 | 
					 | 
				
			||||||
		Scheme:  scheme.Scheme,
 | 
					 | 
				
			||||||
		Storage: storage,
 | 
					 | 
				
			||||||
	}).SetupWithManager(k8sManager)
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred(), "failed to setup GtRepositoryReconciler")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = (&HelmRepositoryReconciler{
 | 
					 | 
				
			||||||
		Client:  k8sManager.GetClient(),
 | 
					 | 
				
			||||||
		Scheme:  scheme.Scheme,
 | 
					 | 
				
			||||||
		Storage: storage,
 | 
					 | 
				
			||||||
		Getters: getter.Providers{getter.Provider{
 | 
					 | 
				
			||||||
			Schemes: []string{"http", "https"},
 | 
					 | 
				
			||||||
			New:     getter.NewHTTPGetter,
 | 
					 | 
				
			||||||
		}},
 | 
					 | 
				
			||||||
	}).SetupWithManager(k8sManager)
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred(), "failed to setup HelmRepositoryReconciler")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = (&HelmChartReconciler{
 | 
					 | 
				
			||||||
		Client:  k8sManager.GetClient(),
 | 
					 | 
				
			||||||
		Scheme:  scheme.Scheme,
 | 
					 | 
				
			||||||
		Storage: storage,
 | 
					 | 
				
			||||||
		Getters: getter.Providers{getter.Provider{
 | 
					 | 
				
			||||||
			Schemes: []string{"http", "https"},
 | 
					 | 
				
			||||||
			New:     getter.NewHTTPGetter,
 | 
					 | 
				
			||||||
		}},
 | 
					 | 
				
			||||||
	}).SetupWithManager(k8sManager)
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred(), "failed to setup HelmChartReconciler")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		err = k8sManager.Start(ctrl.SetupSignalHandler())
 | 
					 | 
				
			||||||
		Expect(err).ToNot(HaveOccurred())
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	k8sClient = k8sManager.GetClient()
 | 
					 | 
				
			||||||
	Expect(k8sClient).ToNot(BeNil())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close(done)
 | 
					 | 
				
			||||||
}, 60)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ = AfterSuite(func() {
 | 
					 | 
				
			||||||
	By("tearing down the test environment")
 | 
					 | 
				
			||||||
	if storage != nil {
 | 
					 | 
				
			||||||
		err := os.RemoveAll(storage.BasePath)
 | 
					 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err := testEnv.Stop()
 | 
					 | 
				
			||||||
	Expect(err).ToNot(HaveOccurred())
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	rand.Seed(time.Now().UnixNano())
 | 
						rand.Seed(time.Now().UnixNano())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func loadExampleKeys() (err error) {
 | 
					func TestMain(m *testing.M) {
 | 
				
			||||||
	examplePublicKey, err = os.ReadFile("testdata/certs/server.pem")
 | 
						initTestTLS()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testEnv = testenv.New(testenv.WithCRDPath(filepath.Join("..", "config", "crd", "bases")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						testServer, err = testserver.NewTempArtifactServer()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							panic(fmt.Sprintf("Failed to create a temporary storage server: %v", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	examplePrivateKey, err = os.ReadFile("testdata/certs/server-key.pem")
 | 
						fmt.Println("Starting the test storage server")
 | 
				
			||||||
 | 
						testServer.Start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testStorage, err = newTestStorage(testServer.HTTPServer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							panic(fmt.Sprintf("Failed to create a test storage: %v", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	exampleCA, err = os.ReadFile("testdata/certs/ca.pem")
 | 
					
 | 
				
			||||||
	return err
 | 
						testEventsH = controller.MakeEvents(testEnv, "source-controller-test", nil)
 | 
				
			||||||
 | 
						testMetricsH = controller.MustMakeMetrics(testEnv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := (&GitRepositoryReconciler{
 | 
				
			||||||
 | 
							Client:  testEnv,
 | 
				
			||||||
 | 
							Events:  testEventsH,
 | 
				
			||||||
 | 
							Metrics: testMetricsH,
 | 
				
			||||||
 | 
							Storage: testStorage,
 | 
				
			||||||
 | 
						}).SetupWithManager(testEnv); err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("Failed to start GitRepositoryReconciler: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							fmt.Println("Starting the test environment")
 | 
				
			||||||
 | 
							if err := testEnv.Start(ctx); err != nil {
 | 
				
			||||||
 | 
								panic(fmt.Sprintf("Failed to start the test environment manager: %v", err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						<-testEnv.Manager.Elected()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						code := m.Run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println("Stopping the test environment")
 | 
				
			||||||
 | 
						if err := testEnv.Stop(); err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("Failed to stop the test environment: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println("Stopping the storage server")
 | 
				
			||||||
 | 
						testServer.Stop()
 | 
				
			||||||
 | 
						if err := os.RemoveAll(testServer.Root()); err != nil {
 | 
				
			||||||
 | 
							panic(fmt.Sprintf("Failed to remove storage server dir: %v", err))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						os.Exit(code)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890")
 | 
					func initTestTLS() {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
func randStringRunes(n int) string {
 | 
						tlsPublicKey, err = os.ReadFile("testdata/certs/server.pem")
 | 
				
			||||||
	b := make([]rune, n)
 | 
						if err != nil {
 | 
				
			||||||
	for i := range b {
 | 
							panic(err)
 | 
				
			||||||
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
 | 
						}
 | 
				
			||||||
 | 
						tlsPrivateKey, err = os.ReadFile("testdata/certs/server-key.pem")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tlsCA, err = os.ReadFile("testdata/certs/ca.pem")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return string(b)
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newTestStorage(s *testserver.HTTPServer) (*Storage, error) {
 | 
				
			||||||
 | 
						storage, err := NewStorage(s.Root(), s.URL(), timeout)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return storage, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					**.txt
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Namespace
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: dummy
 | 
				
			||||||
| 
						 | 
					@ -299,10 +299,8 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>The secret name containing the Git credentials.
 | 
					<p>The secret name containing the Git credentials.
 | 
				
			||||||
For HTTPS repositories the secret must contain username and password
 | 
					For HTTPS repositories the secret must contain username and password fields.
 | 
				
			||||||
fields.
 | 
					For SSH repositories the secret must contain ‘identity’, ‘identity.pub’ and ‘known_hosts’ fields.</p>
 | 
				
			||||||
For SSH repositories the secret must contain identity, identity.pub and
 | 
					 | 
				
			||||||
known_hosts fields.</p>
 | 
					 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -358,7 +356,7 @@ GitRepositoryVerification
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>Verify OpenPGP signature for the Git commit HEAD points to.</p>
 | 
					<p>Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -370,9 +368,8 @@ string
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>Ignore overrides the set of excluded patterns in the .sourceignore format
 | 
					<p>Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
 | 
				
			||||||
(which is the same as .gitignore). If not provided, a default will be used,
 | 
					If not provided, a default will be used, consult the documentation for your version to find out what those are.</p>
 | 
				
			||||||
consult the documentation for your version to find out what those are.</p>
 | 
					 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -384,7 +381,8 @@ bool
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>This flag tells the controller to suspend the reconciliation of this source.</p>
 | 
					<p>Suspend tells the controller to suspend the reconciliation of this source.
 | 
				
			||||||
 | 
					This flag tells the controller to suspend the reconciliation of this source.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -409,8 +407,7 @@ bool
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>When enabled, after the clone is created, initializes all submodules within,
 | 
					<p>When enabled, after the clone is created, initializes all submodules within, using their default settings.
 | 
				
			||||||
using their default settings.
 | 
					 | 
				
			||||||
This option is available only when using the ‘go-git’ GitImplementation.</p>
 | 
					This option is available only when using the ‘go-git’ GitImplementation.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
| 
						 | 
					@ -424,7 +421,8 @@ This option is available only when using the ‘go-git’ GitImplementat
 | 
				
			||||||
</em>
 | 
					</em>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<p>Extra git repositories to map into the repository</p>
 | 
					<p>Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
 | 
				
			||||||
 | 
					this resource.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
</table>
 | 
					</table>
 | 
				
			||||||
| 
						 | 
					@ -1264,10 +1262,8 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>The secret name containing the Git credentials.
 | 
					<p>The secret name containing the Git credentials.
 | 
				
			||||||
For HTTPS repositories the secret must contain username and password
 | 
					For HTTPS repositories the secret must contain username and password fields.
 | 
				
			||||||
fields.
 | 
					For SSH repositories the secret must contain ‘identity’, ‘identity.pub’ and ‘known_hosts’ fields.</p>
 | 
				
			||||||
For SSH repositories the secret must contain identity, identity.pub and
 | 
					 | 
				
			||||||
known_hosts fields.</p>
 | 
					 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1323,7 +1319,7 @@ GitRepositoryVerification
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>Verify OpenPGP signature for the Git commit HEAD points to.</p>
 | 
					<p>Verification defines the configuration to verify the OpenPGP signature for the Git commit HEAD points to.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1335,9 +1331,8 @@ string
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>Ignore overrides the set of excluded patterns in the .sourceignore format
 | 
					<p>Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore).
 | 
				
			||||||
(which is the same as .gitignore). If not provided, a default will be used,
 | 
					If not provided, a default will be used, consult the documentation for your version to find out what those are.</p>
 | 
				
			||||||
consult the documentation for your version to find out what those are.</p>
 | 
					 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1349,7 +1344,8 @@ bool
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>This flag tells the controller to suspend the reconciliation of this source.</p>
 | 
					<p>Suspend tells the controller to suspend the reconciliation of this source.
 | 
				
			||||||
 | 
					This flag tells the controller to suspend the reconciliation of this source.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1374,8 +1370,7 @@ bool
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>When enabled, after the clone is created, initializes all submodules within,
 | 
					<p>When enabled, after the clone is created, initializes all submodules within, using their default settings.
 | 
				
			||||||
using their default settings.
 | 
					 | 
				
			||||||
This option is available only when using the ‘go-git’ GitImplementation.</p>
 | 
					This option is available only when using the ‘go-git’ GitImplementation.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
| 
						 | 
					@ -1389,7 +1384,8 @@ This option is available only when using the ‘go-git’ GitImplementat
 | 
				
			||||||
</em>
 | 
					</em>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<p>Extra git repositories to map into the repository</p>
 | 
					<p>Include defines a list of GitRepository resources which artifacts should be included in the artifact produced for
 | 
				
			||||||
 | 
					this resource.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
</tbody>
 | 
					</tbody>
 | 
				
			||||||
| 
						 | 
					@ -1448,8 +1444,7 @@ string
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<em>(Optional)</em>
 | 
					<em>(Optional)</em>
 | 
				
			||||||
<p>URL is the download link for the artifact output of the last repository
 | 
					<p>URL is the download link for the artifact output of the last repository sync.</p>
 | 
				
			||||||
sync.</p>
 | 
					 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1524,7 +1519,7 @@ string
 | 
				
			||||||
</em>
 | 
					</em>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<p>Mode describes what git object should be verified, currently (‘head’).</p>
 | 
					<p>Mode describes what Git object should be verified, currently (‘head’).</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
| 
						 | 
					@ -1537,7 +1532,7 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
 | 
				
			||||||
</em>
 | 
					</em>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
<td>
 | 
					<td>
 | 
				
			||||||
<p>The secret name containing the public keys of all trusted Git authors.</p>
 | 
					<p>SecretRef containing the public keys of all trusted Git authors.</p>
 | 
				
			||||||
</td>
 | 
					</td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
</tbody>
 | 
					</tbody>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										19
									
								
								go.mod
								
								
								
								
							| 
						 | 
					@ -6,15 +6,15 @@ replace github.com/fluxcd/source-controller/api => ./api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/Masterminds/semver/v3 v3.1.1
 | 
						github.com/Masterminds/semver/v3 v3.1.1
 | 
				
			||||||
	github.com/blang/semver/v4 v4.0.0
 | 
					 | 
				
			||||||
	github.com/cyphar/filepath-securejoin v0.2.2
 | 
						github.com/cyphar/filepath-securejoin v0.2.2
 | 
				
			||||||
	github.com/fluxcd/pkg/apis/meta v0.10.0
 | 
						github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1
 | 
				
			||||||
	github.com/fluxcd/pkg/gittestserver v0.3.0
 | 
						github.com/fluxcd/pkg/gittestserver v0.3.2
 | 
				
			||||||
	github.com/fluxcd/pkg/gitutil v0.1.0
 | 
						github.com/fluxcd/pkg/gitutil v0.1.0
 | 
				
			||||||
	github.com/fluxcd/pkg/helmtestserver v0.2.0
 | 
						github.com/fluxcd/pkg/helmtestserver v0.2.0
 | 
				
			||||||
	github.com/fluxcd/pkg/lockedfile v0.1.0
 | 
						github.com/fluxcd/pkg/lockedfile v0.1.0
 | 
				
			||||||
	github.com/fluxcd/pkg/runtime v0.12.0
 | 
						github.com/fluxcd/pkg/runtime v0.13.0-rc.2
 | 
				
			||||||
	github.com/fluxcd/pkg/ssh v0.1.0
 | 
						github.com/fluxcd/pkg/ssh v0.1.0
 | 
				
			||||||
 | 
						github.com/fluxcd/pkg/testserver v0.1.0
 | 
				
			||||||
	github.com/fluxcd/pkg/untar v0.1.0
 | 
						github.com/fluxcd/pkg/untar v0.1.0
 | 
				
			||||||
	github.com/fluxcd/pkg/version v0.1.0
 | 
						github.com/fluxcd/pkg/version v0.1.0
 | 
				
			||||||
	github.com/fluxcd/source-controller/api v0.15.3
 | 
						github.com/fluxcd/source-controller/api v0.15.3
 | 
				
			||||||
| 
						 | 
					@ -27,13 +27,14 @@ require (
 | 
				
			||||||
	github.com/onsi/gomega v1.13.0
 | 
						github.com/onsi/gomega v1.13.0
 | 
				
			||||||
	github.com/spf13/pflag v1.0.5
 | 
						github.com/spf13/pflag v1.0.5
 | 
				
			||||||
	golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
 | 
						golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
 | 
				
			||||||
	golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
 | 
						golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 | 
				
			||||||
	gotest.tools v2.2.0+incompatible
 | 
						gotest.tools v2.2.0+incompatible
 | 
				
			||||||
	helm.sh/helm/v3 v3.6.3
 | 
						helm.sh/helm/v3 v3.6.3
 | 
				
			||||||
	k8s.io/api v0.21.1
 | 
						k8s.io/api v0.21.2
 | 
				
			||||||
	k8s.io/apimachinery v0.21.1
 | 
						k8s.io/apimachinery v0.21.3
 | 
				
			||||||
	k8s.io/client-go v0.21.1
 | 
						k8s.io/client-go v0.21.2
 | 
				
			||||||
	sigs.k8s.io/controller-runtime v0.9.0
 | 
						k8s.io/utils v0.0.0-20210527160623-6fdb442a123b
 | 
				
			||||||
 | 
						sigs.k8s.io/controller-runtime v0.9.3
 | 
				
			||||||
	sigs.k8s.io/yaml v1.2.0
 | 
						sigs.k8s.io/yaml v1.2.0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										72
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										72
									
								
								go.sum
								
								
								
								
							| 
						 | 
					@ -111,10 +111,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 | 
				
			||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
					github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
				
			||||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
 | 
					github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
 | 
				
			||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 | 
					github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 | 
				
			||||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
 | 
					 | 
				
			||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 | 
					github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 | 
				
			||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
 | 
					 | 
				
			||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 | 
					 | 
				
			||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
 | 
					github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
 | 
				
			||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA=
 | 
					github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA=
 | 
				
			||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
 | 
					github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
 | 
				
			||||||
| 
						 | 
					@ -229,18 +226,18 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM
 | 
				
			||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
 | 
					github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
 | 
				
			||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 | 
					github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 | 
				
			||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 | 
					github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 | 
				
			||||||
github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSLjG2rlE=
 | 
					github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 h1:RHHrztAFv9wmjM+Pk7Svt1UdD+1SdnQSp76MWFiM7Hg=
 | 
				
			||||||
github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE=
 | 
					github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqBlSPkLk7dxi0UM=
 | 
				
			||||||
github.com/fluxcd/pkg/gittestserver v0.3.0 h1:6aa30mybecBwBWaJ2IEk7pQzefWnjWjxkTSrHMHawvg=
 | 
					github.com/fluxcd/pkg/gittestserver v0.3.2 h1:oc1OoZ4b+kAu0vu/RT9wUwuQZxSqEjBOlQWYYA+YeLM=
 | 
				
			||||||
github.com/fluxcd/pkg/gittestserver v0.3.0/go.mod h1:8j36Z6B0BuKNZZ6exAWoyDEpyQoFcjz1IX3WBT7PZNg=
 | 
					github.com/fluxcd/pkg/gittestserver v0.3.2/go.mod h1:8j36Z6B0BuKNZZ6exAWoyDEpyQoFcjz1IX3WBT7PZNg=
 | 
				
			||||||
github.com/fluxcd/pkg/gitutil v0.1.0 h1:VO3kJY/CKOCO4ysDNqfdpTg04icAKBOSb3lbR5uE/IE=
 | 
					github.com/fluxcd/pkg/gitutil v0.1.0 h1:VO3kJY/CKOCO4ysDNqfdpTg04icAKBOSb3lbR5uE/IE=
 | 
				
			||||||
github.com/fluxcd/pkg/gitutil v0.1.0/go.mod h1:Ybz50Ck5gkcnvF0TagaMwtlRy3X3wXuiri1HVsK5id4=
 | 
					github.com/fluxcd/pkg/gitutil v0.1.0/go.mod h1:Ybz50Ck5gkcnvF0TagaMwtlRy3X3wXuiri1HVsK5id4=
 | 
				
			||||||
github.com/fluxcd/pkg/helmtestserver v0.2.0 h1:cE7YHDmrWI0hr9QpaaeQ0vQ16Z0IiqZKiINDpqdY610=
 | 
					github.com/fluxcd/pkg/helmtestserver v0.2.0 h1:cE7YHDmrWI0hr9QpaaeQ0vQ16Z0IiqZKiINDpqdY610=
 | 
				
			||||||
github.com/fluxcd/pkg/helmtestserver v0.2.0/go.mod h1:Yie8n7xuu5Nvf1Q7302LKsubJhWpwzCaK0rLJvmF7aI=
 | 
					github.com/fluxcd/pkg/helmtestserver v0.2.0/go.mod h1:Yie8n7xuu5Nvf1Q7302LKsubJhWpwzCaK0rLJvmF7aI=
 | 
				
			||||||
github.com/fluxcd/pkg/lockedfile v0.1.0 h1:YsYFAkd6wawMCcD74ikadAKXA4s2sukdxrn7w8RB5eo=
 | 
					github.com/fluxcd/pkg/lockedfile v0.1.0 h1:YsYFAkd6wawMCcD74ikadAKXA4s2sukdxrn7w8RB5eo=
 | 
				
			||||||
github.com/fluxcd/pkg/lockedfile v0.1.0/go.mod h1:EJLan8t9MiOcgTs8+puDjbE6I/KAfHbdvIy9VUgIjm8=
 | 
					github.com/fluxcd/pkg/lockedfile v0.1.0/go.mod h1:EJLan8t9MiOcgTs8+puDjbE6I/KAfHbdvIy9VUgIjm8=
 | 
				
			||||||
github.com/fluxcd/pkg/runtime v0.12.0 h1:BPZZ8bBkimpqGAPXqOf3LTaw+tcw6HgbWyCuzbbsJGs=
 | 
					github.com/fluxcd/pkg/runtime v0.13.0-rc.2 h1:+4uTEg+CU++hlr7NpOP4KYp60MtHDOgYvpz/74tbATg=
 | 
				
			||||||
github.com/fluxcd/pkg/runtime v0.12.0/go.mod h1:EyaTR2TOYcjL5U//C4yH3bt2tvTgIOSXpVRbWxUn/C4=
 | 
					github.com/fluxcd/pkg/runtime v0.13.0-rc.2/go.mod h1:TmvE2cJl1QkgZNmmlr7XUKoWDQwUiM5/wTUxXsQVoc8=
 | 
				
			||||||
github.com/fluxcd/pkg/ssh v0.1.0 h1:cym2bqiT4IINOdLV0J6GYxer16Ii/7b2+RlK3CG+CnA=
 | 
					github.com/fluxcd/pkg/ssh v0.1.0 h1:cym2bqiT4IINOdLV0J6GYxer16Ii/7b2+RlK3CG+CnA=
 | 
				
			||||||
github.com/fluxcd/pkg/ssh v0.1.0/go.mod h1:KUuVhaB6AX3IHTGCd3Ti/nesn5t1Nz4zCThFkkjHctM=
 | 
					github.com/fluxcd/pkg/ssh v0.1.0/go.mod h1:KUuVhaB6AX3IHTGCd3Ti/nesn5t1Nz4zCThFkkjHctM=
 | 
				
			||||||
github.com/fluxcd/pkg/testserver v0.1.0 h1:nOYgM1HYFZNNSUFykuWDmrsxj4jQxUCvmLHWOQeqmyA=
 | 
					github.com/fluxcd/pkg/testserver v0.1.0 h1:nOYgM1HYFZNNSUFykuWDmrsxj4jQxUCvmLHWOQeqmyA=
 | 
				
			||||||
| 
						 | 
					@ -841,6 +838,7 @@ github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6Ut
 | 
				
			||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 | 
					github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 | 
				
			||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
 | 
					github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
				
			||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
 | 
					github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
 | 
				
			||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
 | 
					github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
 | 
				
			||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
 | 
					github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
 | 
				
			||||||
| 
						 | 
					@ -939,6 +937,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
 | 
				
			||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
 | 
					golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
| 
						 | 
					@ -979,8 +978,10 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
 | 
				
			||||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
					golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
					golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
 | 
					golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
 | 
					golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
					golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
 | 
				
			||||||
 | 
					golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
					golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
					golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
				
			||||||
| 
						 | 
					@ -994,8 +995,9 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 | 
				
			||||||
 | 
					golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
| 
						 | 
					@ -1052,10 +1054,14 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
 | 
					golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
 | 
				
			||||||
 | 
					golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
					golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
 | 
					golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
 | 
				
			||||||
| 
						 | 
					@ -1072,8 +1078,9 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
 | 
				
			||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
 | 
					 | 
				
			||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
					golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
 | 
					golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs=
 | 
				
			||||||
 | 
					golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
| 
						 | 
					@ -1122,8 +1129,9 @@ golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roY
 | 
				
			||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 | 
					golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
					golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
				
			||||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
 | 
					 | 
				
			||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
					golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs=
 | 
				
			||||||
 | 
					golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
| 
						 | 
					@ -1258,27 +1266,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 | 
				
			||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 | 
					honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 | 
				
			||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 | 
					honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 | 
				
			||||||
k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU=
 | 
					k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU=
 | 
				
			||||||
k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c=
 | 
					k8s.io/api v0.21.2 h1:vz7DqmRsXTCSa6pNxXwQ1IYeAZgdIsua+DZU+o+SX3Y=
 | 
				
			||||||
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
 | 
					k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
 | 
				
			||||||
k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc=
 | 
					k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc=
 | 
				
			||||||
k8s.io/apiextensions-apiserver v0.21.1 h1:AA+cnsb6w7SZ1vD32Z+zdgfXdXY8X9uGX5bN6EoPEIo=
 | 
					k8s.io/apiextensions-apiserver v0.21.2 h1:+exKMRep4pDrphEafRvpEi79wTnCFMqKf8LBtlA3yrE=
 | 
				
			||||||
k8s.io/apiextensions-apiserver v0.21.1/go.mod h1:KESQFCGjqVcVsZ9g0xX5bacMjyX5emuWcS2arzdEouA=
 | 
					k8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA=
 | 
				
			||||||
k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
 | 
					k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
 | 
				
			||||||
k8s.io/apimachinery v0.21.1 h1:Q6XuHGlj2xc+hlMCvqyYfbv3H7SRGn2c8NycxJquDVs=
 | 
					k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
 | 
				
			||||||
k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
 | 
					k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII=
 | 
				
			||||||
 | 
					k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=
 | 
				
			||||||
k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg=
 | 
					k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg=
 | 
				
			||||||
k8s.io/apiserver v0.21.1 h1:wTRcid53IhxhbFt4KTrFSw8tAncfr01EP91lzfcygVg=
 | 
					k8s.io/apiserver v0.21.2 h1:vfGLD8biFXHzbcIEXyW3652lDwkV8tZEFJAaS2iuJlw=
 | 
				
			||||||
k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY=
 | 
					k8s.io/apiserver v0.21.2/go.mod h1:lN4yBoGyiNT7SC1dmNk0ue6a5Wi6O3SWOIw91TsucQw=
 | 
				
			||||||
k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y=
 | 
					k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y=
 | 
				
			||||||
k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo=
 | 
					k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo=
 | 
				
			||||||
k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA=
 | 
					k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA=
 | 
				
			||||||
k8s.io/client-go v0.21.1 h1:bhblWYLZKUu+pm50plvQF8WpY6TXdRRtcS/K9WauOj4=
 | 
					k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0=
 | 
				
			||||||
k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs=
 | 
					k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
 | 
				
			||||||
k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q=
 | 
					k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q=
 | 
				
			||||||
k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q=
 | 
					k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U=
 | 
				
			||||||
k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw=
 | 
					k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw=
 | 
				
			||||||
k8s.io/component-base v0.21.1 h1:iLpj2btXbR326s/xNQWmPNGu0gaYSjzn7IN/5i28nQw=
 | 
					k8s.io/component-base v0.21.2 h1:EsnmFFoJ86cEywC0DoIkAUiEV6fjgauNugiw1lmIjs4=
 | 
				
			||||||
k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA=
 | 
					k8s.io/component-base v0.21.2/go.mod h1:9lvmIThzdlrJj5Hp8Z/TOgIkdfsNARQ1pT+3PByuiuc=
 | 
				
			||||||
k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U=
 | 
					k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U=
 | 
				
			||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 | 
					k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 | 
				
			||||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 | 
					k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 | 
				
			||||||
| 
						 | 
					@ -1299,8 +1308,10 @@ rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
 | 
				
			||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 | 
					rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 | 
				
			||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 | 
					rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 | 
				
			||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 | 
					sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 | 
				
			||||||
sigs.k8s.io/controller-runtime v0.9.0 h1:ZIZ/dtpboPSbZYY7uUz2OzrkaBTOThx2yekLtpGB+zY=
 | 
					sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 | 
				
			||||||
sigs.k8s.io/controller-runtime v0.9.0/go.mod h1:TgkfvrhhEw3PlI0BRL/5xM+89y3/yc0ZDfdbTl84si8=
 | 
					sigs.k8s.io/controller-runtime v0.9.2/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=
 | 
				
			||||||
 | 
					sigs.k8s.io/controller-runtime v0.9.3 h1:n075bHQ1wb8hpX7C27pNrqsb0fj8mcfCQfNX+oKTbYE=
 | 
				
			||||||
 | 
					sigs.k8s.io/controller-runtime v0.9.3/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=
 | 
				
			||||||
sigs.k8s.io/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ=
 | 
					sigs.k8s.io/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ=
 | 
				
			||||||
sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY=
 | 
					sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY=
 | 
				
			||||||
sigs.k8s.io/kustomize/cmd/config v0.9.7/go.mod h1:MvXCpHs77cfyxRmCNUQjIqCmZyYsbn5PyQpWiq44nW0=
 | 
					sigs.k8s.io/kustomize/cmd/config v0.9.7/go.mod h1:MvXCpHs77cfyxRmCNUQjIqCmZyYsbn5PyQpWiq44nW0=
 | 
				
			||||||
| 
						 | 
					@ -1308,8 +1319,9 @@ sigs.k8s.io/kustomize/kustomize/v4 v4.0.5/go.mod h1:C7rYla7sI8EnxHE/xEhRBSHMNfcL
 | 
				
			||||||
sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI=
 | 
					sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI=
 | 
				
			||||||
sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
 | 
					sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg=
 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8=
 | 
					 | 
				
			||||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 | 
				
			||||||
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
 | 
				
			||||||
 | 
					sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 | 
				
			||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 | 
					sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 | 
				
			||||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 | 
					sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 | 
				
			||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 | 
					sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										46
									
								
								main.go
								
								
								
								
							
							
						
						
									
										46
									
								
								main.go
								
								
								
								
							| 
						 | 
					@ -25,6 +25,13 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/client"
 | 
				
			||||||
 | 
						helper "github.com/fluxcd/pkg/runtime/controller"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/events"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/leaderelection"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/logger"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/pprof"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/runtime/probes"
 | 
				
			||||||
	"github.com/go-logr/logr"
 | 
						"github.com/go-logr/logr"
 | 
				
			||||||
	flag "github.com/spf13/pflag"
 | 
						flag "github.com/spf13/pflag"
 | 
				
			||||||
	"helm.sh/helm/v3/pkg/getter"
 | 
						"helm.sh/helm/v3/pkg/getter"
 | 
				
			||||||
| 
						 | 
					@ -33,15 +40,6 @@ import (
 | 
				
			||||||
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 | 
						clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 | 
				
			||||||
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
 | 
						_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
 | 
				
			||||||
	ctrl "sigs.k8s.io/controller-runtime"
 | 
						ctrl "sigs.k8s.io/controller-runtime"
 | 
				
			||||||
	crtlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/client"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/events"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/leaderelection"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/logger"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/metrics"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/pprof"
 | 
					 | 
				
			||||||
	"github.com/fluxcd/pkg/runtime/probes"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
						sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
 | 
				
			||||||
	"github.com/fluxcd/source-controller/controllers"
 | 
						"github.com/fluxcd/source-controller/controllers"
 | 
				
			||||||
| 
						 | 
					@ -99,26 +97,25 @@ func main() {
 | 
				
			||||||
	flag.BoolVar(&watchAllNamespaces, "watch-all-namespaces", true,
 | 
						flag.BoolVar(&watchAllNamespaces, "watch-all-namespaces", true,
 | 
				
			||||||
		"Watch for custom resources in all namespaces, if set to false it will only watch the runtime namespace.")
 | 
							"Watch for custom resources in all namespaces, if set to false it will only watch the runtime namespace.")
 | 
				
			||||||
	flag.DurationVar(&requeueDependency, "requeue-dependency", 30*time.Second, "The interval at which failing dependencies are reevaluated.")
 | 
						flag.DurationVar(&requeueDependency, "requeue-dependency", 30*time.Second, "The interval at which failing dependencies are reevaluated.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clientOptions.BindFlags(flag.CommandLine)
 | 
						clientOptions.BindFlags(flag.CommandLine)
 | 
				
			||||||
	logOptions.BindFlags(flag.CommandLine)
 | 
						logOptions.BindFlags(flag.CommandLine)
 | 
				
			||||||
	leaderElectionOptions.BindFlags(flag.CommandLine)
 | 
						leaderElectionOptions.BindFlags(flag.CommandLine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctrl.SetLogger(logger.NewLogger(logOptions))
 | 
						ctrl.SetLogger(logger.NewLogger(logOptions))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var eventRecorder *events.Recorder
 | 
						var eventRecorder *events.Recorder
 | 
				
			||||||
	if eventsAddr != "" {
 | 
						if eventsAddr != "" {
 | 
				
			||||||
		if er, err := events.NewRecorder(eventsAddr, controllerName); err != nil {
 | 
							er, err := events.NewRecorder(eventsAddr, controllerName)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			setupLog.Error(err, "unable to create event recorder")
 | 
								setupLog.Error(err, "unable to create event recorder")
 | 
				
			||||||
			os.Exit(1)
 | 
								os.Exit(1)
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			eventRecorder = er
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							eventRecorder = er
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricsRecorder := metrics.NewRecorder()
 | 
					 | 
				
			||||||
	crtlmetrics.Registry.MustRegister(metricsRecorder.Collectors()...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	watchNamespace := ""
 | 
						watchNamespace := ""
 | 
				
			||||||
	if !watchAllNamespaces {
 | 
						if !watchAllNamespaces {
 | 
				
			||||||
		watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
 | 
							watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
 | 
				
			||||||
| 
						 | 
					@ -147,18 +144,19 @@ func main() {
 | 
				
			||||||
	probes.SetupChecks(mgr, setupLog)
 | 
						probes.SetupChecks(mgr, setupLog)
 | 
				
			||||||
	pprof.SetupHandlers(mgr, setupLog)
 | 
						pprof.SetupHandlers(mgr, setupLog)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eventsH := helper.MakeEvents(mgr, controllerName, eventRecorder)
 | 
				
			||||||
 | 
						metricsH := helper.MustMakeMetrics(mgr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if storageAdvAddr == "" {
 | 
						if storageAdvAddr == "" {
 | 
				
			||||||
		storageAdvAddr = determineAdvStorageAddr(storageAddr, setupLog)
 | 
							storageAdvAddr = determineAdvStorageAddr(storageAddr, setupLog)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	storage := mustInitStorage(storagePath, storageAdvAddr, setupLog)
 | 
						storage := mustInitStorage(storagePath, storageAdvAddr, setupLog)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = (&controllers.GitRepositoryReconciler{
 | 
						if err = (&controllers.GitRepositoryReconciler{
 | 
				
			||||||
		Client:                mgr.GetClient(),
 | 
							Client:  mgr.GetClient(),
 | 
				
			||||||
		Scheme:                mgr.GetScheme(),
 | 
							Events:  eventsH,
 | 
				
			||||||
		Storage:               storage,
 | 
							Metrics: metricsH,
 | 
				
			||||||
		EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
							Storage: storage,
 | 
				
			||||||
		ExternalEventRecorder: eventRecorder,
 | 
					 | 
				
			||||||
		MetricsRecorder:       metricsRecorder,
 | 
					 | 
				
			||||||
	}).SetupWithManagerAndOptions(mgr, controllers.GitRepositoryReconcilerOptions{
 | 
						}).SetupWithManagerAndOptions(mgr, controllers.GitRepositoryReconcilerOptions{
 | 
				
			||||||
		MaxConcurrentReconciles:   concurrent,
 | 
							MaxConcurrentReconciles:   concurrent,
 | 
				
			||||||
		DependencyRequeueInterval: requeueDependency,
 | 
							DependencyRequeueInterval: requeueDependency,
 | 
				
			||||||
| 
						 | 
					@ -173,7 +171,7 @@ func main() {
 | 
				
			||||||
		Getters:               getters,
 | 
							Getters:               getters,
 | 
				
			||||||
		EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
							EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
				
			||||||
		ExternalEventRecorder: eventRecorder,
 | 
							ExternalEventRecorder: eventRecorder,
 | 
				
			||||||
		MetricsRecorder:       metricsRecorder,
 | 
							MetricsRecorder:       metricsH.MetricsRecorder,
 | 
				
			||||||
	}).SetupWithManagerAndOptions(mgr, controllers.HelmRepositoryReconcilerOptions{
 | 
						}).SetupWithManagerAndOptions(mgr, controllers.HelmRepositoryReconcilerOptions{
 | 
				
			||||||
		MaxConcurrentReconciles: concurrent,
 | 
							MaxConcurrentReconciles: concurrent,
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -187,7 +185,7 @@ func main() {
 | 
				
			||||||
		Getters:               getters,
 | 
							Getters:               getters,
 | 
				
			||||||
		EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
							EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
				
			||||||
		ExternalEventRecorder: eventRecorder,
 | 
							ExternalEventRecorder: eventRecorder,
 | 
				
			||||||
		MetricsRecorder:       metricsRecorder,
 | 
							MetricsRecorder:       metricsH.MetricsRecorder,
 | 
				
			||||||
	}).SetupWithManagerAndOptions(mgr, controllers.HelmChartReconcilerOptions{
 | 
						}).SetupWithManagerAndOptions(mgr, controllers.HelmChartReconcilerOptions{
 | 
				
			||||||
		MaxConcurrentReconciles: concurrent,
 | 
							MaxConcurrentReconciles: concurrent,
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -200,7 +198,7 @@ func main() {
 | 
				
			||||||
		Storage:               storage,
 | 
							Storage:               storage,
 | 
				
			||||||
		EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
							EventRecorder:         mgr.GetEventRecorderFor(controllerName),
 | 
				
			||||||
		ExternalEventRecorder: eventRecorder,
 | 
							ExternalEventRecorder: eventRecorder,
 | 
				
			||||||
		MetricsRecorder:       metricsRecorder,
 | 
							MetricsRecorder:       metricsH.MetricsRecorder,
 | 
				
			||||||
	}).SetupWithManagerAndOptions(mgr, controllers.BucketReconcilerOptions{
 | 
						}).SetupWithManagerAndOptions(mgr, controllers.BucketReconcilerOptions{
 | 
				
			||||||
		MaxConcurrentReconciles: concurrent,
 | 
							MaxConcurrentReconciles: concurrent,
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Flux authors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Commit struct {
 | 
				
			||||||
 | 
						valid bool
 | 
				
			||||||
 | 
						hash  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCommit(valid bool, hash string) Commit {
 | 
				
			||||||
 | 
						return Commit{
 | 
				
			||||||
 | 
							valid: valid,
 | 
				
			||||||
 | 
							hash:  hash,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c Commit) Verify(secret corev1.Secret) error {
 | 
				
			||||||
 | 
						if !c.valid {
 | 
				
			||||||
 | 
							return errors.New("invalid signature")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c Commit) Hash() string {
 | 
				
			||||||
 | 
						return c.hash
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -193,7 +193,7 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tags := make(map[string]string)
 | 
						tags := make(map[string]string)
 | 
				
			||||||
	tagTimestamps := make(map[string]time.Time)
 | 
						tagTimestamps := make(map[string]time.Time)
 | 
				
			||||||
	_ = repoTags.ForEach(func(t *plumbing.Reference) error {
 | 
						if err = repoTags.ForEach(func(t *plumbing.Reference) error {
 | 
				
			||||||
		revision := plumbing.Revision(t.Name().String())
 | 
							revision := plumbing.Revision(t.Name().String())
 | 
				
			||||||
		hash, err := repo.ResolveRevision(revision)
 | 
							hash, err := repo.ResolveRevision(revision)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,9 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tags[t.Name().Short()] = t.Strings()[1]
 | 
							tags[t.Name().Short()] = t.Strings()[1]
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return nil, "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var matchedVersions semver.Collection
 | 
						var matchedVersions semver.Collection
 | 
				
			||||||
	for tag, _ := range tags {
 | 
						for tag, _ := range tags {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,8 +19,11 @@ package libgit2
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/blang/semver/v4"
 | 
						"github.com/Masterminds/semver/v3"
 | 
				
			||||||
 | 
						"github.com/fluxcd/pkg/version"
 | 
				
			||||||
	git2go "github.com/libgit2/git2go/v31"
 | 
						git2go "github.com/libgit2/git2go/v31"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fluxcd/pkg/gitutil"
 | 
						"github.com/fluxcd/pkg/gitutil"
 | 
				
			||||||
| 
						 | 
					@ -168,7 +171,7 @@ type CheckoutSemVer struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *git.Auth) (git.Commit, string, error) {
 | 
					func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *git.Auth) (git.Commit, string, error) {
 | 
				
			||||||
	rng, err := semver.ParseRange(c.semVer)
 | 
						verConstraint, err := semver.NewConstraint(c.semVer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, "", fmt.Errorf("semver parse range error: %w", err)
 | 
							return nil, "", fmt.Errorf("semver parse range error: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -186,28 +189,61 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g
 | 
				
			||||||
		return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
 | 
							return nil, "", fmt.Errorf("unable to clone '%s', error: %w", url, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repoTags, err := repo.Tags.List()
 | 
						tags := make(map[string]string)
 | 
				
			||||||
	if err != nil {
 | 
						tagTimestamps := make(map[string]time.Time)
 | 
				
			||||||
		return nil, "", fmt.Errorf("git list tags error: %w", err)
 | 
						if err := repo.Tags.Foreach(func(name string, id *git2go.Oid) error {
 | 
				
			||||||
	}
 | 
							tag, err := repo.LookupTag(id)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
	svTags := make(map[string]string)
 | 
								return nil
 | 
				
			||||||
	var svers []semver.Version
 | 
					 | 
				
			||||||
	for _, tag := range repoTags {
 | 
					 | 
				
			||||||
		v, _ := semver.ParseTolerant(tag)
 | 
					 | 
				
			||||||
		if rng(v) {
 | 
					 | 
				
			||||||
			svers = append(svers, v)
 | 
					 | 
				
			||||||
			svTags[v.String()] = tag
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							commit, err := tag.Peel(git2go.ObjectCommit)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("can't get commit for tag %s: %w", name, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c, err := commit.AsCommit()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							tagTimestamps[tag.Name()] = c.Committer().When
 | 
				
			||||||
 | 
							tags[tag.Name()] = name
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return nil, "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(svers) == 0 {
 | 
						var matchedVersions semver.Collection
 | 
				
			||||||
 | 
						for tag, _ := range tags {
 | 
				
			||||||
 | 
							v, err := version.ParseVersion(tag)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !verConstraint.Check(v) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							matchedVersions = append(matchedVersions, v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(matchedVersions) == 0 {
 | 
				
			||||||
		return nil, "", fmt.Errorf("no match found for semver: %s", c.semVer)
 | 
							return nil, "", fmt.Errorf("no match found for semver: %s", c.semVer)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	semver.Sort(svers)
 | 
						// Sort versions
 | 
				
			||||||
	v := svers[len(svers)-1]
 | 
						sort.SliceStable(matchedVersions, func(i, j int) bool {
 | 
				
			||||||
	t := svTags[v.String()]
 | 
							left := matchedVersions[i]
 | 
				
			||||||
 | 
							right := matchedVersions[j]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !left.Equal(right) {
 | 
				
			||||||
 | 
								return left.LessThan(right)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Having tag target timestamps at our disposal, we further try to sort
 | 
				
			||||||
 | 
							// versions into a chronological order. This is especially important for
 | 
				
			||||||
 | 
							// versions that differ only by build metadata, because it is not considered
 | 
				
			||||||
 | 
							// a part of the comparable version in Semver
 | 
				
			||||||
 | 
							return tagTimestamps[left.String()].Before(tagTimestamps[right.String()])
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						v := matchedVersions[len(matchedVersions)-1]
 | 
				
			||||||
 | 
						t := v.Original()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ref, err := repo.References.Dwim(t)
 | 
						ref, err := repo.References.Dwim(t)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue