Skip to content

Commit

Permalink
azurestack: Add a custom rhcos image field for ASH
Browse files Browse the repository at this point in the history
Add a new field to the install config so users can specify an RHCOS image
to use in their ASH environment. This field is required for ASH, and not
allowed to be used for azure.
  • Loading branch information
squidboylan authored and patrickdillon committed Dec 17, 2021
1 parent 44f3657 commit e7a1c8a
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 109 deletions.
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 @@ -1342,6 +1342,11 @@ spec:
- AzureGermanCloud
- AzureStackCloud
type: string
clusterOSImage:
description: ClusterOSImage is the url of a storage blob in the
Azure Stack environment containing an RHCOS VHD. This field
is required for Azure Stack and not applicable to Azure.
type: string
computeSubnet:
description: ComputeSubnet specifies an existing subnet for use
by compute nodes
Expand Down
7 changes: 7 additions & 0 deletions pkg/asset/installconfig/azure/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type API interface {
GetDiskSkus(ctx context.Context, region string) ([]azsku.ResourceSku, error)
GetGroup(ctx context.Context, groupName string) (*azres.Group, error)
ListResourceIDsByGroup(ctx context.Context, groupName string) ([]string, error)
GetStorageEndpointSuffix(ctx context.Context) (string, error)
}

// Client makes calls to the Azure API.
Expand Down Expand Up @@ -94,6 +95,12 @@ func (c *Client) getVirtualNetworksClient(ctx context.Context) (*aznetwork.Virtu
return &vnetsClient, nil
}

// GetStorageEndpointSuffix retrieves the StorageEndpointSuffix from the
// session environment
func (c *Client) GetStorageEndpointSuffix(ctx context.Context) (string, error) {
return c.ssn.Environment.StorageEndpointSuffix, nil
}

// getSubnetsClient sets up a new client to retrieve a subnet
func (c *Client) getSubnetsClient(ctx context.Context) (*aznetwork.SubnetsClient, error) {
subnetClient := aznetwork.NewSubnetsClientWithBaseURI(c.ssn.Environment.ResourceManagerEndpoint, c.ssn.Credentials.SubscriptionID)
Expand Down
118 changes: 67 additions & 51 deletions pkg/asset/installconfig/azure/mock/azureclient_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions pkg/asset/installconfig/azure/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net"
"net/url"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -41,6 +42,13 @@ func Validate(client API, ic *types.InstallConfig) error {
allErrs = append(allErrs, validateNetworks(client, ic.Azure, ic.Networking.MachineNetwork, field.NewPath("platform").Child("azure"))...)
allErrs = append(allErrs, validateRegion(client, field.NewPath("platform").Child("azure").Child("region"), ic.Azure)...)
allErrs = append(allErrs, validateInstanceTypes(client, ic)...)
if ic.Azure.CloudName == aztypes.StackCloud && ic.Azure.ClusterOSImage != "" {
StorageEndpointSuffix, err := client.GetStorageEndpointSuffix(context.TODO())
if err != nil {
return err
}
allErrs = append(allErrs, validateAzureStackClusterOSImage(StorageEndpointSuffix, ic.Azure.ClusterOSImage, field.NewPath("platform").Child("azure"))...)
}
return allErrs.ToAggregate()
}

Expand Down Expand Up @@ -274,6 +282,9 @@ func ValidatePublicDNS(ic *types.InstallConfig, azureDNS *DNSConfig) error {
func ValidateForProvisioning(client API, ic *types.InstallConfig) error {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateResourceGroup(client, field.NewPath("platform").Child("azure"), ic.Azure)...)
if ic.Azure.CloudName == aztypes.StackCloud {
allErrs = append(allErrs, checkAzureStackClusterOSImageSet(ic.Azure.ClusterOSImage, field.NewPath("platform").Child("azure"))...)
}
return allErrs.ToAggregate()
}

Expand Down Expand Up @@ -319,3 +330,24 @@ func validateResourceGroup(client API, fieldPath *field.Path, platform *aztypes.
}
return allErrs
}

func checkAzureStackClusterOSImageSet(ClusterOSImage string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if ClusterOSImage == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("clusterOSImage"), "clusterOSImage must be set when installing on Azure Stack"))
}
return allErrs
}

func validateAzureStackClusterOSImage(StorageEndpointSuffix string, ClusterOSImage string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
imageParsedURL, err := url.Parse(ClusterOSImage)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterOSImage"), ClusterOSImage, fmt.Errorf("clusterOSImage URL is invalid: %w", err).Error()))
}
// If the URL for the image isn't in the Azure Stack environment we can't use it.
if !strings.HasSuffix(imageParsedURL.Host, StorageEndpointSuffix) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterOSImage"), ClusterOSImage, "clusterOSImage must be in the Azure Stack environment"))
}
return allErrs
}
49 changes: 49 additions & 0 deletions pkg/asset/installconfig/azure/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,52 @@ func Test_validateResourceGroup(t *testing.T) {
})
}
}

func TestCheckAzureStackClusterOSImageSet(t *testing.T) {
cases := []struct {
ClusterOSImage string
err string
}{{
ClusterOSImage: "https://storage.test-endpoint.com/rhcos-image",
err: "",
}, {
ClusterOSImage: "",
err: "^platform.azure.clusterOSImage: Required value: clusterOSImage must be set when installing on Azure Stack$",
}}
for _, test := range cases {
t.Run("", func(t *testing.T) {
err := checkAzureStackClusterOSImageSet(test.ClusterOSImage, field.NewPath("platform").Child("azure"))
if test.err != "" {
assert.Regexp(t, test.err, err.ToAggregate())
} else {
assert.NoError(t, err.ToAggregate())
}
})
}
}

func TestValidateAzureStackClusterOSImage(t *testing.T) {
cases := []struct {
StorageEndpointSuffix string
ClusterOSImage string
err string
}{{
StorageEndpointSuffix: "storage.test-endpoint.com",
ClusterOSImage: "https://storage.test-endpoint.com/rhcos-image",
err: "",
}, {
StorageEndpointSuffix: "storage.test-endpoint.com",
ClusterOSImage: "https://storage.not-in-the-cluster.com/rhcos-image",
err: `^platform.azure.clusterOSImage: Invalid value: "https://storage.not-in-the-cluster.com/rhcos-image": clusterOSImage must be in the Azure Stack environment$`,
}}
for _, test := range cases {
t.Run("", func(t *testing.T) {
err := validateAzureStackClusterOSImage(test.StorageEndpointSuffix, test.ClusterOSImage, field.NewPath("platform").Child("azure"))
if test.err != "" {
assert.Regexp(t, test.err, err.ToAggregate())
} else {
assert.NoError(t, err.ToAggregate())
}
})
}
}
Loading

0 comments on commit e7a1c8a

Please sign in to comment.