diff --git a/cli/cmd/enterprise_portal_preview.go b/cli/cmd/enterprise_portal_preview.go index 73a299a5d..dba4b4ee7 100644 --- a/cli/cmd/enterprise_portal_preview.go +++ b/cli/cmd/enterprise_portal_preview.go @@ -376,6 +376,9 @@ func customerToPreviewLicense(app *types.App, c types.Customer) previewLicense { IsEmbeddedClusterDownloadEnabled: c.IsEmbeddedClusterDownloadEnabled, IsEmbeddedClusterMultiNodeEnabled: c.IsEmbeddedClusterMultinodeEnabled, IsKotsInstallEnabled: c.IsKotsInstallEnabled, + IsHelmInstallEnabled: c.IsHelmInstallEnabled, + IsKurlInstallEnabled: c.IsKurlInstallEnabled, + IsHelmAirgapEnabled: c.IsHelmAirgapEnabled, EntitlementFields: []previewEntitlementField{}, EntitlementValues: values, } diff --git a/cli/cmd/enterprise_portal_preview_test.go b/cli/cmd/enterprise_portal_preview_test.go new file mode 100644 index 000000000..1679d8c0b --- /dev/null +++ b/cli/cmd/enterprise_portal_preview_test.go @@ -0,0 +1,169 @@ +package cmd + +import ( + "testing" + + "github.com/replicatedhq/replicated/pkg/types" + "github.com/stretchr/testify/assert" +) + +func TestCustomerToPreviewLicense_HelmInstallEnabled(t *testing.T) { + app := &types.App{ + ID: "app_abc", + Name: "Test App", + } + + tests := []struct { + name string + customer types.Customer + want bool + }{ + { + name: "IsHelmInstallEnabled true is mapped", + customer: types.Customer{ + ID: "cust_abc", + Name: "Helm Customer", + IsHelmInstallEnabled: true, + }, + want: true, + }, + { + name: "IsHelmInstallEnabled false is mapped", + customer: types.Customer{ + ID: "cust_def", + Name: "No Helm Customer", + IsHelmInstallEnabled: false, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pl := customerToPreviewLicense(app, tt.customer) + assert.Equal(t, tt.want, pl.IsHelmInstallEnabled) + }) + } +} + +func TestCustomerToPreviewLicense_KurlInstallEnabled(t *testing.T) { + app := &types.App{ + ID: "app_abc", + Name: "Test App", + } + + tests := []struct { + name string + customer types.Customer + want bool + }{ + { + name: "IsKurlInstallEnabled true is mapped", + customer: types.Customer{ + ID: "cust_abc", + Name: "Kurl Customer", + IsKurlInstallEnabled: true, + }, + want: true, + }, + { + name: "IsKurlInstallEnabled false is mapped", + customer: types.Customer{ + ID: "cust_def", + Name: "No Kurl Customer", + IsKurlInstallEnabled: false, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pl := customerToPreviewLicense(app, tt.customer) + assert.Equal(t, tt.want, pl.IsKurlInstallEnabled) + }) + } +} + +func TestCustomerToPreviewLicense_HelmAirgapEnabled(t *testing.T) { + app := &types.App{ + ID: "app_abc", + Name: "Test App", + } + + tests := []struct { + name string + customer types.Customer + want bool + }{ + { + name: "IsHelmAirgapEnabled true is mapped", + customer: types.Customer{ + ID: "cust_abc", + Name: "Airgap Customer", + IsHelmAirgapEnabled: true, + }, + want: true, + }, + { + name: "IsHelmAirgapEnabled false is mapped", + customer: types.Customer{ + ID: "cust_def", + Name: "No Airgap Customer", + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pl := customerToPreviewLicense(app, tt.customer) + assert.Equal(t, tt.want, pl.IsHelmAirgapEnabled) + }) + } +} + +func TestCustomerToPreviewLicense_AllCapabilities(t *testing.T) { + app := &types.App{ + ID: "app_abc", + Name: "Test App", + } + + cust := types.Customer{ + ID: "cust_full", + Name: "Full Customer", + Email: "full@example.com", + InstallationID: "inst_123", + IsAirgapEnabled: true, + IsGitopsSupported: true, + IsIdentityServiceSupported: true, + IsGeoaxisSupported: true, + IsSnapshotSupported: true, + IsSupportBundleUploadEnabled: true, + IsEmbeddedClusterDownloadEnabled: true, + IsEmbeddedClusterMultinodeEnabled: true, + IsKotsInstallEnabled: true, + IsHelmInstallEnabled: true, + IsKurlInstallEnabled: true, + IsHelmAirgapEnabled: true, + } + + pl := customerToPreviewLicense(app, cust) + + assert.Equal(t, "inst_123", pl.ID) + assert.Equal(t, app.ID, pl.AppID) + assert.Equal(t, app.Name, pl.AppName) + assert.Equal(t, "cust_full", pl.CustomerID) + assert.Equal(t, "Full Customer", pl.CustomerName) + assert.Equal(t, "full@example.com", pl.CustomerEmail) + + assert.True(t, pl.IsAirgapSupported) + assert.True(t, pl.IsGitopsSupported) + assert.True(t, pl.IsIdentityServiceSupported) + assert.True(t, pl.IsGeoaxisSupported) + assert.True(t, pl.IsSnapshotSupported) + assert.True(t, pl.IsSupportBundleUploadSupported) + assert.True(t, pl.IsEmbeddedClusterDownloadEnabled) + assert.True(t, pl.IsEmbeddedClusterMultiNodeEnabled) + assert.True(t, pl.IsKotsInstallEnabled) + assert.True(t, pl.IsHelmInstallEnabled) + assert.True(t, pl.IsKurlInstallEnabled) + assert.True(t, pl.IsHelmAirgapEnabled) +} diff --git a/pkg/types/customer.go b/pkg/types/customer.go index ea0c011db..4f9307798 100644 --- a/pkg/types/customer.go +++ b/pkg/types/customer.go @@ -20,11 +20,13 @@ type Customer struct { IsEmbeddedClusterDownloadEnabled bool `json:"isEmbeddedClusterDownloadEnabled"` IsEmbeddedClusterMultinodeEnabled bool `json:"isEmbeddedClusterMultinodeEnabled"` IsGeoaxisSupported bool `json:"isGeoaxisSupported"` + IsHelmAirgapEnabled bool `json:"isHelmAirgapEnabled"` IsHelmInstallEnabled bool `json:"isHelmInstallEnabled"` IsHelmVMDownloadEnabled bool `json:"isHelmVmDownloadEnabled"` IsIdentityServiceSupported bool `json:"isIdentityServiceSupported"` IsInstallerSupportEnabled bool `json:"isInstallerSupportEnabled"` IsKotsInstallEnabled bool `json:"isKotsInstallEnabled"` + IsKurlInstallEnabled bool `json:"isKurlInstallEnabled"` IsSnapshotSupported bool `json:"isSnapshotSupported"` IsSupportBundleUploadEnabled bool `json:"isSupportBundleUploadEnabled"` IsGitopsSupported bool `json:"isGitopsSupported"` diff --git a/pkg/types/customer_test.go b/pkg/types/customer_test.go index a74a1d31e..3cc677b99 100644 --- a/pkg/types/customer_test.go +++ b/pkg/types/customer_test.go @@ -40,24 +40,96 @@ func TestCustomer_UnmarshalJSON_IsHelmInstallEnabled(t *testing.T) { } } -func TestCustomer_MarshalJSON_IsHelmInstallEnabled(t *testing.T) { +func TestCustomer_UnmarshalJSON_IsKurlInstallEnabled(t *testing.T) { + tests := []struct { + name string + payload string + wantKurl bool + }{ + { + name: "isKurlInstallEnabled true", + payload: `{"id":"cust_abc","isKurlInstallEnabled":true}`, + wantKurl: true, + }, + { + name: "isKurlInstallEnabled false", + payload: `{"id":"cust_abc","isKurlInstallEnabled":false}`, + wantKurl: false, + }, + { + name: "isKurlInstallEnabled absent defaults to false", + payload: `{"id":"cust_abc"}`, + wantKurl: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var c Customer + err := json.Unmarshal([]byte(tt.payload), &c) + require.NoError(t, err) + assert.Equal(t, tt.wantKurl, c.IsKurlInstallEnabled) + }) + } +} + +func TestCustomer_UnmarshalJSON_IsHelmAirgapEnabled(t *testing.T) { + tests := []struct { + name string + payload string + wantAirgap bool + }{ + { + name: "isHelmAirgapEnabled true", + payload: `{"id":"cust_abc","isHelmAirgapEnabled":true}`, + wantAirgap: true, + }, + { + name: "isHelmAirgapEnabled false", + payload: `{"id":"cust_abc","isHelmAirgapEnabled":false}`, + wantAirgap: false, + }, + { + name: "isHelmAirgapEnabled absent defaults to false", + payload: `{"id":"cust_abc"}`, + wantAirgap: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var c Customer + err := json.Unmarshal([]byte(tt.payload), &c) + require.NoError(t, err) + assert.Equal(t, tt.wantAirgap, c.IsHelmAirgapEnabled) + }) + } +} + +func TestCustomer_MarshalJSON_NewFields(t *testing.T) { c := Customer{ ID: "cust_abc", Name: "Test", IsHelmInstallEnabled: true, + IsKurlInstallEnabled: true, + IsHelmAirgapEnabled: true, } data, err := json.Marshal(c) require.NoError(t, err) - assert.Contains(t, string(data), `"isHelmInstallEnabled":true`) + jsonStr := string(data) + assert.Contains(t, jsonStr, `"isHelmInstallEnabled":true`) + assert.Contains(t, jsonStr, `"isKurlInstallEnabled":true`) + assert.Contains(t, jsonStr, `"isHelmAirgapEnabled":true`) } -func TestCustomer_RoundTrip_IsHelmInstallEnabled(t *testing.T) { +func TestCustomer_RoundTrip_AllInstallFields(t *testing.T) { original := Customer{ ID: "cust_abc", Name: "Test", IsHelmInstallEnabled: true, + IsKurlInstallEnabled: true, + IsHelmAirgapEnabled: true, + IsKotsInstallEnabled: true, } data, err := json.Marshal(original) @@ -68,6 +140,9 @@ func TestCustomer_RoundTrip_IsHelmInstallEnabled(t *testing.T) { require.NoError(t, err) assert.Equal(t, original.IsHelmInstallEnabled, restored.IsHelmInstallEnabled) + assert.Equal(t, original.IsKurlInstallEnabled, restored.IsKurlInstallEnabled) + assert.Equal(t, original.IsHelmAirgapEnabled, restored.IsHelmAirgapEnabled) + assert.Equal(t, original.IsKotsInstallEnabled, restored.IsKotsInstallEnabled) } func TestCustomer_UnmarshalJSON_IsHelmVMDownloadEnabled_BackwardsCompat(t *testing.T) { @@ -115,7 +190,6 @@ func TestCustomer_MarshalJSON_IsHelmVMDownloadEnabled_BackwardsCompat(t *testing } func TestCustomer_UnmarshalJSON_BothHelmFields(t *testing.T) { - // Verify both fields can coexist in the same payload payload := `{ "id": "cust_abc", "name": "Test Customer", @@ -147,7 +221,6 @@ func TestCustomer_MarshalJSON_BothHelmFields(t *testing.T) { } func TestCustomer_UnmarshalJSON_FullAPIPayload(t *testing.T) { - // Simulates a realistic Vendor API response payload payload := `{ "id": "cust_abc123", "customId": "custom-id-456", @@ -158,11 +231,13 @@ func TestCustomer_UnmarshalJSON_FullAPIPayload(t *testing.T) { "isEmbeddedClusterDownloadEnabled": true, "isEmbeddedClusterMultinodeEnabled": false, "isGeoaxisSupported": false, + "isHelmAirgapEnabled": true, "isHelmInstallEnabled": true, "isHelmVmDownloadEnabled": false, "isIdentityServiceSupported": false, "isInstallerSupportEnabled": true, "isKotsInstallEnabled": true, + "isKurlInstallEnabled": true, "isSnapshotSupported": true, "isSupportBundleUploadEnabled": true, "isGitopsSupported": false @@ -181,11 +256,13 @@ func TestCustomer_UnmarshalJSON_FullAPIPayload(t *testing.T) { assert.True(t, c.IsEmbeddedClusterDownloadEnabled) assert.False(t, c.IsEmbeddedClusterMultinodeEnabled) assert.False(t, c.IsGeoaxisSupported) + assert.True(t, c.IsHelmAirgapEnabled) assert.True(t, c.IsHelmInstallEnabled) assert.False(t, c.IsHelmVMDownloadEnabled) assert.False(t, c.IsIdentityServiceSupported) assert.True(t, c.IsInstallerSupportEnabled) assert.True(t, c.IsKotsInstallEnabled) + assert.True(t, c.IsKurlInstallEnabled) assert.True(t, c.IsSnapshotSupported) assert.True(t, c.IsSupportBundleUploadEnabled) assert.False(t, c.IsGitopsSupported)