diff --git a/api/controllers/app/install/test_suite.go b/api/controllers/app/install/test_suite.go index 37992c92e4..00bb68fd5d 100644 --- a/api/controllers/app/install/test_suite.go +++ b/api/controllers/app/install/test_suite.go @@ -641,8 +641,8 @@ func (s *AppInstallControllerTestSuite) TestInstallApp() { NoProxy: "localhost,127.0.0.1", }, registrySettings: &types.RegistrySettings{ - HasLocalRegistry: true, - Host: "10.128.0.11:5000", + HasLocalRegistry: true, + LocalRegistryHost: "10.128.0.11:5000", }, setupMocks: func(acm *appconfig.MockAppConfigManager, arm *appreleasemanager.MockAppReleaseManager, aim *appinstallmanager.MockAppInstallManager) { configValues := kotsv1beta1.ConfigValues{ diff --git a/api/integration/linux/install/appinstall_test.go b/api/integration/linux/install/appinstall_test.go index 2ec7c3e465..672089bf95 100644 --- a/api/integration/linux/install/appinstall_test.go +++ b/api/integration/linux/install/appinstall_test.go @@ -34,6 +34,18 @@ import ( "github.com/stretchr/testify/require" ) +// mockLicense creates a mock license for testing +func mockLicense() []byte { + return []byte(` +apiVersion: kots.io/v1beta1 +kind: License +spec: + licenseID: "test-license-id-12345" + appSlug: "test-app" + customerName: "Test Customer" +`) +} + // TestGetAppInstallStatus tests the GET /linux/install/app/status endpoint func TestGetAppInstallStatus(t *testing.T) { // Create mock helm chart archive @@ -44,9 +56,11 @@ func TestGetAppInstallStatus(t *testing.T) { HelmChartArchives: [][]byte{mockChartArchive}, EmbeddedClusterConfig: &ecv1beta1.Config{}, ChannelRelease: &release.ChannelRelease{ + AppSlug: "test-app", DefaultDomains: release.Domains{ - ReplicatedAppDomain: "replicated.example.com", - ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedAppDomain: "replicated.example.com", + ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedRegistryDomain: "registry.example.com", }, }, AppConfig: &kotsv1beta1.Config{}, @@ -107,6 +121,7 @@ func TestGetAppInstallStatus(t *testing.T) { linuxinstall.WithAppInstallController(appInstallController), linuxinstall.WithReleaseData(releaseData), linuxinstall.WithRuntimeConfig(runtimeconfig.New(nil)), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -163,6 +178,7 @@ func TestGetAppInstallStatus(t *testing.T) { // Create simple Linux install controller installController, err := linuxinstall.NewInstallController( linuxinstall.WithReleaseData(releaseData), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -226,9 +242,11 @@ func TestPostInstallApp(t *testing.T) { releaseData := &release.ReleaseData{ EmbeddedClusterConfig: &ecv1beta1.Config{}, ChannelRelease: &release.ChannelRelease{ + AppSlug: "test-app", DefaultDomains: release.Domains{ - ReplicatedAppDomain: "replicated.example.com", - ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedAppDomain: "replicated.example.com", + ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedRegistryDomain: "registry.example.com", }, }, AppConfig: &kotsv1beta1.Config{}, @@ -317,6 +335,7 @@ func TestPostInstallApp(t *testing.T) { linuxinstall.WithMetricsReporter(mockReporter), linuxinstall.WithReleaseData(releaseData), linuxinstall.WithRuntimeConfig(rc), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -386,6 +405,7 @@ func TestPostInstallApp(t *testing.T) { linuxinstall.WithStateMachine(stateMachine), linuxinstall.WithAppInstallController(appInstallController), linuxinstall.WithReleaseData(releaseData), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -472,6 +492,7 @@ func TestPostInstallApp(t *testing.T) { linuxinstall.WithStore(mockStore), linuxinstall.WithReleaseData(releaseData), linuxinstall.WithRuntimeConfig(rc), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -524,6 +545,7 @@ func TestPostInstallApp(t *testing.T) { // Create simple Linux install controller installController, err := linuxinstall.NewInstallController( linuxinstall.WithReleaseData(releaseData), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -597,6 +619,7 @@ func TestPostInstallApp(t *testing.T) { linuxinstall.WithStateMachine(stateMachine), linuxinstall.WithAppInstallController(appInstallController), linuxinstall.WithReleaseData(releaseData), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -672,6 +695,7 @@ func TestPostInstallApp(t *testing.T) { linuxinstall.WithStateMachine(stateMachine), linuxinstall.WithAppInstallController(appInstallController), linuxinstall.WithReleaseData(releaseData), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) diff --git a/api/integration/linux/install/apppreflight_test.go b/api/integration/linux/install/apppreflight_test.go index 4f92ff9fbf..9744114bff 100644 --- a/api/integration/linux/install/apppreflight_test.go +++ b/api/integration/linux/install/apppreflight_test.go @@ -236,14 +236,17 @@ func TestPostRunAppPreflights(t *testing.T) { linuxinstall.WithReleaseData(&release.ReleaseData{ EmbeddedClusterConfig: &ecv1beta1.Config{}, ChannelRelease: &release.ChannelRelease{ + AppSlug: "test-app", DefaultDomains: release.Domains{ - ReplicatedAppDomain: "replicated.example.com", - ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedAppDomain: "replicated.example.com", + ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedRegistryDomain: "registry.example.com", }, }, AppConfig: &kotsv1beta1.Config{}, }), linuxinstall.WithRuntimeConfig(rc), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) @@ -292,8 +295,19 @@ func TestPostRunAppPreflights(t *testing.T) { linuxinstall.WithStateMachine(linuxinstall.NewStateMachine( linuxinstall.WithCurrentState(states.StateNew), // Wrong state )), - linuxinstall.WithReleaseData(integration.DefaultReleaseData()), + linuxinstall.WithReleaseData(&release.ReleaseData{ + AppConfig: &kotsv1beta1.Config{}, + ChannelRelease: &release.ChannelRelease{ + AppSlug: "test-app", + DefaultDomains: release.Domains{ + ReplicatedAppDomain: "replicated.example.com", + ProxyRegistryDomain: "some-proxy.example.com", + ReplicatedRegistryDomain: "registry.example.com", + }, + }, + }), linuxinstall.WithRuntimeConfig(rc), + linuxinstall.WithLicense(mockLicense()), ) require.NoError(t, err) diff --git a/api/internal/handlers/kubernetes/install.go b/api/internal/handlers/kubernetes/install.go index 6977d626cd..e59df0393d 100644 --- a/api/internal/handlers/kubernetes/install.go +++ b/api/internal/handlers/kubernetes/install.go @@ -97,6 +97,8 @@ func (h *Handler) PostRunAppPreflights(w http.ResponseWriter, r *http.Request) { return } + // TODO: support registry settings + err = h.installController.RunAppPreflights(r.Context(), appinstall.RunAppPreflightOptions{ PreflightBinaryPath: preflightBinary, ProxySpec: h.cfg.Installation.ProxySpec(), @@ -300,6 +302,8 @@ func (h *Handler) PostInstallApp(w http.ResponseWriter, r *http.Request) { return } + // TODO: support registry settings + err := h.installController.InstallApp(r.Context(), appinstall.InstallAppOptions{ IgnoreAppPreflights: req.IgnoreAppPreflights, ProxySpec: h.cfg.Installation.ProxySpec(), diff --git a/api/internal/managers/app/release/template_test.go b/api/internal/managers/app/release/template_test.go index 710d84e3f6..ce527b3f65 100644 --- a/api/internal/managers/app/release/template_test.go +++ b/api/internal/managers/app/release/template_test.go @@ -723,12 +723,12 @@ spec: }, configValues: types.AppConfigValues{}, registrySettings: &types.RegistrySettings{ - HasLocalRegistry: true, - Host: "10.128.0.11:5000", - Address: "10.128.0.11:5000/myapp", - Namespace: "myapp", - ImagePullSecretName: "embedded-cluster-registry", - ImagePullSecretValue: "dGVzdC1zZWNyZXQtdmFsdWU=", + HasLocalRegistry: true, + LocalRegistryHost: "10.128.0.11:5000", + LocalRegistryAddress: "10.128.0.11:5000/myapp", + LocalRegistryNamespace: "myapp", + ImagePullSecretName: "test-app-registry", + ImagePullSecretValue: "dGVzdC1zZWNyZXQtdmFsdWU=", }, expected: []*kotsv1beta2.HelmChart{ createHelmChartCRFromYAML(` @@ -745,7 +745,7 @@ spec: image: repository: "10.128.0.11:5000/myapp/nginx" imagePullSecrets: - - name: "embedded-cluster-registry" + - name: "test-app-registry" registry: host: "10.128.0.11:5000" address: "10.128.0.11:5000/myapp" @@ -2343,12 +2343,12 @@ spec: }, configValues: types.AppConfigValues{}, registrySettings: &types.RegistrySettings{ - HasLocalRegistry: true, - Host: "10.128.0.11:5000", - Address: "10.128.0.11:5000/myapp", - Namespace: "myapp", - ImagePullSecretName: "embedded-cluster-registry", - ImagePullSecretValue: "dGVzdC1zZWNyZXQtdmFsdWU=", + HasLocalRegistry: true, + LocalRegistryHost: "10.128.0.11:5000", + LocalRegistryAddress: "10.128.0.11:5000/myapp", + LocalRegistryNamespace: "myapp", + ImagePullSecretName: "test-app-registry", + ImagePullSecretValue: "dGVzdC1zZWNyZXQtdmFsdWU=", }, expectError: false, expected: []types.InstallableHelmChart{ @@ -2360,7 +2360,7 @@ spec: "tag": "1.20.0", }, "imagePullSecrets": []any{ - map[string]any{"name": "embedded-cluster-registry"}, + map[string]any{"name": "test-app-registry"}, }, "registry": map[string]any{ "host": "10.128.0.11:5000", @@ -2383,7 +2383,7 @@ spec: repository: "10.128.0.11:5000/myapp/nginx" tag: "1.20.0" imagePullSecrets: - - name: "embedded-cluster-registry" + - name: "test-app-registry" registry: host: "10.128.0.11:5000" address: "10.128.0.11:5000/myapp" diff --git a/api/internal/managers/linux/installation/config.go b/api/internal/managers/linux/installation/config.go index 0c8e4f6d09..cdb9787e25 100644 --- a/api/internal/managers/linux/installation/config.go +++ b/api/internal/managers/linux/installation/config.go @@ -7,6 +7,7 @@ import ( "fmt" "runtime/debug" + "github.com/replicatedhq/embedded-cluster/api/internal/utils" "github.com/replicatedhq/embedded-cluster/api/types" ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1" newconfig "github.com/replicatedhq/embedded-cluster/pkg-new/config" @@ -14,6 +15,8 @@ import ( "github.com/replicatedhq/embedded-cluster/pkg/addons/registry" "github.com/replicatedhq/embedded-cluster/pkg/netutils" "github.com/replicatedhq/embedded-cluster/pkg/runtimeconfig" + kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" + kyaml "sigs.k8s.io/yaml" ) func (m *installationManager) GetConfig() (types.LinuxInstallationConfig, error) { @@ -236,11 +239,37 @@ func (m *installationManager) ConfigureHost(ctx context.Context, rc runtimeconfi return nil } -// CalculateRegistrySettings calculates registry settings for airgap installations +// CalculateRegistrySettings calculates registry settings for both online and airgap installations func (m *installationManager) CalculateRegistrySettings(ctx context.Context, rc runtimeconfig.RuntimeConfig) (*types.RegistrySettings, error) { - // Only return registry settings for airgap installations if m.airgapBundle == "" { - return nil, nil + // Online mode: Use replicated proxy registry with license ID authentication + ecDomains := utils.GetDomains(m.releaseData) + + // Parse license from bytes + if len(m.license) == 0 { + return nil, fmt.Errorf("license is required for online registry settings") + } + license := &kotsv1beta1.License{} + if err := kyaml.Unmarshal(m.license, license); err != nil { + return nil, fmt.Errorf("parse license: %w", err) + } + + // Get app slug for secret name + if m.releaseData == nil || m.releaseData.ChannelRelease == nil || m.releaseData.ChannelRelease.AppSlug == "" { + return nil, fmt.Errorf("release data with app slug is required for registry settings") + } + appSlug := m.releaseData.ChannelRelease.AppSlug + + // Create auth config for both proxy and registry domains + authConfig := fmt.Sprintf(`{"auths":{"%s":{"username": "LICENSE_ID", "password": "%s"},"%s":{"username": "LICENSE_ID", "password": "%s"}}}`, + ecDomains.ProxyRegistryDomain, license.Spec.LicenseID, ecDomains.ReplicatedRegistryDomain, license.Spec.LicenseID) + imagePullSecretValue := base64.StdEncoding.EncodeToString([]byte(authConfig)) + + return &types.RegistrySettings{ + HasLocalRegistry: false, + ImagePullSecretName: fmt.Sprintf("%s-registry", appSlug), + ImagePullSecretValue: imagePullSecretValue, + }, nil } // Use runtime config as the authoritative source for service CIDR @@ -254,27 +283,27 @@ func (m *installationManager) CalculateRegistrySettings(ctx context.Context, rc // Construct registry host with port registryHost := fmt.Sprintf("%s:5000", registryIP) - // Get app namespace from release data - required for app preflights + // Get app slug for secret name if m.releaseData == nil || m.releaseData.ChannelRelease == nil || m.releaseData.ChannelRelease.AppSlug == "" { return nil, fmt.Errorf("release data with app slug is required for registry settings") } - appNamespace := m.releaseData.ChannelRelease.AppSlug + appSlug := m.releaseData.ChannelRelease.AppSlug // Construct full registry address with namespace + appNamespace := appSlug // registry namespace is the same as the app slug in linux target registryAddress := fmt.Sprintf("%s/%s", registryHost, appNamespace) // Create image pull secret value using the same pattern as admin console - authString := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("embedded-cluster:%s", registry.GetRegistryPassword()))) - authConfig := fmt.Sprintf(`{"auths":{"%s":{"username": "embedded-cluster", "password": "%s", "auth": "%s"}}}`, - registryHost, registry.GetRegistryPassword(), authString) + authConfig := fmt.Sprintf(`{"auths":{"%s":{"username": "embedded-cluster", "password": "%s"}}}`, + registryHost, registry.GetRegistryPassword()) imagePullSecretValue := base64.StdEncoding.EncodeToString([]byte(authConfig)) return &types.RegistrySettings{ - HasLocalRegistry: true, - Host: registryHost, - Address: registryAddress, - Namespace: appNamespace, - ImagePullSecretName: "embedded-cluster-registry", - ImagePullSecretValue: imagePullSecretValue, + HasLocalRegistry: true, + LocalRegistryHost: registryHost, + LocalRegistryAddress: registryAddress, + LocalRegistryNamespace: appNamespace, + ImagePullSecretName: fmt.Sprintf("%s-registry", appSlug), + ImagePullSecretValue: imagePullSecretValue, }, nil } diff --git a/api/internal/managers/linux/installation/config_test.go b/api/internal/managers/linux/installation/config_test.go index 7babb46d71..59513adfaa 100644 --- a/api/internal/managers/linux/installation/config_test.go +++ b/api/internal/managers/linux/installation/config_test.go @@ -2,7 +2,9 @@ package installation import ( "context" + "encoding/base64" "errors" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -13,7 +15,11 @@ import ( "github.com/replicatedhq/embedded-cluster/api/types" ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1" "github.com/replicatedhq/embedded-cluster/pkg-new/hostutils" + "github.com/replicatedhq/embedded-cluster/pkg/addons/registry" + "github.com/replicatedhq/embedded-cluster/pkg/release" "github.com/replicatedhq/embedded-cluster/pkg/runtimeconfig" + kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1" + kyaml "sigs.k8s.io/yaml" ) func TestValidateConfig(t *testing.T) { @@ -466,3 +472,172 @@ func TestConfigureHost(t *testing.T) { }) } } + +func TestCalculateRegistrySettings(t *testing.T) { + // Helper to create a test license + createTestLicense := func(licenseID, appSlug string) []byte { + license := kotsv1beta1.License{ + Spec: kotsv1beta1.LicenseSpec{ + LicenseID: licenseID, + AppSlug: appSlug, + }, + } + licenseBytes, _ := kyaml.Marshal(license) + return licenseBytes + } + + // Helper to create test release data + createTestReleaseData := func(appSlug string, domains *ecv1beta1.Domains) *release.ReleaseData { + releaseData := &release.ReleaseData{ + ChannelRelease: &release.ChannelRelease{ + AppSlug: appSlug, + }, + } + if domains != nil { + releaseData.EmbeddedClusterConfig = &ecv1beta1.Config{ + Spec: ecv1beta1.ConfigSpec{ + Domains: *domains, + }, + } + } + return releaseData + } + + // Helper to create runtime config + createTestRuntimeConfig := func() runtimeconfig.RuntimeConfig { + return runtimeconfig.New(&ecv1beta1.RuntimeConfigSpec{ + Network: ecv1beta1.NetworkSpec{ + ServiceCIDR: "10.96.0.0/12", + }, + }) + } + + tests := []struct { + name string + license []byte + releaseData *release.ReleaseData + airgapBundle string + expectedResult *types.RegistrySettings + expectedError string + }{ + { + name: "online mode with default domains", + license: createTestLicense("test-license-123", "test-app"), + releaseData: createTestReleaseData("test-app", nil), + airgapBundle: "", // Online mode + expectedResult: &types.RegistrySettings{ + HasLocalRegistry: false, + ImagePullSecretName: "test-app-registry", + ImagePullSecretValue: base64.StdEncoding.EncodeToString([]byte(`{"auths":{"proxy.replicated.com":{"username": "LICENSE_ID", "password": "test-license-123"},"registry.replicated.com":{"username": "LICENSE_ID", "password": "test-license-123"}}}`)), + }, + }, + { + name: "online mode with custom domains", + license: createTestLicense("custom-license-456", "custom-app"), + releaseData: createTestReleaseData("custom-app", &ecv1beta1.Domains{ + ProxyRegistryDomain: "custom-proxy.example.com", + ReplicatedRegistryDomain: "custom-registry.example.com", + }), + airgapBundle: "", // Online mode + expectedResult: &types.RegistrySettings{ + HasLocalRegistry: false, + ImagePullSecretName: "custom-app-registry", + ImagePullSecretValue: base64.StdEncoding.EncodeToString([]byte(`{"auths":{"custom-proxy.example.com":{"username": "LICENSE_ID", "password": "custom-license-456"},"custom-registry.example.com":{"username": "LICENSE_ID", "password": "custom-license-456"}}}`)), + }, + }, + { + name: "online mode missing license", + license: nil, + releaseData: createTestReleaseData("test-app", nil), + airgapBundle: "", // Online mode + expectedError: "license is required for online registry settings", + }, + { + name: "online mode empty license", + license: []byte{}, + releaseData: createTestReleaseData("test-app", nil), + airgapBundle: "", // Online mode + expectedError: "license is required for online registry settings", + }, + { + name: "online mode invalid license format", + license: []byte("invalid yaml"), + releaseData: createTestReleaseData("test-app", nil), + airgapBundle: "", // Online mode + expectedError: "parse license:", + }, + { + name: "online mode missing release data", + license: createTestLicense("test-license", "test-app"), + releaseData: nil, + airgapBundle: "", // Online mode + expectedError: "release data with app slug is required for registry settings", + }, + { + name: "online mode missing app slug", + license: createTestLicense("test-license", "test-app"), + releaseData: &release.ReleaseData{ + ChannelRelease: &release.ChannelRelease{ + AppSlug: "", // Empty app slug + }, + }, + airgapBundle: "", // Online mode + expectedError: "release data with app slug is required for registry settings", + }, + { + name: "airgap mode", + license: createTestLicense("test-license", "test-app"), + releaseData: createTestReleaseData("test-app", nil), + airgapBundle: "test-bundle.tar", + expectedResult: &types.RegistrySettings{ + HasLocalRegistry: true, + LocalRegistryHost: "10.96.0.11:5000", + LocalRegistryAddress: "10.96.0.11:5000/test-app", + LocalRegistryNamespace: "test-app", + ImagePullSecretName: "test-app-registry", + ImagePullSecretValue: base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(`{"auths":{"10.96.0.11:5000":{"username": "embedded-cluster", "password": "%s"}}}`, registry.GetRegistryPassword()))), + }, + }, + { + name: "airgap mode missing release data", + license: createTestLicense("test-license", "test-app"), + releaseData: nil, + airgapBundle: "test-bundle.tar", + expectedError: "release data with app slug is required for registry settings", + }, + { + name: "airgap mode missing app slug", + license: createTestLicense("test-license", "test-app"), + releaseData: &release.ReleaseData{ + ChannelRelease: &release.ChannelRelease{ + AppSlug: "", // Empty app slug + }, + }, + airgapBundle: "test-bundle.tar", + expectedError: "release data with app slug is required for registry settings", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rc := createTestRuntimeConfig() + + manager := NewInstallationManager( + WithLicense(tt.license), + WithReleaseData(tt.releaseData), + WithAirgapBundle(tt.airgapBundle), + ) + + result, err := manager.CalculateRegistrySettings(context.Background(), rc) + + if tt.expectedError != "" { + assert.Error(t, err) + assert.Contains(t, err.Error(), tt.expectedError) + assert.Nil(t, result) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expectedResult, result) + } + }) + } +} diff --git a/api/pkg/template/registry.go b/api/pkg/template/registry.go index 8e1dce22c0..1c52ccafb5 100644 --- a/api/pkg/template/registry.go +++ b/api/pkg/template/registry.go @@ -15,7 +15,7 @@ func (e *Engine) localRegistryHost() string { if e.registrySettings == nil { return "" } - return e.registrySettings.Host + return e.registrySettings.LocalRegistryHost } // localRegistryAddress returns full registry address with namespace (e.g., "10.128.0.11:5000/myapp") @@ -23,7 +23,7 @@ func (e *Engine) localRegistryAddress() string { if e.registrySettings == nil { return "" } - return e.registrySettings.Address + return e.registrySettings.LocalRegistryAddress } // localRegistryNamespace returns the app-specific namespace for registry isolation @@ -31,7 +31,7 @@ func (e *Engine) localRegistryNamespace() string { if e.registrySettings == nil { return "" } - return e.registrySettings.Namespace + return e.registrySettings.LocalRegistryNamespace } // imagePullSecretName returns the standardized image pull secret name diff --git a/api/pkg/template/registry_test.go b/api/pkg/template/registry_test.go index 40799242dd..bca6c33ec5 100644 --- a/api/pkg/template/registry_test.go +++ b/api/pkg/template/registry_test.go @@ -67,14 +67,14 @@ func TestEngine_LocalRegistryHost(t *testing.T) { { name: "empty host returns empty string", registrySettings: &types.RegistrySettings{ - Host: "", + LocalRegistryHost: "", }, expectedResult: "", }, { name: "host with port returns host", registrySettings: &types.RegistrySettings{ - Host: "10.128.0.11:5000", + LocalRegistryHost: "10.128.0.11:5000", }, expectedResult: "10.128.0.11:5000", }, @@ -112,14 +112,14 @@ func TestEngine_LocalRegistryAddress(t *testing.T) { { name: "empty address returns empty string", registrySettings: &types.RegistrySettings{ - Address: "", + LocalRegistryAddress: "", }, expectedResult: "", }, { name: "address with namespace returns address", registrySettings: &types.RegistrySettings{ - Address: "10.128.0.11:5000/myapp", + LocalRegistryAddress: "10.128.0.11:5000/myapp", }, expectedResult: "10.128.0.11:5000/myapp", }, @@ -157,14 +157,14 @@ func TestEngine_LocalRegistryNamespace(t *testing.T) { { name: "empty namespace returns empty string", registrySettings: &types.RegistrySettings{ - Namespace: "", + LocalRegistryNamespace: "", }, expectedResult: "", }, { name: "namespace returns namespace", registrySettings: &types.RegistrySettings{ - Namespace: "myapp", + LocalRegistryNamespace: "myapp", }, expectedResult: "myapp", }, @@ -209,9 +209,9 @@ func TestEngine_ImagePullSecretName(t *testing.T) { { name: "secret name returns secret name", registrySettings: &types.RegistrySettings{ - ImagePullSecretName: "embedded-cluster-registry", + ImagePullSecretName: "test-app-registry", }, - expectedResult: "embedded-cluster-registry", + expectedResult: "test-app-registry", }, } @@ -281,12 +281,12 @@ func TestEngine_LocalRegistryImagePullSecret(t *testing.T) { // TestEngine_RegistryFunctionsIntegrated tests multiple registry functions in a single template func TestEngine_RegistryFunctionsIntegrated(t *testing.T) { registrySettings := &types.RegistrySettings{ - HasLocalRegistry: true, - Host: "10.128.0.11:5000", - Address: "10.128.0.11:5000/myapp", - Namespace: "myapp", - ImagePullSecretName: "embedded-cluster-registry", - ImagePullSecretValue: "eyJhdXRocyI6e319", + HasLocalRegistry: true, + LocalRegistryHost: "10.128.0.11:5000", + LocalRegistryAddress: "10.128.0.11:5000/myapp", + LocalRegistryNamespace: "myapp", + ImagePullSecretName: "test-app-registry", + ImagePullSecretValue: "eyJhdXRocyI6e319", } tests := []struct { @@ -312,7 +312,7 @@ func TestEngine_RegistryFunctionsIntegrated(t *testing.T) { { name: "image pull secret name in yaml", template: "- name: '{{repl ImagePullSecretName }}'", - expectedResult: "- name: 'embedded-cluster-registry'", + expectedResult: "- name: 'test-app-registry'", }, } diff --git a/api/types/registry.go b/api/types/registry.go index db910a5dc6..c5b063419e 100644 --- a/api/types/registry.go +++ b/api/types/registry.go @@ -5,14 +5,14 @@ type RegistrySettings struct { // HasLocalRegistry indicates if a local registry is available (airgap installations) HasLocalRegistry bool `json:"hasLocalRegistry"` - // Host is the registry host with port (e.g., "10.128.0.11:5000") - Host string `json:"host"` + // LocalRegistryHost is the registry host with port (e.g., "10.128.0.11:5000") + LocalRegistryHost string `json:"host"` - // Address is the full registry address with namespace (e.g., "10.128.0.11:5000/myapp") - Address string `json:"address"` + // LocalRegistryAddress is the full registry address with namespace (e.g., "10.128.0.11:5000/myapp") + LocalRegistryAddress string `json:"address"` - // Namespace is the app-specific namespace for registry isolation - Namespace string `json:"namespace"` + // LocalRegistryNamespace is the app-specific namespace for registry isolation + LocalRegistryNamespace string `json:"namespace"` // ImagePullSecretName is the standardized image pull secret name ImagePullSecretName string `json:"imagePullSecretName"` diff --git a/e2e/kots-release-install-v3/nginx-app-helm-v1beta2.yaml b/e2e/kots-release-install-v3/nginx-app-helm-v1beta2.yaml index 6037f0d2ce..a706fc4e89 100644 --- a/e2e/kots-release-install-v3/nginx-app-helm-v1beta2.yaml +++ b/e2e/kots-release-install-v3/nginx-app-helm-v1beta2.yaml @@ -42,10 +42,10 @@ spec: configItemsConfigMapData: # Registry template functions verification has_local_registry: repl{{ HasLocalRegistry }} - local_registry_host: repl{{ HasLocalRegistry | ternary LocalRegistryHost "fallback-host" }} - local_registry_namespace: repl{{ HasLocalRegistry | ternary LocalRegistryNamespace "fallback-namespace" }} - local_registry_address: repl{{ HasLocalRegistry | ternary LocalRegistryAddress "fallback-address" }} - image_pull_secret_name: repl{{ HasLocalRegistry | ternary ImagePullSecretName "fallback-secret" }} + local_registry_host: repl{{ HasLocalRegistry | ternary LocalRegistryHost "ec-e2e-proxy.testcluster.net" }} + local_registry_namespace: repl{{ HasLocalRegistry | ternary LocalRegistryNamespace "anonymous/registry.replicated.com/library" }} + local_registry_address: repl{{ HasLocalRegistry | ternary LocalRegistryAddress "ec-e2e-proxy.testcluster.net/anonymous/registry.replicated.com/library" }} + image_pull_secret_name: repl{{ ImagePullSecretName }} image_pull_secret_value: repl{{ LocalRegistryImagePullSecret }} # Text items