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
5 changes: 5 additions & 0 deletions data/data/install.openshift.io_installconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2229,6 +2229,11 @@ spec:
description: Network specifies an existing VPC where the cluster
should be created rather than provisioning a new one.
type: string
networkProjectID:
description: NetworkProjectID is currently unsupported. NetworkProjectID
specifies which project the network and subnets exist in when
they are not in the main ProjectID.
type: string
projectID:
description: ProjectID is the the project that will be used for
the cluster.
Expand Down
26 changes: 24 additions & 2 deletions pkg/asset/installconfig/gcp/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func Validate(client API, ic *types.InstallConfig) error {
}

allErrs = append(allErrs, validateProject(client, ic, field.NewPath("platform").Child("gcp"))...)
allErrs = append(allErrs, validateNetworkProject(client, ic, field.NewPath("platform").Child("gcp"))...)
allErrs = append(allErrs, validateRegion(client, ic, field.NewPath("platform").Child("gcp"))...)
allErrs = append(allErrs, validateNetworks(client, ic, field.NewPath("platform").Child("gcp"))...)
allErrs = append(allErrs, validateInstanceTypes(client, ic)...)
Expand Down Expand Up @@ -162,17 +163,38 @@ func validateProject(client API, ic *types.InstallConfig, fieldPath *field.Path)
return allErrs
}

func validateNetworkProject(client API, ic *types.InstallConfig, fieldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

if ic.GCP.NetworkProjectID != "" {
projects, err := client.GetProjects(context.TODO())
if err != nil {
return append(allErrs, field.InternalError(fieldPath.Child("networkProjectID"), err))
}
if _, found := projects[ic.GCP.NetworkProjectID]; !found {
return append(allErrs, field.Invalid(fieldPath.Child("networkProjectID"), ic.GCP.NetworkProjectID, "invalid project ID"))
}
}

return allErrs
}

// validateNetworks checks that the user-provided VPC is in the project and the provided subnets are valid.
func validateNetworks(client API, ic *types.InstallConfig, fieldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

networkProjectID := ic.GCP.NetworkProjectID
if networkProjectID == "" {
networkProjectID = ic.GCP.ProjectID
}

if ic.GCP.Network != "" {
_, err := client.GetNetwork(context.TODO(), ic.GCP.Network, ic.GCP.ProjectID)
_, err := client.GetNetwork(context.TODO(), ic.GCP.Network, networkProjectID)
if err != nil {
return append(allErrs, field.Invalid(fieldPath.Child("network"), ic.GCP.Network, err.Error()))
}

subnets, err := client.GetSubnetworks(context.TODO(), ic.GCP.Network, ic.GCP.ProjectID, ic.GCP.Region)
subnets, err := client.GetSubnetworks(context.TODO(), ic.GCP.Network, networkProjectID, ic.GCP.Region)
if err != nil {
return append(allErrs, field.Invalid(fieldPath.Child("network"), ic.GCP.Network, "failed to retrieve subnets"))
}
Expand Down
23 changes: 15 additions & 8 deletions pkg/asset/installconfig/gcp/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,15 @@ var (
ic.Platform.GCP.DefaultMachinePlatform.InstanceType = "n1-dne-1"
}

invalidateNetwork = func(ic *types.InstallConfig) { ic.GCP.Network = "invalid-vpc" }
invalidateComputeSubnet = func(ic *types.InstallConfig) { ic.GCP.ComputeSubnet = "invalid-compute-subnet" }
invalidateCPSubnet = func(ic *types.InstallConfig) { ic.GCP.ControlPlaneSubnet = "invalid-cp-subnet" }
invalidateRegion = func(ic *types.InstallConfig) { ic.GCP.Region = invalidRegion }
invalidateProject = func(ic *types.InstallConfig) { ic.GCP.ProjectID = invalidProjectName }
removeVPC = func(ic *types.InstallConfig) { ic.GCP.Network = "" }
removeSubnets = func(ic *types.InstallConfig) { ic.GCP.ComputeSubnet, ic.GCP.ControlPlaneSubnet = "", "" }
invalidClusterName = func(ic *types.InstallConfig) { ic.ObjectMeta.Name = "testgoogletest" }
invalidateNetwork = func(ic *types.InstallConfig) { ic.GCP.Network = "invalid-vpc" }
invalidateComputeSubnet = func(ic *types.InstallConfig) { ic.GCP.ComputeSubnet = "invalid-compute-subnet" }
invalidateCPSubnet = func(ic *types.InstallConfig) { ic.GCP.ControlPlaneSubnet = "invalid-cp-subnet" }
invalidateRegion = func(ic *types.InstallConfig) { ic.GCP.Region = invalidRegion }
invalidateProject = func(ic *types.InstallConfig) { ic.GCP.ProjectID = invalidProjectName }
invalidateNetworkProject = func(ic *types.InstallConfig) { ic.GCP.NetworkProjectID = invalidProjectName }
removeVPC = func(ic *types.InstallConfig) { ic.GCP.Network = "" }
removeSubnets = func(ic *types.InstallConfig) { ic.GCP.ComputeSubnet, ic.GCP.ControlPlaneSubnet = "", "" }
invalidClusterName = func(ic *types.InstallConfig) { ic.ObjectMeta.Name = "testgoogletest" }

machineTypeAPIResult = map[string]*compute.MachineType{
"n1-standard-1": {GuestCpus: 1, MemoryMb: 3840},
Expand Down Expand Up @@ -229,6 +230,12 @@ func TestGCPInstallConfigValidation(t *testing.T) {
expectedError: true,
expectedErrMsg: "platform.gcp.project: Invalid value: \"invalid-project\": invalid project ID",
},
{
name: "Invalid network project ID",
edits: editFunctions{invalidateNetworkProject},
expectedError: true,
expectedErrMsg: "platform.gcp.networkProjectID: Invalid value: \"invalid-project\": invalid project ID",
},
{
name: "Valid Region",
edits: editFunctions{},
Expand Down
6 changes: 6 additions & 0 deletions pkg/types/gcp/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ type Platform struct {
// +optional
Network string `json:"network,omitempty"`

// NetworkProjectID is currently unsupported.
// NetworkProjectID specifies which project the network and subnets exist in when
// they are not in the main ProjectID.
// +optional
NetworkProjectID string `json:"networkProjectID,omitempty"`

// ControlPlaneSubnet is an existing subnet where the control plane will be deployed.
// The value should be the name of the subnet.
// +optional
Expand Down