diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/cache/chart_cache.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/cache/chart_cache.go index f518ce018e9..c07e26d7be4 100644 --- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/cache/chart_cache.go +++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/cache/chart_cache.go @@ -580,7 +580,7 @@ func chartCacheKeyFor(namespace, chartID, chartVersion string) (string, error) { } var err error - if chartID, err = pkgutils.GetUnescapedChartID(chartID); err != nil { + if chartID, err = pkgutils.GetUnescapedPackageID(chartID); err != nil { return "", fmt.Errorf("invalid chart ID in chartCacheKeyFor: [%s]: %v", chartID, err) } diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/chart.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/chart.go index ed6adbe354a..91cb82be9f7 100644 --- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/chart.go +++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/chart.go @@ -40,7 +40,7 @@ func (s *Server) getChartInCluster(ctx context.Context, key types.NamespacedName func (s *Server) availableChartDetail(ctx context.Context, packageRef *corev1.AvailablePackageReference, chartVersion string) (*corev1.AvailablePackageDetail, error) { log.Infof("+availableChartDetail(%s, %s)", packageRef, chartVersion) - repoN, chartName, err := pkgutils.SplitChartIdentifier(packageRef.Identifier) + repoN, chartName, err := pkgutils.SplitPackageIdentifier(packageRef.Identifier) if err != nil { return nil, err } diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go index 510cdb1bb86..a534feaa808 100644 --- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go +++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/release.go @@ -321,7 +321,7 @@ func (s *Server) getReleaseViaHelmApi(ctx context.Context, key types.NamespacedN } func (s *Server) newRelease(ctx context.Context, packageRef *corev1.AvailablePackageReference, targetName types.NamespacedName, versionRef *corev1.VersionReference, reconcile *corev1.ReconciliationOptions, valuesString string) (*corev1.InstalledPackageReference, error) { - repoName, chartName, err := pkgutils.SplitChartIdentifier(packageRef.Identifier) + repoName, chartName, err := pkgutils.SplitPackageIdentifier(packageRef.Identifier) if err != nil { return nil, err } diff --git a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/server.go b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/server.go index 74272596bde..c497a65f047 100644 --- a/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/server.go +++ b/cmd/kubeapps-apis/plugins/fluxv2/packages/v1alpha1/server.go @@ -266,7 +266,7 @@ func (s *Server) GetAvailablePackageVersions(ctx context.Context, request *corev cluster) } - repoName, chartName, err := pkgutils.SplitChartIdentifier(packageRef.Identifier) + repoName, chartName, err := pkgutils.SplitPackageIdentifier(packageRef.Identifier) if err != nil { return nil, err } diff --git a/cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/server.go b/cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/server.go index 9ed10d64f45..cf44fe05d32 100644 --- a/cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/server.go +++ b/cmd/kubeapps-apis/plugins/helm/packages/v1alpha1/server.go @@ -305,7 +305,7 @@ func (s *Server) GetAvailablePackageDetail(ctx context.Context, request *corev1. return nil, err } - unescapedChartID, err := pkgutils.GetUnescapedChartID(request.AvailablePackageRef.Identifier) + unescapedChartID, err := pkgutils.GetUnescapedPackageID(request.AvailablePackageRef.Identifier) if err != nil { return nil, err } @@ -371,7 +371,7 @@ func (s *Server) GetAvailablePackageVersions(ctx context.Context, request *corev return nil, err } - unescapedChartID, err := pkgutils.GetUnescapedChartID(request.GetAvailablePackageRef().GetIdentifier()) + unescapedChartID, err := pkgutils.GetUnescapedPackageID(request.GetAvailablePackageRef().GetIdentifier()) if err != nil { return nil, err } @@ -697,7 +697,7 @@ func (s *Server) CreateInstalledPackage(ctx context.Context, request *corev1.Cre } chartID := request.GetAvailablePackageRef().GetIdentifier() repoNamespace := request.GetAvailablePackageRef().GetContext().GetNamespace() - repoName, chartName, err := pkgutils.SplitChartIdentifier(chartID) + repoName, chartName, err := pkgutils.SplitPackageIdentifier(chartID) if err != nil { return nil, err } @@ -769,7 +769,7 @@ func (s *Server) UpdateInstalledPackage(ctx context.Context, request *corev1.Upd return nil, status.Errorf(codes.Internal, "Unable to create kubernetes clientset: %v", err) } chartID := availablePkgRef.GetIdentifier() - repoName, chartName, err := pkgutils.SplitChartIdentifier(chartID) + repoName, chartName, err := pkgutils.SplitPackageIdentifier(chartID) if err != nil { return nil, err } diff --git a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_ctrl_packages.go b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_ctrl_packages.go index 7b4eb7b315e..c446212ff05 100644 --- a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_ctrl_packages.go +++ b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_ctrl_packages.go @@ -100,7 +100,7 @@ func (s *Server) GetAvailablePackageSummaries(ctx context.Context, request *core if currentPkg.Spec.RefName > pkgMetadata.Name { return nil, status.Errorf(codes.Internal, fmt.Sprintf("unexpected order for kapp-controller packages, expected %q, found %q", pkgMetadata.Name, currentPkg.Spec.RefName)) } - log.Errorf("Package %q did not have a corresponding metadata", currentPkg.Spec.RefName) + log.Errorf("Package %q did not have a corresponding metadata (want %q)", currentPkg.Spec.RefName, pkgMetadata.Name) currentPkg = <-getPkgsChannel } // Collect the packages for a particular refName to be able to send the @@ -165,8 +165,13 @@ func (s *Server) GetAvailablePackageVersions(ctx context.Context, request *corev cluster = s.globalPackagingCluster } + _, pkgName, err := pkgutils.SplitPackageIdentifier(identifier) + if err != nil { + return nil, err + } + // Use the field selector to return only Package CRs that match on the spec.refName. - fieldSelector := fmt.Sprintf("spec.refName=%s", identifier) + fieldSelector := fmt.Sprintf("spec.refName=%s", pkgName) pkgs, err := s.getPkgsWithFieldSelector(ctx, cluster, namespace, fieldSelector) if err != nil { return nil, statuserror.FromK8sError("get", "Package", "", err) @@ -179,8 +184,8 @@ func (s *Server) GetAvailablePackageVersions(ctx context.Context, request *corev // TODO(minelson): support configurable version summary for kapp-controller pkgs // as already done for Helm (see #3588 for more info). - versions := make([]*corev1.PackageAppVersion, len(pkgVersionsMap[identifier])) - for i, v := range pkgVersionsMap[identifier] { + versions := make([]*corev1.PackageAppVersion, len(pkgVersionsMap[pkgName])) + for i, v := range pkgVersionsMap[pkgName] { // Currently, PkgVersion and AppVersion are the same // https://kubernetes.slack.com/archives/CH8KCCKA5/p1636386358322000?thread_ts=1636371493.320900&cid=CH8KCCKA5 versions[i] = &corev1.PackageAppVersion{ @@ -215,17 +220,22 @@ func (s *Server) GetAvailablePackageDetail(ctx context.Context, request *corev1. cluster = s.globalPackagingCluster } + _, pkgName, err := pkgutils.SplitPackageIdentifier(identifier) + if err != nil { + return nil, err + } + // fetch the package metadata - pkgMetadata, err := s.getPkgMetadata(ctx, cluster, namespace, identifier) + pkgMetadata, err := s.getPkgMetadata(ctx, cluster, namespace, pkgName) if err != nil { - return nil, statuserror.FromK8sError("get", "PackageMetadata", identifier, err) + return nil, statuserror.FromK8sError("get", "PackageMetadata", pkgName, err) } // Use the field selector to return only Package CRs that match on the spec.refName. - fieldSelector := fmt.Sprintf("spec.refName=%s", identifier) + fieldSelector := fmt.Sprintf("spec.refName=%s", pkgName) pkgs, err := s.getPkgsWithFieldSelector(ctx, cluster, namespace, fieldSelector) if err != nil { - return nil, statuserror.FromK8sError("get", "Package", identifier, err) + return nil, statuserror.FromK8sError("get", "Package", pkgName, err) } pkgVersionsMap, err := getPkgVersionsMap(pkgs) if err != nil { @@ -235,22 +245,22 @@ func (s *Server) GetAvailablePackageDetail(ctx context.Context, request *corev1. var foundPkgSemver = &pkgSemver{} if requestedPkgVersion != "" { // Ensure the version is available. - for _, v := range pkgVersionsMap[identifier] { + for _, v := range pkgVersionsMap[pkgName] { if v.version.String() == requestedPkgVersion { foundPkgSemver = &v break } } if foundPkgSemver.version == nil { - return nil, status.Errorf(codes.NotFound, fmt.Sprintf("unable to find %q package with version %q", identifier, requestedPkgVersion)) + return nil, status.Errorf(codes.NotFound, fmt.Sprintf("unable to find %q package with version %q", pkgName, requestedPkgVersion)) } } else { // If the pkgVersion wasn't specified, grab the packages to find the latest. - if len(pkgVersionsMap[identifier]) > 0 { - foundPkgSemver = &pkgVersionsMap[identifier][0] + if len(pkgVersionsMap[pkgName]) > 0 { + foundPkgSemver = &pkgVersionsMap[pkgName][0] requestedPkgVersion = foundPkgSemver.version.String() } else { - return nil, status.Errorf(codes.NotFound, fmt.Sprintf("unable to find any versions for the package %q", identifier)) + return nil, status.Errorf(codes.NotFound, fmt.Sprintf("unable to find any versions for the package %q", pkgName)) } } @@ -551,13 +561,18 @@ func (s *Server) CreateInstalledPackage(ctx context.Context, request *corev1.Cre } // Retrieve additional parameters from the request - packageRef := request.GetAvailablePackageRef() + identifier := request.GetAvailablePackageRef().GetIdentifier() packageCluster := request.GetAvailablePackageRef().GetContext().GetCluster() packageNamespace := request.GetAvailablePackageRef().GetContext().GetNamespace() reconciliationOptions := request.GetReconciliationOptions() pkgVersion := request.GetPkgVersionReference().GetVersion() values := request.GetValues() + _, pkgName, err := pkgutils.SplitPackageIdentifier(identifier) + if err != nil { + return nil, err + } + if targetCluster == "" { targetCluster = s.globalPackagingCluster } @@ -572,9 +587,9 @@ func (s *Server) CreateInstalledPackage(ctx context.Context, request *corev1.Cre } // fetch the package metadata - pkgMetadata, err := s.getPkgMetadata(ctx, packageCluster, packageNamespace, packageRef.Identifier) + pkgMetadata, err := s.getPkgMetadata(ctx, packageCluster, packageNamespace, pkgName) if err != nil { - return nil, statuserror.FromK8sError("get", "PackageMetadata", packageRef.Identifier, err) + return nil, statuserror.FromK8sError("get", "PackageMetadata", pkgName, err) } // build a new secret object with the values diff --git a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_data_adapters.go b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_data_adapters.go index d74407c59e3..3d69c6f0772 100644 --- a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_data_adapters.go +++ b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_data_adapters.go @@ -38,6 +38,9 @@ func (s *Server) buildAvailablePackageSummary(pkgMetadata *datapackagingv1alpha1 iconStringBuilder.WriteString(pkgMetadata.Spec.IconSVGBase64) } + // build package identifier based on the metadata + identifier := buildPackageIdentifier(pkgMetadata) + availablePackageSummary := &corev1.AvailablePackageSummary{ AvailablePackageRef: &corev1.AvailablePackageReference{ Context: &corev1.Context{ @@ -45,7 +48,7 @@ func (s *Server) buildAvailablePackageSummary(pkgMetadata *datapackagingv1alpha1 Namespace: pkgMetadata.Namespace, }, Plugin: &pluginDetail, - Identifier: pkgMetadata.Name, + Identifier: identifier, }, Name: pkgMetadata.Name, // Currently, PkgVersion and AppVersion are the same @@ -85,6 +88,9 @@ func (s *Server) buildAvailablePackageDetail(pkgMetadata *datapackagingv1alpha1. }) } + // build package identifier based on the metadata + identifier := buildPackageIdentifier(pkgMetadata) + // build readme readme := buildReadme(pkgMetadata, foundPkgSemver) @@ -102,7 +108,7 @@ func (s *Server) buildAvailablePackageDetail(pkgMetadata *datapackagingv1alpha1. Namespace: pkgMetadata.Namespace, }, Plugin: &pluginDetail, - Identifier: pkgMetadata.Name, + Identifier: identifier, }, Name: pkgMetadata.Name, IconUrl: iconStringBuilder.String(), @@ -226,6 +232,9 @@ func (s *Server) buildInstalledPackageDetail(pkgInstall *packagingv1alpha1.Packa return nil, fmt.Errorf("Cannot get the latest matching version for the pkg %q: %s", pkgMetadata.Name, err.Error()) } + // build package availablePackageIdentifier based on the metadata + availablePackageIdentifier := buildPackageIdentifier(pkgMetadata) + installedPackageDetail := &corev1.InstalledPackageDetail{ InstalledPackageRef: &corev1.InstalledPackageReference{ Context: &corev1.Context{ @@ -256,8 +265,8 @@ func (s *Server) buildInstalledPackageDetail(pkgInstall *packagingv1alpha1.Packa Namespace: pkgMetadata.Namespace, Cluster: cluster, }, - Identifier: pkgInstall.Spec.PackageRef.RefName, Plugin: &pluginDetail, + Identifier: availablePackageIdentifier, }, // Currently, PkgVersion and AppVersion are the same // https://kubernetes.slack.com/archives/CH8KCCKA5/p1636386358322000?thread_ts=1636371493.320900&cid=CH8KCCKA5 diff --git a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_test.go b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_test.go index 0d9aac6493b..1c49e321800 100644 --- a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_test.go +++ b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_test.go @@ -300,7 +300,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -316,7 +316,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tombi.foo.example.com", + Identifier: "unknown/tombi.foo.example.com", }, Name: "tombi.foo.example.com", DisplayName: "Tombi!", @@ -435,7 +435,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -451,7 +451,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tombi.foo.example.com", + Identifier: "unknown/tombi.foo.example.com", }, Name: "tombi.foo.example.com", DisplayName: "Tombi!", @@ -512,7 +512,71 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", + }, + Name: "tetris.foo.example.com", + DisplayName: "Classic Tetris", + LatestVersion: &corev1.PackageAppVersion{ + PkgVersion: "1.2.3", + AppVersion: "1.2.3", + }, + IconUrl: "data:image/svg+xml;base64,Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + Categories: []string{"logging", "daemon-set"}, + }, + }, + }, + { + name: "it returns carvel package summaries with repo-based identifiers", + existingObjects: []k8sruntime.Object{ + &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + Annotations: map[string]string{ + REPO_REF_ANNOTATION: "default/tce-repo", + }, + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, + &datapackagingv1alpha1.Package{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com.1.2.3", + }, + Spec: datapackagingv1alpha1.PackageSpec{ + RefName: "tetris.foo.example.com", + Version: "1.2.3", + Licenses: []string{"my-license"}, + ReleaseNotes: "release notes", + CapactiyRequirementsDescription: "capacity description", + ReleasedAt: metav1.Time{time.Date(1984, time.June, 6, 0, 0, 0, 0, time.UTC)}, + }, + }, + }, + expectedPackages: []*corev1.AvailablePackageSummary{ + { + AvailablePackageRef: &corev1.AvailablePackageReference{ + Context: defaultContext, + Plugin: &pluginDetail, + Identifier: "tce-repo/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -609,7 +673,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -750,7 +814,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tombi.foo.example.com", + Identifier: "unknown/tombi.foo.example.com", }, Name: "tombi.foo.example.com", DisplayName: "Tombi!", @@ -766,7 +830,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tunotherone.foo.example.com", + Identifier: "unknown/tunotherone.foo.example.com", }, Name: "tunotherone.foo.example.com", DisplayName: "Tunotherone!", @@ -869,7 +933,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -971,7 +1035,7 @@ func TestGetAvailablePackageSummaries(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, Name: "tetris.foo.example.com", DisplayName: "Classic Tetris", @@ -1049,7 +1113,7 @@ func TestGetAvailablePackageVersions(t *testing.T) { request: &corev1.GetAvailablePackageVersionsRequest{ AvailablePackageRef: &corev1.AvailablePackageReference{ Context: &corev1.Context{}, - Identifier: "package-one", + Identifier: "unknown/package-one", }, }, expectedStatusCode: codes.InvalidArgument, @@ -1128,7 +1192,7 @@ func TestGetAvailablePackageVersions(t *testing.T) { Context: &corev1.Context{ Namespace: "default", }, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, }, expectedStatusCode: codes.OK, @@ -1204,7 +1268,7 @@ func TestGetAvailablePackageDetail(t *testing.T) { request: &corev1.GetAvailablePackageDetailRequest{ AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, }, existingObjects: []k8sruntime.Object{ @@ -1284,7 +1348,101 @@ Some support information `, AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", + Plugin: &pluginDetail, + }, + }, + statusCode: codes.OK, + }, + { + name: "it returns an availablePackageDetail of the latest version with repo-based identifiers", + request: &corev1.GetAvailablePackageDetailRequest{ + AvailablePackageRef: &corev1.AvailablePackageReference{ + Context: defaultContext, + Identifier: "unknown/tetris.foo.example.com", + }, + }, + existingObjects: []k8sruntime.Object{ + &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + Annotations: map[string]string{ + REPO_REF_ANNOTATION: "default/tce-repo", + }, + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, + &datapackagingv1alpha1.Package{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com.1.2.3", + }, + Spec: datapackagingv1alpha1.PackageSpec{ + RefName: "tetris.foo.example.com", + Version: "1.2.3", + Licenses: []string{"my-license"}, + ReleaseNotes: "release notes", + CapactiyRequirementsDescription: "capacity description", + ReleasedAt: metav1.Time{time.Date(1984, time.June, 6, 0, 0, 0, 0, time.UTC)}, + }, + }, + }, + expectedPackage: &corev1.AvailablePackageDetail{ + Name: "tetris.foo.example.com", + DisplayName: "Classic Tetris", + LongDescription: "A few sentences but not really a readme", + Version: &corev1.PackageAppVersion{ + PkgVersion: "1.2.3", + AppVersion: "1.2.3", + }, + Maintainers: []*corev1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + IconUrl: "data:image/svg+xml;base64,Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + Categories: []string{"logging", "daemon-set"}, + Readme: `## Description + +A few sentences but not really a readme + +## Capactiy requirements + +capacity description + +## Release notes + +release notes + +Released at: June, 6 1984 + +## Support + +Some support information + +## Licenses + +- my-license + +`, + AvailablePackageRef: &corev1.AvailablePackageReference{ + Context: defaultContext, + Identifier: "tce-repo/tetris.foo.example.com", Plugin: &pluginDetail, }, }, @@ -1295,7 +1453,7 @@ Some support information request: &corev1.GetAvailablePackageDetailRequest{ AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, }, existingObjects: []k8sruntime.Object{ @@ -1375,7 +1533,7 @@ Some support information `, AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", Plugin: &pluginDetail, }, }, @@ -1385,7 +1543,7 @@ Some support information name: "it returns an invalid arg error status if no context is provided", request: &corev1.GetAvailablePackageDetailRequest{ AvailablePackageRef: &corev1.AvailablePackageReference{ - Identifier: "foo/bar", + Identifier: "unknown/foo/bar", }, }, statusCode: codes.InvalidArgument, @@ -1395,7 +1553,7 @@ Some support information request: &corev1.GetAvailablePackageDetailRequest{ AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersion: "1.2.4", }, @@ -2725,7 +2883,243 @@ func TestGetInstalledPackageDetail(t *testing.T) { AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", + }, + InstalledPackageRef: &corev1.InstalledPackageReference{ + Context: defaultContext, + Plugin: &pluginDetail, + Identifier: "my-installation", + }, + Name: "my-installation", + PkgVersionReference: &corev1.VersionReference{ + Version: "1.2.3", + }, + CurrentVersion: &corev1.PackageAppVersion{ + PkgVersion: "1.2.3", + AppVersion: "1.2.3", + }, + ValuesApplied: "\n# values.yaml\nfoo: bar\n", + ReconciliationOptions: &corev1.ReconciliationOptions{ + ServiceAccountName: "default", + Interval: 30, + Suspend: false, + }, + Status: &corev1.InstalledPackageStatus{ + Ready: true, + Reason: corev1.InstalledPackageStatus_STATUS_REASON_INSTALLED, + UserReason: "Deployed", + }, + PostInstallationNotes: strings.ReplaceAll(`#### Deploy + + +deployStdout + + +#### Fetch + + +fetchStdout + + +### Errors + +#### Deploy + + +deployStderr + + +#### Fetch + + +fetchStderr + + +`, "", "`"), + LatestMatchingVersion: &corev1.PackageAppVersion{ + PkgVersion: "1.2.7", + AppVersion: "1.2.7", + }, + LatestVersion: &corev1.PackageAppVersion{ + PkgVersion: "2.0.0", + AppVersion: "2.0.0", + }, + }, + }, + { + name: "it returns carvel installed package detail with the latest matching version and repo-based identifiers", + request: &corev1.GetInstalledPackageDetailRequest{ + InstalledPackageRef: &corev1.InstalledPackageReference{ + Context: defaultContext, + Identifier: "my-installation", + }, + }, + existingObjects: []k8sruntime.Object{ + &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + Annotations: map[string]string{ + REPO_REF_ANNOTATION: "default/tce-repo", + }, + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, + &datapackagingv1alpha1.Package{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com.1.2.3", + }, + Spec: datapackagingv1alpha1.PackageSpec{ + RefName: "tetris.foo.example.com", + Version: "1.2.3", + Licenses: []string{"my-license"}, + ReleaseNotes: "release notes", + CapactiyRequirementsDescription: "capacity description", + ReleasedAt: metav1.Time{time.Date(1984, time.June, 6, 0, 0, 0, 0, time.UTC)}, + }, + }, + &datapackagingv1alpha1.Package{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com.1.2.7", + }, + Spec: datapackagingv1alpha1.PackageSpec{ + RefName: "tetris.foo.example.com", + Version: "1.2.7", + Licenses: []string{"my-license"}, + ReleaseNotes: "release notes", + CapactiyRequirementsDescription: "capacity description", + }, + }, + &datapackagingv1alpha1.Package{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com.2.0.0", + }, + Spec: datapackagingv1alpha1.PackageSpec{ + RefName: "tetris.foo.example.com", + Version: "2.0.0", + Licenses: []string{"my-license"}, + ReleaseNotes: "release notes", + CapactiyRequirementsDescription: "capacity description", + }, + }, + &packagingv1alpha1.PackageInstall{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgInstallResource, + APIVersion: packagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "my-installation", + }, + Spec: packagingv1alpha1.PackageInstallSpec{ + ServiceAccountName: "default", + PackageRef: &packagingv1alpha1.PackageRef{ + RefName: "tetris.foo.example.com", + VersionSelection: &vendirversions.VersionSelectionSemver{ + Constraints: ">1.0.0 <2.0.0", + }, + }, + Values: []packagingv1alpha1.PackageInstallValues{{ + SecretRef: &packagingv1alpha1.PackageInstallValuesSecretRef{ + Name: "my-installation-default-values", + }, + }, + }, + Paused: false, + Canceled: false, + SyncPeriod: &metav1.Duration{(time.Second * 30)}, + NoopDelete: false, + }, + Status: packagingv1alpha1.PackageInstallStatus{ + GenericStatus: kappctrlv1alpha1.GenericStatus{ + ObservedGeneration: 1, + Conditions: []kappctrlv1alpha1.Condition{{ + Type: kappctrlv1alpha1.ReconcileSucceeded, + Status: k8scorev1.ConditionTrue, + Reason: "baz", + Message: "qux", + }}, + FriendlyDescription: "foo", + UsefulErrorMessage: "Deployed", + }, + Version: "1.2.3", + LastAttemptedVersion: "1.2.3", + }, + }, + &kappctrlv1alpha1.App{ + TypeMeta: metav1.TypeMeta{ + Kind: appResource, + APIVersion: kappctrlAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "my-installation", + }, + Spec: kappctrlv1alpha1.AppSpec{ + SyncPeriod: &metav1.Duration{(time.Second * 30)}, + }, + Status: kappctrlv1alpha1.AppStatus{ + Deploy: &kappctrlv1alpha1.AppStatusDeploy{ + Stdout: "deployStdout", + Stderr: "deployStderr", + }, + Fetch: &kappctrlv1alpha1.AppStatusFetch{ + Stdout: "fetchStdout", + Stderr: "fetchStderr", + }, + Inspect: &kappctrlv1alpha1.AppStatusInspect{ + Stdout: "inspectStdout", + Stderr: "inspectStderr", + }, + }, + }, + }, + existingTypedObjects: []k8sruntime.Object{ + &k8scorev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "my-installation-default-values", + }, + Type: "Opaque", + Data: map[string][]byte{ + "values.yaml": []byte("foo: bar"), + }, + }, + }, + statusCode: codes.OK, + expectedPackage: &corev1.InstalledPackageDetail{ + AvailablePackageRef: &corev1.AvailablePackageReference{ + Context: defaultContext, + Plugin: &pluginDetail, + Identifier: "tce-repo/tetris.foo.example.com", }, InstalledPackageRef: &corev1.InstalledPackageReference{ Context: defaultContext, @@ -2923,7 +3317,7 @@ fetchStderr AvailablePackageRef: &corev1.AvailablePackageReference{ Context: defaultContext, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, InstalledPackageRef: &corev1.InstalledPackageReference{ Context: defaultContext, @@ -3042,7 +3436,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.2.3", @@ -3196,7 +3590,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.2.3", @@ -3282,7 +3676,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.2.3", @@ -3437,7 +3831,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.2.3", @@ -3593,7 +3987,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -3752,7 +4146,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0-rc1", @@ -3864,7 +4258,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4023,7 +4417,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4182,7 +4576,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4336,7 +4730,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4494,7 +4888,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4652,7 +5046,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", @@ -4810,7 +5204,7 @@ func TestCreateInstalledPackage(t *testing.T) { Cluster: "default", }, Plugin: &pluginDetail, - Identifier: "tetris.foo.example.com", + Identifier: "unknown/tetris.foo.example.com", }, PkgVersionReference: &corev1.VersionReference{ Version: "1.0.0", diff --git a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils.go b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils.go index d5b874365d0..b54a92dde90 100644 --- a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils.go +++ b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils.go @@ -19,6 +19,9 @@ import ( "k8s.io/client-go/rest" ) +const REPO_REF_ANNOTATION = "packaging.carvel.dev/package-repository-ref" +const DEFAULT_REPO_NAME = "unknown" + type pkgSemver struct { pkg *datapackagingv1alpha1.Package version *semver.Version @@ -127,6 +130,24 @@ func buildReadme(pkgMetadata *datapackagingv1alpha1.PackageMetadata, foundPkgSem return readmeSB.String() } +// buildPackageIdentifier generates the package identifier (repoName/pkgName) for a given package +func buildPackageIdentifier(pkgMetadata *datapackagingv1alpha1.PackageMetadata) string { + // default repo name if using kapp controller < v0.36.1 + repoName := DEFAULT_REPO_NAME + + // See https://github.com/vmware-tanzu/carvel-kapp-controller/pull/532 + if repoRefAnnotation := pkgMetadata.Annotations[REPO_REF_ANNOTATION]; repoRefAnnotation != "" { + // this annotation returns "namespace/reponame", for instance "default/tce-repo", + // but we just want the "reponame" part + splitRepoRefAnnotation := strings.Split(repoRefAnnotation, "/") + // just change the repo name if we have a valid annotation + if len(splitRepoRefAnnotation) == 2 { + repoName = strings.Split(repoRefAnnotation, "/")[1] + } + } + return fmt.Sprintf("%s/%s", repoName, pkgMetadata.Name) +} + // buildPostInstallationNotes generates the installation notes based on the application status func buildPostInstallationNotes(app *kappctrlv1alpha1.App) string { var postInstallNotesSB strings.Builder diff --git a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils_test.go b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils_test.go index 9df58f6e819..85239421503 100644 --- a/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils_test.go +++ b/cmd/kubeapps-apis/plugins/kapp_controller/packages/v1alpha1/server_utils_test.go @@ -526,6 +526,92 @@ Some support information } } +func TestBuildPackageIdentifier(t *testing.T) { + tests := []struct { + name string + pkgMetadata *datapackagingv1alpha1.PackageMetadata + expected string + }{ + {"empty", &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, "unknown/tetris.foo.example.com", + }, + {"a valid annotation", &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + Annotations: map[string]string{ + REPO_REF_ANNOTATION: "default/tce-repo", + }, + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, "tce-repo/tetris.foo.example.com", + }, + {"an invalid annotation", &datapackagingv1alpha1.PackageMetadata{ + TypeMeta: metav1.TypeMeta{ + Kind: pkgMetadataResource, + APIVersion: datapackagingAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "tetris.foo.example.com", + Annotations: map[string]string{ + REPO_REF_ANNOTATION: "default/foo/tce-repo", + }, + }, + Spec: datapackagingv1alpha1.PackageMetadataSpec{ + DisplayName: "Classic Tetris", + IconSVGBase64: "Tm90IHJlYWxseSBTVkcK", + ShortDescription: "A great game for arcade gamers", + LongDescription: "A few sentences but not really a readme", + Categories: []string{"logging", "daemon-set"}, + Maintainers: []datapackagingv1alpha1.Maintainer{{Name: "person1"}, {Name: "person2"}}, + SupportDescription: "Some support information", + ProviderName: "Tetris inc.", + }, + }, "unknown/tetris.foo.example.com", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + packageIdentifier := buildPackageIdentifier(tt.pkgMetadata) + if want, got := tt.expected, packageIdentifier; !cmp.Equal(want, got) { + t.Errorf("in %s: mismatch (-want +got):\n%s", tt.name, cmp.Diff(want, got)) + } + }) + } +} + func TestPrereleasesVersionSelection(t *testing.T) { tests := []struct { name string diff --git a/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils.go b/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils.go index 128ce8d82ad..77e63ae84b0 100644 --- a/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils.go +++ b/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils.go @@ -182,29 +182,29 @@ func AvailablePackageSummaryFromChart(chart *models.Chart, plugin *plugins.Plugi // https://github.com/vmware-tanzu/kubeapps/pull/4094#discussion_r790349962. // Will come back to this -// GetUnescapedChartID takes a chart id with URI-encoded characters and decode them. Ex: 'foo%2Fbar' becomes 'foo/bar' -// also checks that the chart ID is in the expected format, namely "repoName/chartName" -func GetUnescapedChartID(chartID string) (string, error) { - unescapedChartID, err := url.QueryUnescape(chartID) +// GetUnescapedPackageID takes a package id with URI-encoded characters and decode them. Ex: 'foo%2Fbar' becomes 'foo/bar' +// also checks that the package ID is in the expected format, namely "repoName/packageName" +func GetUnescapedPackageID(packageID string) (string, error) { + unescapedPackageID, err := url.QueryUnescape(packageID) if err != nil { - return "", status.Errorf(codes.InvalidArgument, "Unable to decode chart ID chart: %v", chartID) + return "", status.Errorf(codes.InvalidArgument, "Unable to decode package ID: %v", packageID) } // TODO(agamez): support ID with multiple slashes, eg: aaa/bbb/ccc - chartIDParts := strings.Split(unescapedChartID, "/") - if len(chartIDParts) != 2 { - return "", status.Errorf(codes.InvalidArgument, "Incorrect package ref dentifier, currently just 'foo/bar' patterns are supported: %s", chartID) + packageIDParts := strings.Split(unescapedPackageID, "/") + if len(packageIDParts) != 2 { + return "", status.Errorf(codes.InvalidArgument, "Incorrect package ref dentifier, currently just 'foo/bar' patterns are supported: %s", packageID) } - return unescapedChartID, nil + return unescapedPackageID, nil } -func SplitChartIdentifier(chartID string) (repoName, chartName string, err error) { - // getUnescapedChartID also ensures that there are two parts (ie. repo/chart-name only) - unescapedChartID, err := GetUnescapedChartID(chartID) +func SplitPackageIdentifier(packageID string) (repoName, packageName string, err error) { + // GetUnescapedPackageID also ensures that there are two parts (ie. repo/package-name only) + unescapedPackageID, err := GetUnescapedPackageID(packageID) if err != nil { return "", "", err } - chartIDParts := strings.Split(unescapedChartID, "/") - return chartIDParts[0], chartIDParts[1], nil + packageIDParts := strings.Split(unescapedPackageID, "/") + return packageIDParts[0], packageIDParts[1], nil } // DefaultValuesFromSchema returns a yaml string with default values generated from an OpenAPI v3 Schema diff --git a/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils_test.go b/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils_test.go index 46b4b755b13..0c841050eb8 100644 --- a/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils_test.go +++ b/cmd/kubeapps-apis/plugins/pkg/pkgutils/pkgutils_test.go @@ -600,7 +600,7 @@ func TestAvailablePackageSummaryFromChart(t *testing.T) { } } -func TestGetUnescapedChartID(t *testing.T) { +func TestGetUnescapedPackageID(t *testing.T) { testCases := []struct { name string in string @@ -633,7 +633,7 @@ func TestGetUnescapedChartID(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - actualOut, err := GetUnescapedChartID(tc.in) + actualOut, err := GetUnescapedPackageID(tc.in) if got, want := status.Code(err), tc.statusCode; got != want { t.Fatalf("got: %+v, want: %+v, err: %+v", got, want, err) } @@ -647,7 +647,7 @@ func TestGetUnescapedChartID(t *testing.T) { } } -func TestSplitChartIdentifier(t *testing.T) { +func TestSplitPackageIdentifier(t *testing.T) { testCases := []struct { name string in string @@ -671,7 +671,7 @@ func TestSplitChartIdentifier(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - repoName, chartName, err := SplitChartIdentifier(tc.in) + repoName, chartName, err := SplitPackageIdentifier(tc.in) if got, want := status.Code(err), tc.statusCode; got != want { t.Fatalf("got: %+v, want: %+v, err: %+v", got, want, err) } diff --git a/dashboard/src/components/Catalog/PackageCatalogItem.tsx b/dashboard/src/components/Catalog/PackageCatalogItem.tsx index 8c3311881bf..156b1587eb2 100644 --- a/dashboard/src/components/Catalog/PackageCatalogItem.tsx +++ b/dashboard/src/components/Catalog/PackageCatalogItem.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import * as url from "shared/url"; -import { getPluginIcon, getPluginName, PluginNames, trimDescription } from "shared/utils"; +import { getPluginIcon, getPluginName, trimDescription } from "shared/utils"; import placeholder from "../../placeholder.png"; import InfoCard from "../InfoCard/InfoCard"; import { IPackageCatalogItem } from "./CatalogItem"; @@ -22,13 +22,10 @@ export default function PackageCatalogItem(props: IPackageCatalogItem) { const pkgPluginName = getPluginName(availablePackageSummary.availablePackageRef?.plugin); // Get the pkg repository for the plugins that have one. - switch (availablePackageSummary.availablePackageRef?.plugin?.name) { - case (PluginNames.PACKAGES_HELM, PluginNames.PACKAGES_FLUX): - pkgRepository = availablePackageSummary.availablePackageRef?.identifier.split("/")[0]; - break; - case PluginNames.PACKAGES_KAPP: - // TODO: get repo from kapp-controller - break; + // Assuming an identifier will always be like: "repo/pkgName" + const splitIdentifier = availablePackageSummary.availablePackageRef?.identifier.split("/"); + if (splitIdentifier && splitIdentifier?.length > 0) { + pkgRepository = splitIdentifier[0]; } return (