Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.

Commit 82ef38e

Browse files
authored
Merge branch 'main' into improve-oidc-docs
2 parents 95d5c0d + 8693f39 commit 82ef38e

17 files changed

Lines changed: 475 additions & 339 deletions

File tree

.github/workflows/kubeapps-general.yaml

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ on:
1313
type: boolean
1414
required: false
1515
default: true
16+
trigger_release:
17+
type: boolean
18+
required: false
19+
default: false
1620

1721
env:
1822
CHARTMUSEUM_VERSION: "3.9.1"
@@ -86,7 +90,6 @@ jobs:
8690
postgresql_version: ${{ steps.set-outputs.outputs.postgresql_version }}
8791
rust_version: ${{ steps.set-outputs.outputs.rust_version }}
8892
running_on_main: ${{ steps.set-outputs.outputs.running_on_main }}
89-
running_on_tag: ${{ steps.set-outputs.outputs.running_on_tag }}
9093
ssh_key_kubeapps_deploy_filename: ${{ steps.set-outputs.outputs.ssh_key_kubeapps_deploy_filename }}
9194
ssh_key_forked_charts_deploy_filename: ${{ steps.set-outputs.outputs.ssh_key_forked_charts_deploy_filename }}
9295
triggered_from_fork: ${{ steps.set-outputs.outputs.triggered_from_fork }}
@@ -134,12 +137,6 @@ jobs:
134137
echo "running_on_main=false" >> $GITHUB_OUTPUT
135138
fi
136139
137-
if [[ ${GITHUB_REF_TYPE} == "tag" && ${GITHUB_REF_NAME} =~ ^v[0-9]+ ]]; then
138-
echo "running_on_tag=true" >> $GITHUB_OUTPUT
139-
else
140-
echo "running_on_tag=false" >> $GITHUB_OUTPUT
141-
fi
142-
143140
# TODO(bjesus) Once we've properly tested the release job, we can/should remove this hack, just leave the content from the else branch
144141
if [[ ${GITHUB_REF_TYPE} == "tag" && ${GITHUB_REF_NAME} == 'test-'* ]]; then
145142
echo "dev_mode=true" >> $GITHUB_OUTPUT
@@ -165,7 +162,6 @@ jobs:
165162
echo "POSTGRESQL_VERSION: ${{steps.set-outputs.outputs.postgresql_version}}"
166163
echo "RUST_VERSION: ${{steps.set-outputs.outputs.rust_version}}"
167164
echo "RUNNING_ON_MAIN: ${{steps.set-outputs.outputs.running_on_main}}"
168-
echo "RUNNING_ON_TAG: ${{steps.set-outputs.outputs.running_on_tag}}"
169165
echo "SSH_KEY_KUBEAPPS_DEPLOY_FILENAME: ${{steps.set-outputs.outputs.ssh_key_kubeapps_deploy_filename}}"
170166
echo "SSH_KEY_FORKED_CHARTS_DEPLOY_FILENAME: ${{steps.set-outputs.outputs.ssh_key_forked_charts_deploy_filename}}"
171167
echo "TRIGGERED_FROM_FORK: ${{steps.set-outputs.outputs.triggered_from_fork}}"
@@ -554,7 +550,7 @@ jobs:
554550
run: exit 1
555551

