Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/controllers/app/install/test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
32 changes: 28 additions & 4 deletions api/integration/linux/install/appinstall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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{},
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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{},
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
20 changes: 17 additions & 3 deletions api/integration/linux/install/apppreflight_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions api/internal/handlers/kubernetes/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
30 changes: 15 additions & 15 deletions api/internal/managers/app/release/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(`
Expand All @@ -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"
Expand Down Expand Up @@ -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{
Expand All @@ -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",
Expand All @@ -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"
Expand Down
57 changes: 43 additions & 14 deletions api/internal/managers/linux/installation/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ 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"
"github.com/replicatedhq/embedded-cluster/pkg-new/hostutils"
"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) {
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Loading
Loading