Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-1.7] update SDKImageToImage func to handle different image types #3469

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
105 changes: 99 additions & 6 deletions azure/converters/vmss.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package converters

import (
"regexp"

"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-11-01/compute"
"github.com/Azure/go-autorest/autorest/to"
"k8s.io/utils/pointer"
Expand All @@ -25,6 +27,13 @@ import (
"sigs.k8s.io/cluster-api-provider-azure/azure"
)

const (
// RegExpStrCommunityGalleryID is a regexp string used for matching community gallery IDs and capturing specific values.
RegExpStrCommunityGalleryID = `/CommunityGalleries/(?P<gallery>.*)/Images/(?P<name>.*)/Versions/(?P<version>.*)`
// RegExpStrComputeGalleryID is a regexp string used for matching compute gallery IDs and capturing specific values.
RegExpStrComputeGalleryID = `/subscriptions/(?P<subID>.*)/resourceGroups/(?P<rg>.*)/providers/Microsoft.Compute/galleries/(?P<gallery>.*)/images/(?P<name>.*)/versions/(?P<version>.*)`
)

// SDKToVMSS converts an Azure SDK VirtualMachineScaleSet to the AzureMachinePool type.
func SDKToVMSS(sdkvmss compute.VirtualMachineScaleSet, sdkinstances []compute.VirtualMachineScaleSetVM) *azure.VMSS {
vmss := &azure.VMSS{
Expand Down Expand Up @@ -150,8 +159,53 @@ func SDKToVMSSVM(sdkInstance compute.VirtualMachineScaleSetVM) *azure.VMSSVM {

// SDKImageToImage converts a SDK image reference to infrav1.Image.
func SDKImageToImage(sdkImageRef *compute.ImageReference, isThirdPartyImage bool) infrav1.Image {
if sdkImageRef.ID != nil {
return IDImageRefToImage(*sdkImageRef.ID)
}
// community gallery image
if sdkImageRef.CommunityGalleryImageID != nil {
return cgImageRefToImage(*sdkImageRef.CommunityGalleryImageID)
}
// shared gallery image
if sdkImageRef.SharedGalleryImageID != nil {
return sgImageRefToImage(*sdkImageRef.SharedGalleryImageID)
}
// marketplace image
return mpImageRefToImage(sdkImageRef, isThirdPartyImage)
}

// GetOrchestrationMode returns the compute.OrchestrationMode for the given infrav1.OrchestrationModeType.
func GetOrchestrationMode(modeType infrav1.OrchestrationModeType) compute.OrchestrationMode {
if modeType == infrav1.FlexibleOrchestrationMode {
return compute.OrchestrationModeFlexible
}
return compute.OrchestrationModeUniform
}

// IDImageRefToImage converts an ID to a infrav1.Image with ComputerGallery set or ID, depending on the structure of the ID.
func IDImageRefToImage(id string) infrav1.Image {
// compute gallery image
if ok, params := getParams(RegExpStrComputeGalleryID, id); ok {
return infrav1.Image{
ComputeGallery: &infrav1.AzureComputeGalleryImage{
Gallery: params["gallery"],
Name: params["name"],
Version: params["version"],
SubscriptionID: pointer.String(params["subID"]),
ResourceGroup: pointer.String(params["rg"]),
},
}
}

// specific image
return infrav1.Image{
ID: &id,
}
}

// mpImageRefToImage converts a marketplace gallery ImageReference to an infrav1.Image.
func mpImageRefToImage(sdkImageRef *compute.ImageReference, isThirdPartyImage bool) infrav1.Image {
return infrav1.Image{
ID: sdkImageRef.ID,
Marketplace: &infrav1.AzureMarketplaceImage{
ImagePlan: infrav1.ImagePlan{
Publisher: to.String(sdkImageRef.Publisher),
Expand All @@ -164,10 +218,49 @@ func SDKImageToImage(sdkImageRef *compute.ImageReference, isThirdPartyImage bool
}
}

// GetOrchestrationMode returns the compute.OrchestrationMode for the given infrav1.OrchestrationModeType.
func GetOrchestrationMode(modeType infrav1.OrchestrationModeType) compute.OrchestrationMode {
if modeType == infrav1.FlexibleOrchestrationMode {
return compute.OrchestrationModeFlexible
// cgImageRefToImage converts a community gallery ImageReference to an infrav1.Image.
func cgImageRefToImage(id string) infrav1.Image {
if ok, params := getParams(RegExpStrCommunityGalleryID, id); ok {
return infrav1.Image{
ComputeGallery: &infrav1.AzureComputeGalleryImage{
Gallery: params["gallery"],
Name: params["name"],
Version: params["version"],
},
}
}
return compute.OrchestrationModeUniform
return infrav1.Image{}
}

// sgImageRefToImage converts a shared gallery ImageReference to an infrav1.Image.
func sgImageRefToImage(id string) infrav1.Image {
if ok, params := getParams(RegExpStrComputeGalleryID, id); ok {
return infrav1.Image{
SharedGallery: &infrav1.AzureSharedGalleryImage{
SubscriptionID: params["subID"],
ResourceGroup: params["rg"],
Gallery: params["gallery"],
Name: params["name"],
Version: params["version"],
},
}
}
return infrav1.Image{}
}

func getParams(regStr, str string) (matched bool, params map[string]string) {
re := regexp.MustCompile(regStr)
match := re.FindAllStringSubmatch(str, -1)

if len(match) == 1 {
params = make(map[string]string)
for i, name := range re.SubexpNames() {
if i > 0 && i <= len(match[0]) {
params[name] = match[0][i]
}
}
matched = true
}

return matched, params
}
72 changes: 63 additions & 9 deletions azure/converters/vmss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ func Test_SDKToVMSSVM(t *testing.T) {
ID: "/subscriptions/foo/resourceGroups/my_resource_group/providers/bar",
Name: "instance-000001",
Image: infrav1.Image{
ID: to.StringPtr("imageID"),
Marketplace: &infrav1.AzureMarketplaceImage{},
ID: to.StringPtr("imageID"),
},
State: "Creating",
},
Expand Down Expand Up @@ -223,28 +222,25 @@ func Test_SDKImageToImage(t *testing.T) {
Image infrav1.Image
}{
{
Name: "minimal image",
Name: "id image",
SDKImageRef: &compute.ImageReference{
ID: to.StringPtr("imageID"),
},
IsThirdParty: false,
Image: infrav1.Image{
ID: to.StringPtr("imageID"),
Marketplace: &infrav1.AzureMarketplaceImage{},
ID: to.StringPtr("imageID"),
},
},
{
Name: "marketplace image",
SDKImageRef: &compute.ImageReference{
ID: to.StringPtr("imageID"),
Publisher: to.StringPtr("publisher"),
Offer: to.StringPtr("offer"),
Sku: to.StringPtr("sku"),
Version: to.StringPtr("version"),
},
IsThirdParty: true,
Image: infrav1.Image{
ID: to.StringPtr("imageID"),
Marketplace: &infrav1.AzureMarketplaceImage{
ImagePlan: infrav1.ImagePlan{
Publisher: "publisher",
Expand All @@ -256,6 +252,65 @@ func Test_SDKImageToImage(t *testing.T) {
},
},
},
{
Name: "shared gallery image",
SDKImageRef: &compute.ImageReference{
SharedGalleryImageID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/galleries/gallery/images/image/versions/version"),
},
Image: infrav1.Image{
SharedGallery: &infrav1.AzureSharedGalleryImage{
SubscriptionID: "subscription",
ResourceGroup: "rg",
Gallery: "gallery",
Name: "image",
Version: "version",
},
},
},
{
Name: "community gallery image",
SDKImageRef: &compute.ImageReference{
CommunityGalleryImageID: to.StringPtr("/CommunityGalleries/gallery/Images/image/Versions/version"),
},
Image: infrav1.Image{
ComputeGallery: &infrav1.AzureComputeGalleryImage{
Gallery: "gallery",
Name: "image",
Version: "version",
},
},
},
{
Name: "compute gallery image",
SDKImageRef: &compute.ImageReference{
ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/galleries/gallery/images/image/versions/version"),
},
Image: infrav1.Image{
ComputeGallery: &infrav1.AzureComputeGalleryImage{
Gallery: "gallery",
Name: "image",
Version: "version",
SubscriptionID: to.StringPtr("subscription"),
ResourceGroup: to.StringPtr("rg"),
},
},
},
{
Name: "compute gallery image not formatted as expected",
SDKImageRef: &compute.ImageReference{
ID: to.StringPtr("/compute/gallery/not/formatted/as/expected"),
},
Image: infrav1.Image{
ID: to.StringPtr("/compute/gallery/not/formatted/as/expected"),
},
},
{
Name: "community gallery image not formatted as expected",
SDKImageRef: &compute.ImageReference{
CommunityGalleryImageID: to.StringPtr("/community/gallery/not/formatted/as/expected"),
},
Image: infrav1.Image{},
},
}

for _, c := range cases {
Expand Down Expand Up @@ -319,8 +374,7 @@ func Test_SDKVMToVMSSVM(t *testing.T) {
Expected: &azure.VMSSVM{
ID: "vmID3",
Image: infrav1.Image{
ID: to.StringPtr("imageID"),
Marketplace: &infrav1.AzureMarketplaceImage{},
ID: to.StringPtr("imageID"),
},
Name: "vmwithstorage",
State: "Creating",
Expand Down
11 changes: 11 additions & 0 deletions azure/scope/machinepoolmachine.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"k8s.io/utils/pointer"
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-azure/azure"
"sigs.k8s.io/cluster-api-provider-azure/azure/converters"
infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-azure/util/futures"
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
Expand Down Expand Up @@ -542,6 +543,16 @@ func (s *MachinePoolMachineScope) hasLatestModelApplied(ctx context.Context) (bo
return false, errors.New("machinepoolscope image must not be nil")
}

// check if image.ID is actually a compute gallery image
if s.instance.Image.ComputeGallery != nil && image.ID != nil {
newImage := converters.IDImageRefToImage(*image.ID)

// this means the ID was a compute gallery image ID
if newImage.ComputeGallery != nil {
return reflect.DeepEqual(s.instance.Image, newImage), nil
}
}

// if the images match, then the VM is of the same model
return reflect.DeepEqual(s.instance.Image, *image), nil
}
Expand Down