Skip to content
Open
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
377 changes: 377 additions & 0 deletions pkg/asset/installconfig/vsphere/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,377 @@
package vsphere

import (
"context"
"testing"

"github.com/openshift/installer/pkg/types/vsphere"
)

// Test Plan for Story #6: Per-Component Installation Flow (Greenfield)
//
// This test file implements integration tests covering all acceptance criteria:
// - AC1: Installer validates each component's credentials have required privileges
// - AC2: Installer uses installer account to create infrastructure
// - AC3: CCO creates component-specific secrets with appropriate credentials
// - AC4: Machine API uses machine-api credentials
// - AC5: CSI Driver uses csi-driver credentials
// - AC6: Cloud Controller Manager uses cloud-controller credentials
// - AC7: Diagnostics uses diagnostics credentials
// - AC8: vCenter event logs show distinct usernames for each component's actions

// TestPerComponentInstallation_HappyPath tests the complete greenfield installation flow
// with all 5 component accounts properly configured and validated.
//
// Acceptance Criteria Covered: AC1-AC8 (all)
//
// Test Scenario:
// Given: install-config.yaml with componentCredentials containing all 5 accounts
// (installer, machineAPI, csiDriver, cloudController, diagnostics)
// When: Installer runs validation
// Then: All component credentials validated successfully
// Installer credentials identified for infrastructure provisioning
// Per-component mode detected
//
// Expected Behavior:
// - ValidatePerComponentCredentials() succeeds for all components
// - GetInstallerCredentials() returns installer account credentials
// - IsPerComponentMode() returns true
func TestPerComponentInstallation_HappyPath(t *testing.T) {
t.Skip("Implementation pending - Story #6")

ctx := context.Background()

platform := &vsphere.Platform{
VCenters: []vsphere.VCenter{
{
Server: "vcenter.example.com",
},
},
ComponentCredentials: &vsphere.ComponentCredentials{
Installer: &vsphere.AccountCredentials{
Username: "installer@vsphere.local",
Password: "installer-password",
},
MachineAPI: &vsphere.AccountCredentials{
Username: "ocp-machine-api@vsphere.local",
Password: "machine-api-password",
},
CSIDriver: &vsphere.AccountCredentials{
Username: "ocp-csi@vsphere.local",
Password: "csi-password",
},
CloudController: &vsphere.AccountCredentials{
Username: "ocp-ccm@vsphere.local",
Password: "ccm-password",
},
Diagnostics: &vsphere.AccountCredentials{
Username: "ocp-diagnostics@vsphere.local",
Password: "diagnostics-password",
},
},
}

validator := NewPerComponentValidator()

// Test 1: Validate all component credentials
err := validator.ValidatePerComponentCredentials(ctx, platform)
if err != nil {
t.Fatalf("ValidatePerComponentCredentials() failed: %v", err)
}

// Test 2: Verify installer credentials are returned for infrastructure provisioning
username, password, vcenter := validator.GetInstallerCredentials(platform)
if username != "installer@vsphere.local" {
t.Errorf("GetInstallerCredentials() username = %v, want installer@vsphere.local", username)
}
if password != "installer-password" {
t.Errorf("GetInstallerCredentials() password mismatch")
}
if vcenter != "vcenter.example.com" {
t.Errorf("GetInstallerCredentials() vcenter = %v, want vcenter.example.com", vcenter)
}

// Test 3: Verify per-component mode is detected
if !IsPerComponentMode(platform) {
t.Errorf("IsPerComponentMode() = false, want true")
}
}

// TestPerComponentInstallation_InstallerPrivilegeMissing tests validation failure
// when installer credentials lack required privileges.
//
// Acceptance Criteria Covered: AC1 (validation)
//
// Test Scenario:
// Given: Installer account missing Folder.Create privilege
// When: Installer validates credentials
// Then: Validation fails with error "installer missing required privilege: Folder.Create on Datacenter"
//
// Expected Behavior:
// - ValidatePerComponentCredentials() returns error
// - Error message identifies missing privilege and scope
func TestPerComponentInstallation_InstallerPrivilegeMissing(t *testing.T) {
t.Skip("Implementation pending - Story #6")

ctx := context.Background()

// Mock: installer credentials missing Folder.Create privilege
platform := &vsphere.Platform{
VCenters: []vsphere.VCenter{
{
Server: "vcenter.example.com",
},
},
ComponentCredentials: &vsphere.ComponentCredentials{
Installer: &vsphere.AccountCredentials{
Username: "installer-restricted@vsphere.local",
Password: "installer-password",
},
},
}

validator := NewPerComponentValidator()
err := validator.ValidatePerComponentCredentials(ctx, platform)

if err == nil {
t.Fatalf("ValidatePerComponentCredentials() succeeded, want error")
}

expectedErr := "installer credentials validation failed"
if err.Error() != expectedErr {
t.Errorf("ValidatePerComponentCredentials() error = %v, want substring %v", err, expectedErr)
}
}

