From 792eae132d9466f08b851815308fd444b7e0bccc Mon Sep 17 00:00:00 2001 From: Shivam Kumar Date: Thu, 25 Aug 2022 11:14:11 +0530 Subject: [PATCH] Adding mariner support in dapr init (#1029) * Adding image-variant flag in self-hosted mode Signed-off-by: shivam * Adding image-variant in kubernetes init Signed-off-by: shivam * Adding image-variant in dapr upgrade Signed-off-by: shivam * e2e test for standalone mariner init Signed-off-by: shivam * Incorporating comments Signed-off-by: shivam * Reducing code duplicacy Signed-off-by: shivam * Formatting change Signed-off-by: shivam * Adding e2e tests for kubernetes init Signed-off-by: shivam * e2e test for upgrade Signed-off-by: shivam * Fixing linter error Signed-off-by: shivam * fix linter errors Signed-off-by: shivam * Uncommenting upgrade tsts Signed-off-by: shivam Signed-off-by: shivam --- cmd/init.go | 8 +++- cmd/upgrade.go | 7 +++- pkg/kubernetes/kubernetes.go | 6 +++ pkg/kubernetes/upgrade.go | 6 +++ pkg/standalone/standalone.go | 24 ++++++++---- tests/e2e/common/common.go | 25 ++++++++++++ tests/e2e/kubernetes/kubernetes_test.go | 40 ++++++++++++++++++- tests/e2e/standalone/init_test.go | 20 ++++++++++ tests/e2e/upgrade/upgrade_test.go | 52 ++++++++++++++++--------- utils/utils.go | 16 ++++++++ 10 files changed, 175 insertions(+), 29 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index b5bfc6de..eabdd022 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -41,6 +41,7 @@ var ( values []string fromDir string containerRuntime string + imageVariant string ) var InitCmd = &cobra.Command{ @@ -76,6 +77,9 @@ dapr init -s # Initialize Dapr from a directory (installer-bundle installation) (Preview feature) dapr init --from-dir +# Initialize dapr with a particular image variant. Allowed values: "mariner" +dapr init --image-variant + # See more at: https://docs.dapr.io/getting-started/ `, Run: func(cmd *cobra.Command, args []string) { @@ -106,6 +110,7 @@ dapr init --from-dir Wait: wait, Timeout: timeout, ImageRegistryURI: imageRegistryURI, + ImageVariant: imageVariant, } err = kubernetes.Init(config) if err != nil { @@ -131,7 +136,7 @@ dapr init --from-dir if len(imageRegistryURI) != 0 { warnForPrivateRegFeat() } - err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime) + err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRegistryURI, fromDir, containerRuntime, imageVariant) if err != nil { print.FailureStatusEvent(os.Stderr, err.Error()) os.Exit(1) @@ -169,6 +174,7 @@ func init() { InitCmd.Flags().BoolVarP(&enableHA, "enable-ha", "", false, "Enable high availability (HA) mode") InitCmd.Flags().String("network", "", "The Docker network on which to deploy the Dapr runtime") InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "", "Use Dapr artifacts from local directory for self-hosted installation") + InitCmd.Flags().StringVarP(&imageVariant, "image-variant", "", "", "The image variant to use for the Dapr runtime, for example: mariner") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-registry", "", "Custom/Private docker image repository url") diff --git a/cmd/upgrade.go b/cmd/upgrade.go index e3a2590f..b58c6899 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -24,7 +24,10 @@ import ( "github.com/dapr/cli/pkg/print" ) -var upgradeRuntimeVersion string +var ( + upgradeRuntimeVersion string + upgradeImageVariant string +) var UpgradeCmd = &cobra.Command{ Use: "upgrade", @@ -58,6 +61,7 @@ dapr upgrade -k Args: values, Timeout: timeout, ImageRegistryURI: imageRegistryURI, + ImageVariant: upgradeImageVariant, }) if err != nil { print.FailureStatusEvent(os.Stderr, "Failed to upgrade Dapr: %s", err) @@ -77,6 +81,7 @@ func init() { UpgradeCmd.Flags().BoolP("help", "h", false, "Print this help message") UpgradeCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") UpgradeCmd.Flags().String("image-registry", "", "Custom/Private docker image repository URL") + UpgradeCmd.Flags().StringVarP(&upgradeImageVariant, "image-variant", "", "", "The image variant to use for the Dapr runtime, for example: mariner") UpgradeCmd.MarkFlagRequired("runtime-version") UpgradeCmd.MarkFlagRequired("kubernetes") diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index 09e0755b..88a2fbed 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -50,6 +50,7 @@ type InitConfiguration struct { Wait bool Timeout uint ImageRegistryURI string + ImageVariant string } // Init deploys the Dapr operator using the supplied runtime version. @@ -156,9 +157,14 @@ func daprChart(version string, config *helm.Configuration) (*chart.Chart, error) func chartValues(config InitConfiguration) (map[string]interface{}, error) { chartVals := map[string]interface{}{} + err := utils.ValidateImageVariant(config.ImageVariant) + if err != nil { + return nil, err + } globalVals := []string{ fmt.Sprintf("global.ha.enabled=%t", config.EnableHA), fmt.Sprintf("global.mtls.enabled=%t", config.EnableMTLS), + fmt.Sprintf("global.tag=%s", utils.GetVariantVersion(config.Version, config.ImageVariant)), } if len(config.ImageRegistryURI) != 0 { globalVals = append(globalVals, fmt.Sprintf("global.registry=%s", config.ImageRegistryURI)) diff --git a/pkg/kubernetes/upgrade.go b/pkg/kubernetes/upgrade.go index f50b7782..c46e2cb0 100644 --- a/pkg/kubernetes/upgrade.go +++ b/pkg/kubernetes/upgrade.go @@ -49,6 +49,7 @@ type UpgradeConfig struct { Args []string Timeout uint ImageRegistryURI string + ImageVariant string } func Upgrade(conf UpgradeConfig) error { @@ -158,6 +159,11 @@ func applyCRDs(version string) error { func upgradeChartValues(ca, issuerCert, issuerKey string, haMode, mtls bool, conf UpgradeConfig) (map[string]interface{}, error) { chartVals := map[string]interface{}{} globalVals := conf.Args + err := utils.ValidateImageVariant(conf.ImageVariant) + if err != nil { + return nil, err + } + globalVals = append(globalVals, fmt.Sprintf("global.tag=%s", utils.GetVariantVersion(conf.RuntimeVersion, conf.ImageVariant))) if mtls && ca != "" && issuerCert != "" && issuerKey != "" { globalVals = append(globalVals, fmt.Sprintf("dapr_sentry.tls.root.certPEM=%s", ca), diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 4815c896..ff426fe3 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -124,6 +124,7 @@ type initInfo struct { dockerNetwork string imageRegistryURL string containerRuntime string + imageVariant string } type daprImageInfo struct { @@ -146,7 +147,7 @@ func isBinaryInstallationRequired(binaryFilePrefix, installDir string) (bool, er } // Init installs Dapr on a local machine using the supplied runtimeVersion. -func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string) error { +func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRegistryURL string, fromDir string, containerRuntime string, imageVariant string) error { var err error var bundleDet bundleDetails containerRuntime = strings.TrimSpace(containerRuntime) @@ -258,6 +259,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod dockerNetwork: dockerNetwork, imageRegistryURL: imageRegistryURL, containerRuntime: containerRuntime, + imageVariant: imageVariant, } for _, step := range initSteps { // Run init on the configurations and containers. @@ -1175,22 +1177,30 @@ func getPlacementImageName(imageInfo daprImageInfo, info initInfo) (string, erro return "", err } - image = getPlacementImageWithTag(image, info.runtimeVersion) + image, err = getPlacementImageWithTag(image, info.runtimeVersion, info.imageVariant) + if err != nil { + return "", err + } // if default registry is GHCR and the image is not available in or cannot be pulled from GHCR // fallback to using dockerhub. if useGHCR(imageInfo, info.fromDir) && !tryPullImage(image, info.containerRuntime) { print.InfoStatusEvent(os.Stdout, "Placement image not found in Github container registry, pulling it from Docker Hub") - image = getPlacementImageWithTag(daprDockerImageName, info.runtimeVersion) + image, err = getPlacementImageWithTag(daprDockerImageName, info.runtimeVersion, info.imageVariant) + if err != nil { + return "", err + } } return image, nil } -func getPlacementImageWithTag(name, version string) string { - if version == latestVersion { - return name +func getPlacementImageWithTag(name, version, imageVariant string) (string, error) { + err := utils.ValidateImageVariant(imageVariant) + if err != nil { + return "", err } - return fmt.Sprintf("%s:%s", name, version) + version = utils.GetVariantVersion(version, imageVariant) + return fmt.Sprintf("%s:%s", name, version), nil } // useGHCR returns true iff default registry is set as GHCR and --image-registry and --from-dir flags are not set. diff --git a/tests/e2e/common/common.go b/tests/e2e/common/common.go index 1f29c470..7b7728cc 100644 --- a/tests/e2e/common/common.go +++ b/tests/e2e/common/common.go @@ -52,6 +52,7 @@ const ( type VersionDetails struct { RuntimeVersion string DashboardVersion string + ImageVariant string CustomResourceDefs []string ClusterRoles []string ClusterRoleBindings []string @@ -96,6 +97,11 @@ func UpgradeTest(details VersionDetails, opts TestOptions) func(t *testing.T) { "--runtime-version", details.RuntimeVersion, "--log-as-json", } + + if details.ImageVariant != "" { + args = append(args, "--image-variant", details.ImageVariant) + } + output, err := spawn.Command(daprPath, args...) t.Log(output) require.NoError(t, err, "upgrade failed") @@ -277,6 +283,14 @@ func StatusTestOnInstallUpgrade(details VersionDetails, opts TestOptions) func(t "dapr-operator": {details.RuntimeVersion, "3"}, } } + + if details.ImageVariant != "" { + notFound["dapr-sentry"][0] = notFound["dapr-sentry"][0] + "-" + details.ImageVariant + notFound["dapr-sidecar-injector"][0] = notFound["dapr-sidecar-injector"][0] + "-" + details.ImageVariant + notFound["dapr-placement-server"][0] = notFound["dapr-placement-server"][0] + "-" + details.ImageVariant + notFound["dapr-operator"][0] = notFound["dapr-operator"][0] + "-" + details.ImageVariant + } + lines := strings.Split(output, "\n")[1:] // remove header of status. t.Logf("dapr status -k infos: \n%s\n", lines) for _, line := range lines { @@ -659,6 +673,9 @@ func installTest(details VersionDetails, opts TestOptions) func(t *testing.T) { } else { t.Log("install with mtls") } + if details.ImageVariant != "" { + args = append(args, "--image-variant", details.ImageVariant) + } output, err := spawn.Command(daprPath, args...) t.Log(output) require.NoError(t, err, "init failed") @@ -807,6 +824,14 @@ func validatePodsOnInstallUpgrade(t *testing.T, details VersionDetails) { "placement": details.RuntimeVersion, "operator": details.RuntimeVersion, } + + if details.ImageVariant != "" { + notFound["sentry"] = notFound["sentry"] + "-" + details.ImageVariant + notFound["sidecar"] = notFound["sidecar"] + "-" + details.ImageVariant + notFound["placement"] = notFound["placement"] + "-" + details.ImageVariant + notFound["operator"] = notFound["operator"] + "-" + details.ImageVariant + } + prefixes := map[string]string{ "sentry": "dapr-sentry-", "sidecar": "dapr-sidecar-injector-", diff --git a/tests/e2e/kubernetes/kubernetes_test.go b/tests/e2e/kubernetes/kubernetes_test.go index a0671efb..c262712f 100644 --- a/tests/e2e/kubernetes/kubernetes_test.go +++ b/tests/e2e/kubernetes/kubernetes_test.go @@ -39,6 +39,7 @@ func ensureCleanEnv(t *testing.T) { CustomResourceDefs: []string{"components.dapr.io", "configurations.dapr.io", "subscriptions.dapr.io"}, ClusterRoles: []string{"dapr-operator-admin", "dashboard-reader"}, ClusterRoleBindings: []string{"dapr-operator", "dapr-role-tokenreview-binding", "dashboard-reader-global"}, + ImageVariant: "", } // Ensure a clean environment common.EnsureUninstall(true) // does not wait for pod deletion @@ -318,7 +319,7 @@ func TestKubernetesUninstall(t *testing.T) { ensureCleanEnv(t) tests := []common.TestCase{} - var installOpts = common.TestOptions{ + installOpts := common.TestOptions{ HAEnabled: false, MTLSEnabled: true, ApplyComponentChanges: true, @@ -348,7 +349,7 @@ func TestRenewCertWithIncorrectFlags(t *testing.T) { common.EnsureUninstall(true) tests := []common.TestCase{} - var installOpts = common.TestOptions{ + installOpts := common.TestOptions{ HAEnabled: false, MTLSEnabled: true, ApplyComponentChanges: true, @@ -379,3 +380,38 @@ func TestRenewCertWithIncorrectFlags(t *testing.T) { t.Run(tc.Name, tc.Callable) } } + +func TestKubernetesInstallwithMarinerImages(t *testing.T) { + // ensure clean env for test + ensureCleanEnv(t) + + // install with mariner images + currentVersionDetails.ImageVariant = "mariner" + + tests := []common.TestCase{} + installOpts := common.TestOptions{ + HAEnabled: false, + MTLSEnabled: true, + ApplyComponentChanges: true, + CheckResourceExists: map[common.Resource]bool{ + common.CustomResourceDefs: true, + common.ClusterRoles: true, + common.ClusterRoleBindings: true, + }, + } + + tests = append(tests, common.GetTestsOnInstall(currentVersionDetails, installOpts)...) + + // teardown everything + tests = append(tests, common.GetTestsOnUninstall(currentVersionDetails, common.TestOptions{ + CheckResourceExists: map[common.Resource]bool{ + common.CustomResourceDefs: true, + common.ClusterRoles: false, + common.ClusterRoleBindings: false, + }, + })...) + + for _, tc := range tests { + t.Run(tc.Name, tc.Callable) + } +} diff --git a/tests/e2e/standalone/init_test.go b/tests/e2e/standalone/init_test.go index 86804ea8..b4d22a64 100644 --- a/tests/e2e/standalone/init_test.go +++ b/tests/e2e/standalone/init_test.go @@ -81,6 +81,26 @@ func TestStandaloneInit(t *testing.T) { verifyBinaries(t, daprPath, daprRuntimeVersion, daprDashboardVersion) verifyConfigs(t, daprPath) }) + + t.Run("init with mariner images", func(t *testing.T) { + // Ensure a clean environment + must(t, cmdUninstall, "failed to uninstall Dapr") + + output, err := cmdInit(daprRuntimeVersion, "--image-variant", "mariner") + t.Log(output) + require.NoError(t, err, "init failed") + assert.Contains(t, output, "Success! Dapr is up and running.") + + homeDir, err := os.UserHomeDir() + require.NoError(t, err, "failed to get user home directory") + + daprPath := filepath.Join(homeDir, ".dapr") + require.DirExists(t, daprPath, "Directory %s does not exist", daprPath) + + verifyContainers(t, daprRuntimeVersion+"-mariner") + verifyBinaries(t, daprPath, daprRuntimeVersion, daprDashboardVersion) + verifyConfigs(t, daprPath) + }) } // verifyContainers ensures that the correct containers are up and running. diff --git a/tests/e2e/upgrade/upgrade_test.go b/tests/e2e/upgrade/upgrade_test.go index 6ae5082b..b025a8ea 100644 --- a/tests/e2e/upgrade/upgrade_test.go +++ b/tests/e2e/upgrade/upgrade_test.go @@ -1,6 +1,3 @@ -//go:build e2e -// +build e2e - /* Copyright 2021 The Dapr Authors Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,6 +26,25 @@ type upgradePath struct { } var supportedUpgradePaths = []upgradePath{ + { + // test upgrade on mariner images. + previous: common.VersionDetails{ + RuntimeVersion: "1.8.0", + DashboardVersion: "0.10.0", + ImageVariant: "mariner", + ClusterRoles: []string{"dapr-operator-admin", "dashboard-reader"}, + ClusterRoleBindings: []string{"dapr-operator", "dapr-role-tokenreview-binding", "dashboard-reader-global"}, + CustomResourceDefs: []string{"components.dapr.io", "configurations.dapr.io", "subscriptions.dapr.io", "resiliencies.dapr.io"}, + }, + next: common.VersionDetails{ + RuntimeVersion: "1.8.4", + DashboardVersion: "0.10.0", + ImageVariant: "mariner", + ClusterRoles: []string{"dapr-operator-admin", "dashboard-reader"}, + ClusterRoleBindings: []string{"dapr-operator", "dapr-role-tokenreview-binding", "dashboard-reader-global"}, + CustomResourceDefs: []string{"components.dapr.io", "configurations.dapr.io", "subscriptions.dapr.io", "resiliencies.dapr.io"}, + }, + }, { previous: common.VersionDetails{ RuntimeVersion: "1.7.4", @@ -99,7 +115,7 @@ var supportedUpgradePaths = []upgradePath{ func getTestsOnUpgrade(p upgradePath, installOpts, upgradeOpts common.TestOptions) []common.TestCase { tests := []common.TestCase{} - // install previous version + // install previous version. tests = append(tests, common.GetTestsOnInstall(p.previous, installOpts)...) details := p.next @@ -114,7 +130,7 @@ func getTestsOnUpgrade(p upgradePath, installOpts, upgradeOpts common.TestOption {"status check " + details.RuntimeVersion, common.StatusTestOnInstallUpgrade(details, upgradeOpts)}, }...) - // uninstall + // uninstall. tests = append(tests, common.GetTestsOnUninstall(p.next, common.TestOptions{ CheckResourceExists: map[common.Resource]bool{ // TODO Related to https://github.com/dapr/cli/issues/656 @@ -124,7 +140,7 @@ func getTestsOnUpgrade(p upgradePath, installOpts, upgradeOpts common.TestOption }, })...) - // delete CRDs if exist + // delete CRDs if exist. tests = append(tests, common.TestCase{"delete CRDs " + p.previous.RuntimeVersion, common.DeleteCRD(p.previous.CustomResourceDefs)}) tests = append(tests, common.TestCase{"delete CRDs " + p.next.RuntimeVersion, common.DeleteCRD(p.next.CustomResourceDefs)}) @@ -134,8 +150,8 @@ func getTestsOnUpgrade(p upgradePath, installOpts, upgradeOpts common.TestOption // Upgrade path tests. func TestUpgradePathNonHAModeMTLSDisabled(t *testing.T) { - // Ensure a clean environment - common.EnsureUninstall(false) // does not wait for pod deletion + // Ensure a clean environment. + common.EnsureUninstall(false) // does not wait for pod deletion. for _, p := range supportedUpgradePaths { t.Run(fmt.Sprintf("setup v%s to v%s", p.previous.RuntimeVersion, p.next.RuntimeVersion), func(t *testing.T) { t.Run("delete CRDs "+p.previous.RuntimeVersion, common.DeleteCRD(p.previous.CustomResourceDefs)) @@ -159,7 +175,7 @@ func TestUpgradePathNonHAModeMTLSDisabled(t *testing.T) { upgradeOpts := common.TestOptions{ HAEnabled: false, MTLSEnabled: false, - // do not apply changes on upgrade, verify existing components + // do not apply changes on upgrade, verify existing components. ApplyComponentChanges: false, CheckResourceExists: map[common.Resource]bool{ common.CustomResourceDefs: true, @@ -177,8 +193,8 @@ func TestUpgradePathNonHAModeMTLSDisabled(t *testing.T) { } func TestUpgradePathNonHAModeMTLSEnabled(t *testing.T) { - // Ensure a clean environment - common.EnsureUninstall(false) // does not wait for pod deletion + // Ensure a clean environment. + common.EnsureUninstall(false) // does not wait for pod deletion. for _, p := range supportedUpgradePaths { t.Run(fmt.Sprintf("setup v%s to v%s", p.previous.RuntimeVersion, p.next.RuntimeVersion), func(t *testing.T) { t.Run("delete CRDs "+p.previous.RuntimeVersion, common.DeleteCRD(p.previous.CustomResourceDefs)) @@ -202,7 +218,7 @@ func TestUpgradePathNonHAModeMTLSEnabled(t *testing.T) { upgradeOpts := common.TestOptions{ HAEnabled: false, MTLSEnabled: true, - // do not apply changes on upgrade, verify existing components + // do not apply changes on upgrade, verify existing components. ApplyComponentChanges: false, CheckResourceExists: map[common.Resource]bool{ common.CustomResourceDefs: true, @@ -220,8 +236,8 @@ func TestUpgradePathNonHAModeMTLSEnabled(t *testing.T) { } func TestUpgradePathHAModeMTLSDisabled(t *testing.T) { - // Ensure a clean environment - common.EnsureUninstall(false) // does not wait for pod deletion + // Ensure a clean environment. + common.EnsureUninstall(false) // does not wait for pod deletion. for _, p := range supportedUpgradePaths { t.Run(fmt.Sprintf("setup v%s to v%s", p.previous.RuntimeVersion, p.next.RuntimeVersion), func(t *testing.T) { t.Run("delete CRDs "+p.previous.RuntimeVersion, common.DeleteCRD(p.previous.CustomResourceDefs)) @@ -245,7 +261,7 @@ func TestUpgradePathHAModeMTLSDisabled(t *testing.T) { upgradeOpts := common.TestOptions{ HAEnabled: true, MTLSEnabled: false, - // do not apply changes on upgrade, verify existing components + // do not apply changes on upgrade, verify existing components. ApplyComponentChanges: false, CheckResourceExists: map[common.Resource]bool{ common.CustomResourceDefs: true, @@ -263,8 +279,8 @@ func TestUpgradePathHAModeMTLSDisabled(t *testing.T) { } func TestUpgradePathHAModeMTLSEnabled(t *testing.T) { - // Ensure a clean environment - common.EnsureUninstall(false) // does not wait for pod deletion + // Ensure a clean environment. + common.EnsureUninstall(false) // does not wait for pod deletion. for _, p := range supportedUpgradePaths { t.Run(fmt.Sprintf("setup v%s to v%s", p.previous.RuntimeVersion, p.next.RuntimeVersion), func(t *testing.T) { t.Run("delete CRDs "+p.previous.RuntimeVersion, common.DeleteCRD(p.previous.CustomResourceDefs)) @@ -288,7 +304,7 @@ func TestUpgradePathHAModeMTLSEnabled(t *testing.T) { upgradeOpts := common.TestOptions{ HAEnabled: true, MTLSEnabled: true, - // do not apply changes on upgrade, verify existing components + // do not apply changes on upgrade, verify existing components. ApplyComponentChanges: false, CheckResourceExists: map[common.Resource]bool{ common.CustomResourceDefs: true, diff --git a/utils/utils.go b/utils/utils.go index b96452d0..333297f5 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -52,6 +52,8 @@ func GetContainerRuntimeCmd(containerRuntime string) string { } } +const marinerImageVariantName = "mariner" + // PrintTable to print in the table format. func PrintTable(csvContent string) { WriteTable(os.Stdout, csvContent) @@ -274,3 +276,17 @@ func GetDefaultRegistry(githubContainerRegistryName, dockerContainerRegistryName return "", fmt.Errorf("environment variable %q can only be set to %s", "DAPR_DEFAULT_IMAGE_REGISTRY", "GHCR") } } + +func ValidateImageVariant(imageVariant string) error { + if imageVariant != "" && imageVariant != marinerImageVariantName { + return fmt.Errorf("image variant %s is not supported", imageVariant) + } + return nil +} + +func GetVariantVersion(version, imageVariant string) string { + if imageVariant == "" { + return version + } + return fmt.Sprintf("%s-%s", version, imageVariant) +}