556552
push_images:
557-
if: needs.setup.outputs.running_on_main == 'true' || needs.setup.outputs.running_on_tag == 'true'
553+
if: needs.setup.outputs.running_on_main == 'true' || inputs.trigger_release
558554
runs-on: ubuntu-latest
559555
needs:
560556
- setup
@@ -617,7 +613,7 @@ jobs:
617613
sync_chart_from_bitnami:
618614
needs:
619615
- setup
620-
if: needs.setup.outputs.running_on_main == 'true'
616+
if: needs.setup.outputs.running_on_main == 'true' || inputs.trigger_release
621617
runs-on: ubuntu-latest
622618
steps:
623619
- uses: actions/checkout@v3
@@ -676,7 +672,7 @@ jobs:
676672
- local_e2e_tests
677673
- GKE_REGULAR_VERSION
678674
- GKE_STABLE_VERSION
679-
if: needs.setup.outputs.running_on_tag == 'true'
675+
if: inputs.trigger_release
680676
runs-on: ubuntu-latest
681677
steps:
682678
- uses: actions/checkout@v3
@@ -727,7 +723,7 @@ jobs:
727723
${DEV_MODE}
728724
729725
release:
730-
if: needs.setup.outputs.running_on_tag == 'true'
726+
if: inputs.trigger_release
731727
needs:
732728
- setup
733729
- sync_chart_to_bitnami
@@ -744,12 +740,14 @@ jobs:
744740
- # Assuming there is a personal access token created in GitHub granted with the scopes
745741
# "repo:status", "public_repo" and "read:org"
746742
name: Run the create_release script
743+
env:
744+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
747745
run: |
748746
set -eu
749747
./script/create_release.sh "${GITHUB_REF_NAME}" "${KUBEAPPS_REPO}"
750748
751749
gke_setup:
752-
if: needs.setup.outputs.running_on_tag == 'true' || inputs.run_gke_tests
750+
if: inputs.run_gke_tests
753751
needs:
754752
- setup
755753
- test_go

.github/workflows/kubeapps-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99
tags:
1010
- 'v[0-9]+.[0-9]+.[0-9]+'
1111
# TODO(bjesus) Remove the following line once we have tested the release process
12-
- 'test-.*'
12+
- 'test-v[0-9]+.[0-9]+.[0-9]+'
1313

1414
concurrency:
1515
group: ${{ github.head_ref || github.ref_name }}_release
@@ -22,3 +22,4 @@ jobs:
2222
with:
2323
run_gke_tests: true
2424
run_linters: false
25+
trigger_release: true

cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/repositories.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (s *Server) newRepo(ctx context.Context, repo *HelmRepository) (*corev1.Pac
7878
}
7979