// TestPerComponentInstallation_MachineAPIPrivilegeMissing tests validation failure
// when Machine API credentials lack required privileges.
//
// Acceptance Criteria Covered: AC1, AC4
//
// Test Scenario:
// Given: Machine API account missing VirtualMachine.Provisioning.Clone privilege
// When: Installer validates credentials
// Then: Validation fails with error "machine-api missing required privilege: VirtualMachine.Provisioning.Clone"
//
// Expected Behavior:
// - ValidatePerComponentCredentials() returns error for machine-api
// - Error message identifies component, privilege, and scope
func TestPerComponentInstallation_MachineAPIPrivilegeMissing(t *testing.T) {
t.Skip("Implementation pending - Story #6")

ctx := context.Background()

platform := &vsphere.Platform{
VCenters: []vsphere.VCenter{
{
Server: "vcenter.example.com",
},
},
ComponentCredentials: &vsphere.ComponentCredentials{
Installer: &vsphere.AccountCredentials{
Username: "installer@vsphere.local",
Password: "installer-password",
},
MachineAPI: &vsphere.AccountCredentials{
Username: "machine-api-restricted@vsphere.local",
Password: "machine-api-password",
},
},
}

validator := NewPerComponentValidator()
err := validator.ValidatePerComponentCredentials(ctx, platform)

if err == nil {
t.Fatalf("ValidatePerComponentCredentials() succeeded, want error")
}

expectedErr := "machine-api credentials validation failed"
if err.Error() != expectedErr {
t.Errorf("ValidatePerComponentCredentials() error = %v, want substring %v", err, expectedErr)
}
}

// TestPerComponentInstallation_CSIDriverPrivilegeMissing tests validation failure
// when CSI Driver credentials lack required privileges.
//
// Acceptance Criteria Covered: AC1, AC5
//
// Test Scenario:
// Given: CSI Driver account missing Datastore.AllocateSpace privilege
// When: Installer validates credentials
// Then: Validation fails with error "csi-driver missing required privilege: Datastore.AllocateSpace on Datastore"
//
// Expected Behavior:
// - ValidatePerComponentCredentials() returns error for csi-driver
// - Error message identifies component and missing privilege on Datastore scope
func TestPerComponentInstallation_CSIDriverPrivilegeMissing(t *testing.T) {
t.Skip("Implementation pending - Story #6")

ctx := context.Background()

platform := &vsphere.Platform{
VCenters: []vsphere.VCenter{
{
Server: "vcenter.example.com",
},
},
ComponentCredentials: &vsphere.ComponentCredentials{
Installer: &vsphere.AccountCredentials{
Username: "installer@vsphere.local",
Password: "installer-password",
},
CSIDriver: &vsphere.AccountCredentials{
Username: "csi-restricted@vsphere.local",
Password: "csi-password",
},
},
}

validator := NewPerComponentValidator()
err := validator.ValidatePerComponentCredentials(ctx, platform)

if err == nil {
t.Fatalf("ValidatePerComponentCredentials() succeeded, want error")
}

expectedErr := "csi-driver credentials validation failed"
if err.Error() != expectedErr {
t.Errorf("ValidatePerComponentCredentials() error = %v, want substring %v", err, expectedErr)
}
}

// TestPerComponentInstallation_ComponentSecretIsolation tests that component-specific
// secrets are created with proper RBAC isolation.
//
// Acceptance Criteria Covered: AC3 (CCO secret creation with isolation)
//
// Test Scenario:
// Given: Per-component installation completes successfully
// When: Administrator inspects cluster secrets
// Then: machine-api-vsphere-credentials contains only machine-api credentials
// vsphere-csi-credentials contains only csi-driver credentials
// vsphere-ccm-credentials contains only cloud-controller credentials
// vsphere-diagnostics-credentials contains only diagnostics credentials
// No component can access another component's credentials
//
// Expected Behavior:
// - Each secret contains exactly 2 keys (username, password)
// - Secrets are in component-specific namespaces
// - RBAC prevents cross-component access
//
// Note: This test verifies the integration with Story #5 (CCO secret generation)
func TestPerComponentInstallation_ComponentSecretIsolation(t *testing.T) {
t.Skip("Implementation pending - Story #6 (requires CCO integration)")

// This test will verify:
// 1. CCO creates secrets in correct namespaces
// 2. Each secret contains only component-specific credentials
// 3. RBAC prevents cross-component access
//
// Expected secrets:
// - openshift-machine-api/machine-api-vsphere-credentials
// - openshift-cluster-csi-drivers/vsphere-csi-credentials
// - openshift-cloud-controller-manager/vsphere-ccm-credentials
// - openshift-config/vsphere-diagnostics-credentials
}

