diff --git a/api/v1alpha1/repository.go b/api/v1alpha1/repository.go index 6d774f86..329c8ba4 100644 --- a/api/v1alpha1/repository.go +++ b/api/v1alpha1/repository.go @@ -19,6 +19,7 @@ package v1alpha1 import ( "context" "fmt" + "net/http" "os" "path/filepath" "strings" @@ -34,6 +35,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/config" ) +type RepositoryType string + +const ( + RepositoryTypeOCI RepositoryType = "oci" + RepositoryTypeChartmuseum RepositoryType = "chartmuseum" + RepositoryUnknown RepositoryType = "unknown" +) + const ( Username = "username" Password = "password" @@ -218,3 +227,38 @@ func ParseRepoSecret(c client.Client, instance *Repository) (username, password, func (r *Repository) IsOCI() bool { return registry.IsOCI(r.Spec.URL) } + +func (r *Repository) GetRepoType(c client.Client) RepositoryType { + if r.IsOCI() { + return RepositoryTypeOCI + } + if r.IsChartmuseum(c) { + return RepositoryTypeChartmuseum + } + return RepositoryUnknown +} + +// IsChartmuseum determines whether the repository is to be treated as a chartmuseum +func (r *Repository) IsChartmuseum(c client.Client) bool { + // reference apis: https://github.com/helm/chartmuseum#chart-manipulation + req, err := http.NewRequest("POST", r.Spec.URL+"/api/charts", nil) + if err != nil { + return false + } + + // set auth info if needed + if r.Spec.AuthSecret != "" { + username, password, _, _, _, _ := ParseRepoSecret(c, r) + req.SetBasicAuth(username, password) + } + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil || resp == nil { + return false + } + defer resp.Body.Close() + + // when api exists and authorized, it is `chartmuseum` which can be used to push charts + return resp.StatusCode != http.StatusNotFound && resp.StatusCode != http.StatusUnauthorized +} diff --git a/config/samples/example-test.sh b/config/samples/example-test.sh index 540bb616..d69113b7 100755 --- a/config/samples/example-test.sh +++ b/config/samples/example-test.sh @@ -594,6 +594,11 @@ echo "\n" info "6.2.2 Add this private chartmuseum repository(basic auth enabled) to kubebb" kubectl apply -f config/samples/core_v1alpha1_repository_chartmuseum.yaml waitComponentStatus "kubebb-system" "repository-chartmuseum.nginx" "false" +repoType=$(kubectl get repo repository-chartmuseum -nkubebb-system -ojson | jq -r '.metadata.labels."kubebb.repository.type"') +if [[ ${repoType} != "chartmuseum" ]]; then + echo "get repotype failed" + exit 1 +fi info "6.2.3 Plan a nignx with private chartmuseum(basic auth enabled) " kubectl apply -f config/samples/core_v1alpha1_componentplan_mynginx.yaml waitComponentPlanDone "kubebb-system" "mynginx" diff --git a/controllers/repository_controller.go b/controllers/repository_controller.go index 795c2a21..dc205c42 100644 --- a/controllers/repository_controller.go +++ b/controllers/repository_controller.go @@ -141,10 +141,12 @@ func (r *RepositoryReconciler) checkInitial(ctx context.Context, logger logr.Log instanceDeepCopy.Labels = make(map[string]string) } - if v, ok := instanceDeepCopy.Labels[corev1alpha1.RepositoryTypeLabel]; !ok || v != instanceDeepCopy.Spec.RepositoryType { - instanceDeepCopy.Labels[corev1alpha1.RepositoryTypeLabel] = instanceDeepCopy.Spec.RepositoryType + currentType := string(instanceDeepCopy.GetRepoType(r.Client)) + if v := instanceDeepCopy.Labels[corev1alpha1.RepositoryTypeLabel]; v != currentType { + instanceDeepCopy.Labels[corev1alpha1.RepositoryTypeLabel] = currentType update = true } + if v, ok := instanceDeepCopy.Labels[corev1alpha1.RepositorySourceLabel]; !ok || (v != string(corev1alpha1.Official) && v != string(corev1alpha1.Unknown)) { instanceDeepCopy.Labels[corev1alpha1.RepositorySourceLabel] = string(corev1alpha1.Unknown) update = true