@@ -44,6 +44,7 @@ import (
44
44
kstatus "sigs.k8s.io/cli-utils/pkg/kstatus/status"
45
45
"sigs.k8s.io/controller-runtime/pkg/client"
46
46
"sigs.k8s.io/controller-runtime/pkg/client/fake"
47
+ fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
47
48
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
48
49
49
50
"github.com/fluxcd/pkg/apis/meta"
@@ -893,21 +894,11 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
893
894
chartPath = "testdata/charts/helmchart-0.1.0.tgz"
894
895
)
895
896
896
- // Login to the registry
897
- err := testRegistryServer .registryClient .Login (testRegistryServer .registryHost ,
898
- helmreg .LoginOptBasicAuth (testRegistryUsername , testRegistryPassword ),
899
- helmreg .LoginOptInsecure (true ))
900
- g .Expect (err ).NotTo (HaveOccurred ())
901
-
902
897
// Load a test chart
903
898
chartData , err := ioutil .ReadFile (chartPath )
904
- g .Expect (err ).NotTo (HaveOccurred ())
905
- metadata , err := extractChartMeta (chartData )
906
- g .Expect (err ).NotTo (HaveOccurred ())
907
899
908
900
// Upload the test chart
909
- ref := fmt .Sprintf ("%s/testrepo/%s:%s" , testRegistryServer .registryHost , metadata .Name , metadata .Version )
910
- _ , err = testRegistryServer .registryClient .Push (chartData , ref )
901
+ metadata , err := loadTestChartToOCI (chartData , chartPath , testRegistryServer )
911
902
g .Expect (err ).NotTo (HaveOccurred ())
912
903
913
904
storage , err := NewStorage (tmpDir , "example.com" , retentionTTL , retentionRecords )
@@ -2038,6 +2029,194 @@ func TestHelmChartReconciler_notify(t *testing.T) {
2038
2029
}
2039
2030
}
2040
2031
2032
+ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy (t * testing.T ) {
2033
+ const (
2034
+ chartPath = "testdata/charts/helmchart-0.1.0.tgz"
2035
+ )
2036
+
2037
+ type secretOptions struct {
2038
+ username string
2039
+ password string
2040
+ }
2041
+
2042
+ tests := []struct {
2043
+ name string
2044
+ url string
2045
+ registryOpts registryOptions
2046
+ secretOpts secretOptions
2047
+ provider string
2048
+ providerImg string
2049
+ want sreconcile.Result
2050
+ wantErr bool
2051
+ assertConditions []metav1.Condition
2052
+ }{
2053
+ {
2054
+ name : "HTTP without basic auth" ,
2055
+ want : sreconcile .ResultSuccess ,
2056
+ assertConditions : []metav1.Condition {
2057
+ * conditions .TrueCondition (sourcev1 .ArtifactOutdatedCondition , "NewChart" , "pulled '<helmchart>' chart with version '<version>'" ),
2058
+ },
2059
+ },
2060
+ {
2061
+ name : "HTTP with basic auth secret" ,
2062
+ want : sreconcile .ResultSuccess ,
2063
+ registryOpts : registryOptions {
2064
+ withBasicAuth : true ,
2065
+ },
2066
+ secretOpts : secretOptions {
2067
+ username : testRegistryUsername ,
2068
+ password : testRegistryPassword ,
2069
+ },
2070
+ assertConditions : []metav1.Condition {
2071
+ * conditions .TrueCondition (sourcev1 .ArtifactOutdatedCondition , "NewChart" , "pulled '<helmchart>' chart with version '<version>'" ),
2072
+ },
2073
+ },
2074
+ {
2075
+ name : "HTTP registry - basic auth with invalid secret" ,
2076
+ want : sreconcile .ResultEmpty ,
2077
+ wantErr : true ,
2078
+ registryOpts : registryOptions {
2079
+ withBasicAuth : true ,
2080
+ },
2081
+ secretOpts : secretOptions {
2082
+ username : "wrong-pass" ,
2083
+ password : "wrong-pass" ,
2084
+ },
2085
+ assertConditions : []metav1.Condition {
2086
+ * conditions .TrueCondition (sourcev1 .FetchFailedCondition , "Unknown" , "unknown build error: failed to login to OCI registry" ),
2087
+ },
2088
+ },
2089
+ {
2090
+ name : "with contextual login provider" ,
2091
+ wantErr : true ,
2092
+ provider : "aws" ,
2093
+ providerImg : "oci://123456789000.dkr.ecr.us-east-2.amazonaws.com/test" ,
2094
+ assertConditions : []metav1.Condition {
2095
+ * conditions .TrueCondition (sourcev1 .FetchFailedCondition , "Unknown" , "unknown build error: failed to get credential from" ),
2096
+ },
2097
+ },
2098
+ {
2099
+ name : "with contextual login provider and secretRef" ,
2100
+ want : sreconcile .ResultSuccess ,
2101
+ registryOpts : registryOptions {
2102
+ withBasicAuth : true ,
2103
+ },
2104
+ secretOpts : secretOptions {
2105
+ username : testRegistryUsername ,
2106
+ password : testRegistryPassword ,
2107
+ },
2108
+ provider : "azure" ,
2109
+ assertConditions : []metav1.Condition {
2110
+ * conditions .TrueCondition (sourcev1 .ArtifactOutdatedCondition , "NewChart" , "pulled '<helmchart>' chart with version '<version>'" ),
2111
+ },
2112
+ },
2113
+ }
2114
+
2115
+ for _ , tt := range tests {
2116
+ t .Run (tt .name , func (t * testing.T ) {
2117
+ g := NewWithT (t )
2118
+
2119
+ builder := fakeclient .NewClientBuilder ().WithScheme (testEnv .GetScheme ())
2120
+ workspaceDir := t .TempDir ()
2121
+ server , err := setupRegistryServer (ctx , workspaceDir , tt .registryOpts )
2122
+
2123
+ g .Expect (err ).NotTo (HaveOccurred ())
2124
+
2125
+ // Load a test chart
2126
+ chartData , err := ioutil .ReadFile (chartPath )
2127
+
2128
+ // Upload the test chart
2129
+ metadata , err := loadTestChartToOCI (chartData , chartPath , server )
2130
+ g .Expect (err ).NotTo (HaveOccurred ())
2131
+ g .Expect (err ).ToNot (HaveOccurred ())
2132
+
2133
+ repo := & sourcev1.HelmRepository {
2134
+ ObjectMeta : metav1.ObjectMeta {
2135
+ GenerateName : "auth-strategy-" ,
2136
+ },
2137
+ Spec : sourcev1.HelmRepositorySpec {
2138
+ Interval : metav1.Duration {Duration : interval },
2139
+ Timeout : & metav1.Duration {Duration : timeout },
2140
+ Type : sourcev1 .HelmRepositoryTypeOCI ,
2141
+ Provider : sourcev1 .GenericOCIProvider ,
2142
+ URL : fmt .Sprintf ("oci://%s/testrepo" , server .registryHost ),
2143
+ },
2144
+ }
2145
+
2146
+ if tt .provider != "" {
2147
+ repo .Spec .Provider = tt .provider
2148
+ }
2149
+ // If a provider specific image is provided, overwrite existing URL
2150
+ // set earlier. It'll fail but it's necessary to set them because
2151
+ // the login check expects the URLs to be of certain pattern.
2152
+ if tt .providerImg != "" {
2153
+ repo .Spec .URL = tt .providerImg
2154
+ }
2155
+
2156
+ if tt .secretOpts .username != "" && tt .secretOpts .password != "" {
2157
+ secret := & corev1.Secret {
2158
+ ObjectMeta : metav1.ObjectMeta {
2159
+ Name : "auth-secretref" ,
2160
+ },
2161
+ Type : corev1 .SecretTypeDockerConfigJson ,
2162
+ Data : map [string ][]byte {
2163
+ ".dockerconfigjson" : []byte (fmt .Sprintf (`{"auths": {%q: {"username": %q, "password": %q}}}` ,
2164
+ server .registryHost , tt .secretOpts .username , tt .secretOpts .password )),
2165
+ },
2166
+ }
2167
+
2168
+ repo .Spec .SecretRef = & meta.LocalObjectReference {
2169
+ Name : secret .Name ,
2170
+ }
2171
+ builder .WithObjects (secret , repo )
2172
+ } else {
2173
+ builder .WithObjects (repo )
2174
+ }
2175
+
2176
+ obj := & sourcev1.HelmChart {
2177
+ ObjectMeta : metav1.ObjectMeta {
2178
+ GenerateName : "auth-strategy-" ,
2179
+ },
2180
+ Spec : sourcev1.HelmChartSpec {
2181
+ Chart : metadata .Name ,
2182
+ Version : metadata .Version ,
2183
+ SourceRef : sourcev1.LocalHelmChartSourceReference {
2184
+ Kind : sourcev1 .HelmRepositoryKind ,
2185
+ Name : repo .Name ,
2186
+ },
2187
+ Interval : metav1.Duration {Duration : interval },
2188
+ },
2189
+ }
2190
+
2191
+ r := & HelmChartReconciler {
2192
+ Client : builder .Build (),
2193
+ EventRecorder : record .NewFakeRecorder (32 ),
2194
+ Getters : testGetters ,
2195
+ RegistryClientGenerator : registry .ClientGenerator ,
2196
+ }
2197
+
2198
+ var b chart.Build
2199
+ defer func () {
2200
+ if _ , err := os .Stat (b .Path ); ! os .IsNotExist (err ) {
2201
+ err := os .Remove (b .Path )
2202
+ g .Expect (err ).NotTo (HaveOccurred ())
2203
+ }
2204
+ }()
2205
+
2206
+ assertConditions := tt .assertConditions
2207
+ for k := range assertConditions {
2208
+ assertConditions [k ].Message = strings .ReplaceAll (assertConditions [k ].Message , "<helmchart>" , metadata .Name )
2209
+ assertConditions [k ].Message = strings .ReplaceAll (assertConditions [k ].Message , "<version>" , metadata .Version )
2210
+ }
2211
+
2212
+ got , err := r .reconcileSource (ctx , obj , & b )
2213
+ g .Expect (err != nil ).To (Equal (tt .wantErr ))
2214
+ g .Expect (got ).To (Equal (tt .want ))
2215
+ g .Expect (obj .Status .Conditions ).To (conditions .MatchConditions (tt .assertConditions ))
2216
+ })
2217
+ }
2218
+ }
2219
+
2041
2220
// extractChartMeta is used to extract a chart metadata from a byte array
2042
2221
func extractChartMeta (chartData []byte ) (* hchart.Metadata , error ) {
2043
2222
ch , err := loader .LoadArchive (bytes .NewReader (chartData ))
@@ -2046,3 +2225,32 @@ func extractChartMeta(chartData []byte) (*hchart.Metadata, error) {
2046
2225
}
2047
2226
return ch .Metadata , nil
2048
2227
}
2228
+
2229
+ func loadTestChartToOCI (chartData []byte , chartPath string , server * registryClientTestServer ) (* hchart.Metadata , error ) {
2230
+ // Login to the registry
2231
+ err := server .registryClient .Login (server .registryHost ,
2232
+ helmreg .LoginOptBasicAuth (testRegistryUsername , testRegistryPassword ),
2233
+ helmreg .LoginOptInsecure (true ))
2234
+ if err != nil {
2235
+ return nil , err
2236
+ }
2237
+
2238
+ // Load a test chart
2239
+ chartData , err = ioutil .ReadFile (chartPath )
2240
+ if err != nil {
2241
+ return nil , err
2242
+ }
2243
+ metadata , err := extractChartMeta (chartData )
2244
+ if err != nil {
2245
+ return nil , err
2246
+ }
2247
+
2248
+ // Upload the test chart
2249
+ ref := fmt .Sprintf ("%s/testrepo/%s:%s" , server .registryHost , metadata .Name , metadata .Version )
2250
+ _ , err = server .registryClient .Push (chartData , ref )
2251
+ if err != nil {
2252
+ return nil , err
2253
+ }
2254
+
2255
+ return metadata , nil
2256
+ }
0 commit comments