// TestPerComponentInstallation_MachineAPICredentialUsage tests that Machine API
// operator uses machine-api credentials at runtime.
//
// Acceptance Criteria Covered: AC4 (Machine API uses machine-api credentials)
//
// Test Scenario:
// Given: Per-component installation completes
// Machine API operator is running
// When: Machine API creates a new VM
// Then: vCenter event log shows username "ocp-machine-api@vsphere.local"
// VM creation succeeds using machine-api credentials
//
// Expected Behavior:
// - Machine API reads credentials from machine-api-vsphere-credentials secret
// - vCenter API calls authenticated as ocp-machine-api@vsphere.local
// - Audit trail shows distinct machine-api username
func TestPerComponentInstallation_MachineAPICredentialUsage(t *testing.T) {
t.Skip("Implementation pending - Story #6 (requires runtime verification)")

// This test will verify:
// 1. Machine API operator reads correct secret
// 2. VM creation uses machine-api credentials
// 3. vCenter audit log shows machine-api username
}

// TestPerComponentInstallation_CSIDriverCredentialUsage tests that CSI Driver
// uses csi-driver credentials at runtime.
//
// Acceptance Criteria Covered: AC5 (CSI Driver uses csi-driver credentials)
//
// Test Scenario:
// Given: Per-component installation completes
// CSI Driver is running
// When: User creates a PersistentVolumeClaim
// Then: vCenter event log shows username "ocp-csi@vsphere.local"
// PV provisioning succeeds using csi-driver credentials
//
// Expected Behavior:
// - CSI Driver reads credentials from vsphere-csi-credentials secret
// - Datastore operations authenticated as ocp-csi@vsphere.local
// - Audit trail shows distinct csi username
func TestPerComponentInstallation_CSIDriverCredentialUsage(t *testing.T) {
t.Skip("Implementation pending - Story #6 (requires runtime verification)")

// This test will verify:
// 1. CSI Driver reads correct secret
// 2. PV provisioning uses csi-driver credentials
// 3. vCenter audit log shows csi username
}

// TestPerComponentInstallation_CCMCredentialUsage tests that Cloud Controller Manager
// uses cloud-controller credentials at runtime.
//
// Acceptance Criteria Covered: AC6 (CCM uses cloud-controller credentials)
//
// Test Scenario:
// Given: Per-component installation completes
// CCM is running
// When: CCM discovers node information
// Then: vCenter event log shows username "ocp-ccm@vsphere.local"
// Node discovery succeeds using cloud-controller credentials (read-only)
//
// Expected Behavior:
// - CCM reads credentials from vsphere-ccm-credentials secret
// - vCenter read operations authenticated as ocp-ccm@vsphere.local
// - Audit trail shows distinct ccm username with read-only operations
func TestPerComponentInstallation_CCMCredentialUsage(t *testing.T) {
t.Skip("Implementation pending - Story #6 (requires runtime verification)")

// This test will verify:
// 1. CCM reads correct secret
// 2. Node discovery uses cloud-controller credentials
// 3. vCenter audit log shows ccm username (read-only)
}

// TestPerComponentInstallation_DiagnosticsCredentialUsage tests that Diagnostics
// components use diagnostics credentials at runtime.
//
// Acceptance Criteria Covered: AC7 (Diagnostics uses diagnostics credentials)
//
// Test Scenario:
// Given: Per-component installation completes
// Diagnostics components are running
// When: Diagnostics gathers troubleshooting data
// Then: vCenter event log shows username "ocp-diagnostics@vsphere.local"
// Data gathering succeeds using diagnostics credentials (read-only)
//
// Expected Behavior:
// - Diagnostics read credentials from vsphere-diagnostics-credentials secret
// - vCenter read operations authenticated as ocp-diagnostics@vsphere.local
// - Audit trail shows distinct diagnostics username
func TestPerComponentInstallation_DiagnosticsCredentialUsage(t *testing.T) {
t.Skip("Implementation pending - Story #6 (requires runtime verification)")

// This test will verify:
// 1. Diagnostics read correct secret
// 2. Data gathering uses diagnostics credentials
// 3. vCenter audit log shows diagnostics username
}
Loading