8080
// Handle imagesPullSecret if any
81-
imagePullSecret, imagePullSecretIsKubeappsManaged, err := handleImagesPullSecretForCreate(ctx, typedClient, repo)
81+
imagePullSecret, imagePullSecretIsKubeappsManaged, err := handleImagesPullSecretForCreate(ctx, typedClient, repo.name, repo.customDetail)
8282
if err != nil {
8383
return nil, err
8484
}
@@ -300,7 +300,7 @@ func (s *Server) updateRepo(ctx context.Context,
300300
appRepo.Spec.TLSInsecureSkipVerify = repo.tlsConfig != nil && repo.tlsConfig.InsecureSkipVerify
301301

302302
// validate and get updated (or newly created) secret
303-
secret, secretIsKubeappsManaged, secretIsUpdated, err := handleAuthSecretForUpdate(ctx, typedClient, repo.name, repo.tlsConfig, repo.auth, secret)
303+
secret, secretIsKubeappsManaged, secretIsUpdated, err := handleAuthSecretForUpdate(ctx, typedClient, appRepo, repo.tlsConfig, repo.auth, secret)
304304
if err != nil {
305305
return nil, err
306306
}
@@ -315,7 +315,7 @@ func (s *Server) updateRepo(ctx context.Context,
315315
}
316316

317317
// Handle imagesPullSecret if any
318-
imagePullSecret, imagePullSecretIsKubeappsManaged, imagePullSecretIsUpdated, err := handleImagesPullSecretForUpdate(ctx, typedClient, repo, imagePullSecret)
318+
imagePullSecret, imagePullSecretIsKubeappsManaged, imagePullSecretIsUpdated, err := handleImagesPullSecretForUpdate(ctx, typedClient, appRepo, repo.customDetail, imagePullSecret)
319319
if err != nil {
320320
return nil, err
321321
}

cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/repositories_auth.go

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,16 @@ const (
3131
SecretCaKey = "ca.crt"
3232
SecretAuthHeaderKey = "authorizationHeader"
3333
DockerConfigJsonKey = ".dockerconfigjson"
34+
35+
Annotation_ManagedBy_Key = "kubeapps.dev/managed-by"
36+
Annotation_ManagedBy_Value = "plugin:helm"
3437
)
3538

36-
func newLocalOpaqueSecret(ownerRepo types.NamespacedName) *k8scorev1.Secret {
39+
func newLocalOpaqueSecret(repoName string) *k8scorev1.Secret {
3740
return &k8scorev1.Secret{
3841
ObjectMeta: metav1.ObjectMeta{
39-
Name: helm.SecretNameForRepo(ownerRepo.Name),
42+
Name: helm.SecretNameForRepo(repoName),
43+
Annotations: map[string]string{Annotation_ManagedBy_Key: Annotation_ManagedBy_Value},
4044
},
4145
Type: k8scorev1.SecretTypeOpaque,
4246
Data: map[string][]byte{},
@@ -62,10 +66,10 @@ func handleAuthSecretForCreate(
6266

6367
// create/get secret
6468
if hasCaRef || hasAuthRef {
65-
secret, err := validateUserManagedRepoSecret(ctx, typedClient, repoName, tlsConfig, auth)
69+
secret, err := validateUserManagedRepoSecret(ctx, typedClient, repoName.Namespace, tlsConfig, auth)
6670
return secret, false, err
6771
} else if hasCaData || hasAuthData {
68-
secret, _, err := newSecretFromTlsConfigAndAuth(repoName, tlsConfig, auth)
72+
secret, _, err := newSecretFromTlsConfigAndAuth(repoName.Name, tlsConfig, auth)
6973
return secret, true, err
7074
} else {
7175
return nil, false, nil
@@ -75,17 +79,18 @@ func handleAuthSecretForCreate(
7579
func handleImagesPullSecretForCreate(
7680
ctx context.Context,
7781
typedClient kubernetes.Interface,
78-
repo *HelmRepository) (*k8scorev1.Secret, bool, error) {
82+
repoName types.NamespacedName,
83+
customDetail *v1alpha1.HelmPackageRepositoryCustomDetail) (*k8scorev1.Secret, bool, error) {
7984

80-
hasRef := repo.customDetail != nil && repo.customDetail.ImagesPullSecret != nil && repo.customDetail.ImagesPullSecret.GetSecretRef() != ""
81-
hasData := repo.customDetail != nil && repo.customDetail.ImagesPullSecret != nil && repo.customDetail.ImagesPullSecret.GetCredentials() != nil
85+
hasRef := customDetail != nil && customDetail.ImagesPullSecret != nil && customDetail.ImagesPullSecret.GetSecretRef() != ""
86+
hasData := customDetail != nil && customDetail.ImagesPullSecret != nil && customDetail.ImagesPullSecret.GetCredentials() != nil
8287

8388
// create/get secret
8489
if hasRef {
85-
secret, err := validateDockerImagePullSecret(ctx, typedClient, repo.name, repo.customDetail.ImagesPullSecret.GetSecretRef())
90+
secret, err := validateDockerImagePullSecret(ctx, typedClient, repoName.Namespace, customDetail.ImagesPullSecret.GetSecretRef())
8691
return secret, false, err
8792
} else if hasData {
88-
secret, _, err := newDockerImagePullSecret(repo.name, repo.customDetail.ImagesPullSecret.GetCredentials())
93+
secret, _, err := newDockerImagePullSecret(repoName.Name, customDetail.ImagesPullSecret.GetCredentials())
8994
return secret, true, err
9095
} else {
9196
return nil, false, nil
@@ -95,7 +100,7 @@ func handleImagesPullSecretForCreate(
95100
func handleAuthSecretForUpdate(
96101
ctx context.Context,
97102
typedClient kubernetes.Interface,
98-
repoName types.NamespacedName,
103+
repo *apprepov1alpha1.AppRepository,
99104
tlsConfig *corev1.PackageRepositoryTlsConfig,
100105
auth *corev1.PackageRepositoryAuth,
101106
secret *k8scorev1.Secret) (updatedSecret *k8scorev1.Secret, secretIsKubeappsManaged bool, secretIsUpdated bool, err error) {
@@ -112,19 +117,19 @@ func handleAuthSecretForUpdate(
112117

113118
// check we cannot change mode (per design spec)
114119
if secret != nil && (hasCaRef || hasCaData || hasAuthRef || hasAuthData) {
115-
if isAuthSecretKubeappsManaged(repoName.Name, secret) != (hasAuthData || hasCaData) {
120+
if isAuthSecretKubeappsManaged(repo, secret) != (hasAuthData || hasCaData) {
116121
return nil, false, false, status.Errorf(codes.InvalidArgument, "Auth management mode cannot be changed")
117122
}
118123
}
119124

120125
// handle user managed secret
121126
if hasCaRef || hasAuthRef {
122-
updatedSecret, err := validateUserManagedRepoSecret(ctx, typedClient, repoName, tlsConfig, auth)
127+
updatedSecret, err := validateUserManagedRepoSecret(ctx, typedClient, repo.GetNamespace(), tlsConfig, auth)
123128
return updatedSecret, false, true, err
124129
}
125130

126131
// handle kubeapps managed secret
127-
updatedSecret, isSameSecret, err := newSecretFromTlsConfigAndAuth(repoName, tlsConfig, auth)
132+
updatedSecret, isSameSecret, err := newSecretFromTlsConfigAndAuth(repo.GetName(), tlsConfig, auth)
128133
if err != nil {
129134
return nil, true, false, err
130135
} else if isSameSecret {
@@ -146,12 +151,13 @@ func handleAuthSecretForUpdate(
146151
func handleImagesPullSecretForUpdate(
147152
ctx context.Context,
148153
typedClient kubernetes.Interface,
149-
repo *HelmRepository,
154+
repo *apprepov1alpha1.AppRepository,
155+
customDetail *v1alpha1.HelmPackageRepositoryCustomDetail,
150156
secret *k8scorev1.Secret) (updatedSecret *k8scorev1.Secret, secretIsKubeappsManaged bool, secretIsUpdated bool, err error) {
151157

152158
var imagesPullSecrets *v1alpha1.ImagesPullSecret
153-
if repo.customDetail != nil && repo.customDetail.ImagesPullSecret != nil {
154-
imagesPullSecrets = repo.customDetail.ImagesPullSecret
159+
if customDetail != nil && customDetail.ImagesPullSecret != nil {
160+
imagesPullSecrets = customDetail.ImagesPullSecret
155161
} else {
156162
imagesPullSecrets = &v1alpha1.ImagesPullSecret{}
157163
}
@@ -161,19 +167,19 @@ func handleImagesPullSecretForUpdate(
161167

162168
// check we are not changing mode
163169
if secret != nil && (hasRef || hasData) {
164-
if isImagesPullSecretKubeappsManaged(repo.name.Name, secret) != hasData {
170+
if isImagesPullSecretKubeappsManaged(repo, secret) != hasData {
165171
return nil, false, false, status.Errorf(codes.InvalidArgument, "Auth management mode cannot be changed")
166172
}
167173
}
168174

169175
// handle user managed secret
170176
if hasRef {
171-
updatedSecret, err := validateDockerImagePullSecret(ctx, typedClient, repo.name, imagesPullSecrets.GetSecretRef())
177+
updatedSecret, err := validateDockerImagePullSecret(ctx, typedClient, repo.GetNamespace(), imagesPullSecrets.GetSecretRef())
172178
return updatedSecret, false, true, err
173179
}
174180

175181
// handle kubeapps managed secret
176-
updatedSecret, isSameSecret, err := newDockerImagePullSecret(repo.name, imagesPullSecrets.GetCredentials())
182+
updatedSecret, isSameSecret, err := newDockerImagePullSecret(repo.GetName(), imagesPullSecrets.GetCredentials())
177183
if err != nil {
178184
return nil, true, false, err
179185
} else if isSameSecret {
@@ -193,7 +199,7 @@ func handleImagesPullSecretForUpdate(
193199
}
194200

195201
// this func is only used with kubeapps-managed secrets
196-
func newSecretFromTlsConfigAndAuth(repoName types.NamespacedName,
202+
func newSecretFromTlsConfigAndAuth(repoName string,
197203
tlsConfig *corev1.PackageRepositoryTlsConfig,
198204
auth *corev1.PackageRepositoryAuth) (secret *k8scorev1.Secret, isSameSecret bool, err error) {
199205
if tlsConfig != nil {
@@ -370,10 +376,10 @@ func createKubeappsManagedRepoSecret(
370376

371377
func validateDockerImagePullSecret(ctx context.Context,
372378
typedClient kubernetes.Interface,
373-
repoName types.NamespacedName,
379+
namespace string,
374380
secretName string) (*k8scorev1.Secret, error) {
375381

376-
if secret, err := typedClient.CoreV1().Secrets(repoName.Namespace).Get(ctx, secretName, metav1.GetOptions{}); err != nil {
382+
if secret, err := typedClient.CoreV1().Secrets(namespace).Get(ctx, secretName, metav1.GetOptions{}); err != nil {
377383
return nil, statuserror.FromK8sError("get", "secret", secretName, err)
378384
} else if secret.Type != k8scorev1.SecretTypeDockerConfigJson {
379385
return nil, status.Errorf(codes.InvalidArgument, "Images Docker pull secret %s does not have valid type", secretName)
@@ -388,15 +394,16 @@ func imagesPullSecretName(repoName string) string {
388394
return fmt.Sprintf("pullsecret-%s", repoName)
389395
}
390396

391-
func newDockerImagePullSecret(ownerRepo types.NamespacedName, credentials *corev1.DockerCredentials) (secret *k8scorev1.Secret, isSameSecret bool, err error) {
397+
func newDockerImagePullSecret(repoName string, credentials *corev1.DockerCredentials) (secret *k8scorev1.Secret, isSameSecret bool, err error) {
392398
if credentials != nil {
393399
if credentials.Server == "" || credentials.Username == "" || credentials.Password == "" || credentials.Email == "" {
394400
return nil, false, status.Errorf(codes.InvalidArgument, "Images pull secret Docker credentials are wrong")
395401
}
396402

397403
secret = &k8scorev1.Secret{
398404
ObjectMeta: metav1.ObjectMeta{
399-
Name: imagesPullSecretName(ownerRepo.Name),
405+
Name: imagesPullSecretName(repoName),
406+
Annotations: map[string]string{Annotation_ManagedBy_Key: Annotation_ManagedBy_Value},
400407
},
401408
Type: k8scorev1.SecretTypeDockerConfigJson,
402409
Data: map[string][]byte{},
@@ -461,7 +468,7 @@ func (s *Server) deleteRepositorySecretFromNamespace(typedClient kubernetes.Inte
461468
func validateUserManagedRepoSecret(
462469
ctx context.Context,
463470
typedClient kubernetes.Interface,
464-
repoName types.NamespacedName,
471+
namespace string,
465472
tlsConfig *corev1.PackageRepositoryTlsConfig,
466473
auth *corev1.PackageRepositoryAuth) (*k8scorev1.Secret, error) {
467474
var secretRefTls, secretRefAuth string
@@ -498,7 +505,7 @@ func validateUserManagedRepoSecret(
498505
if secretRef != "" {
499506
var err error
500507
// check that the specified secret exists
501-
if secret, err = typedClient.CoreV1().Secrets(repoName.Namespace).Get(ctx, secretRef, metav1.GetOptions{}); err != nil {
508+
if secret, err = typedClient.CoreV1().Secrets(namespace).Get(ctx, secretRef, metav1.GetOptions{}); err != nil {
502509
return nil, statuserror.FromK8sError("get", "secret", secretRef, err)
503510
} else {
504511
// also check that the data in the opaque secret corresponds
@@ -532,7 +539,7 @@ func validateUserManagedRepoSecret(
532539
func getRepoImagesPullSecret(source *apprepov1alpha1.AppRepository, imagesPullSecret *k8scorev1.Secret) *v1alpha1.ImagesPullSecret {
533540
if imagesPullSecret == nil {
534541
return nil
535-
} else if isImagesPullSecretKubeappsManaged(source.GetName(), imagesPullSecret) {
542+
} else if isImagesPullSecretKubeappsManaged(source, imagesPullSecret) {
536543
return &v1alpha1.ImagesPullSecret{
537544
DockerRegistryCredentialOneOf: &v1alpha1.ImagesPullSecret_Credentials{
538545
Credentials: &corev1.DockerCredentials{
@@ -577,7 +584,7 @@ func getRepoTlsConfigAndAuth(
577584
tlsConfig = &corev1.PackageRepositoryTlsConfig{}
578585
}
579586

580-
if isAuthSecretKubeappsManaged(source.GetName(), caSecret) {
587+
if isAuthSecretKubeappsManaged(source, caSecret) {
581588
tlsConfig.PackageRepoTlsConfigOneOf = &corev1.PackageRepositoryTlsConfig_CertAuthority{
582589
CertAuthority: RedactedString,
583590
}
@@ -614,7 +621,7 @@ func getRepoTlsConfigAndAuth(
614621
}
615622

616623
// create data
617-
if isAuthSecretKubeappsManaged(source.GetName(), authSecret) {
624+
if isAuthSecretKubeappsManaged(source, authSecret) {
618625
switch auth.Type {
619626
case corev1.PackageRepositoryAuth_PACKAGE_REPOSITORY_AUTH_TYPE_BASIC_AUTH:
620627
auth.PackageRepoAuthOneOf = &corev1.PackageRepositoryAuth_UsernamePassword{
@@ -666,12 +673,30 @@ func getRepoTlsConfigAndAuth(
666673
return tlsConfig, auth, nil
667674
}
668675

669-
// note: for now, checking based on name pattern for backward compatibility
670-
func isAuthSecretKubeappsManaged(repoName string, secret *k8scorev1.Secret) bool {
671-
return secret.GetName() == helm.SecretNameForRepo(repoName)
676+
func isAuthSecretKubeappsManaged(repo *apprepov1alpha1.AppRepository, secret *k8scorev1.Secret) bool {
677+
if isSecretKubeappsManaged(repo, secret) {
678+
return true
679+
}
680+
681+
// note: until fully deprecated, we also check based on name pattern for backward compatibility
682+
return secret.GetName() == helm.SecretNameForRepo(repo.GetName())
672683
}
673684

674-
// note: for now, checking based on name pattern for backward compatibility
675-
func isImagesPullSecretKubeappsManaged(repoName string, secret *k8scorev1.Secret) bool {
676-
return secret.GetName() == imagesPullSecretName(repoName)
685+
func isImagesPullSecretKubeappsManaged(repo *apprepov1alpha1.AppRepository, secret *k8scorev1.Secret) bool {
686+
if isSecretKubeappsManaged(repo, secret) {
687+
return true
688+
}
689+
690+
// note: until fully deprecated, we also check based on name pattern for backward compatibility
691+
return secret.GetName() == imagesPullSecretName(repo.GetName())
692+
}
693+
694+
func isSecretKubeappsManaged(repo *apprepov1alpha1.AppRepository, secret *k8scorev1.Secret) bool {
695+
if !metav1.IsControlledBy(secret, repo) {
696+
return false
697+
}
698+
if managedby := secret.GetAnnotations()[Annotation_ManagedBy_Key]; managedby != Annotation_ManagedBy_Value {
699+
return false
700+
}
701+
return true
677702
}

0 commit comments

Comments
 (0)