constellation/operators/constellation-node-operator/internal/azure/client/scalinggroup.go
Daniel Weiße b35b74b772
Use tags for UID and role parsing (#242)
* Apply tags to all applicable GCP resources

* Move GCP UID and role from VM metadata to labels

* Adjust Azure tags to be in line with GCP and AWS

* Dont rely on resource name to find resources

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2022-10-24 16:58:21 +02:00

123 lines
4.2 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package client
import (
"context"
"fmt"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
)
// GetScalingGroupImage returns the image URI of the scaling group.
func (c *Client) GetScalingGroupImage(ctx context.Context, scalingGroupID string) (string, error) {
_, resourceGroup, scaleSet, err := splitVMSSID(scalingGroupID)
if err != nil {
return "", err
}
res, err := c.scaleSetsAPI.Get(ctx, resourceGroup, scaleSet, nil)
if err != nil {
return "", err
}
if res.Properties == nil ||
res.Properties.VirtualMachineProfile == nil ||
res.Properties.VirtualMachineProfile.StorageProfile == nil ||
res.Properties.VirtualMachineProfile.StorageProfile.ImageReference == nil ||
res.Properties.VirtualMachineProfile.StorageProfile.ImageReference.ID == nil && res.Properties.VirtualMachineProfile.StorageProfile.ImageReference.CommunityGalleryImageID == nil {
return "", fmt.Errorf("scalet set %q does not have valid image reference", scalingGroupID)
}
if res.Properties.VirtualMachineProfile.StorageProfile.ImageReference.ID != nil {
return *res.Properties.VirtualMachineProfile.StorageProfile.ImageReference.ID, nil
}
return *res.Properties.VirtualMachineProfile.StorageProfile.ImageReference.CommunityGalleryImageID, nil
}
// SetScalingGroupImage sets the image URI of the scaling group.
func (c *Client) SetScalingGroupImage(ctx context.Context, scalingGroupID, imageURI string) error {
_, resourceGroup, scaleSet, err := splitVMSSID(scalingGroupID)
if err != nil {
return err
}
poller, err := c.scaleSetsAPI.BeginUpdate(ctx, resourceGroup, scaleSet, armcompute.VirtualMachineScaleSetUpdate{
Properties: &armcompute.VirtualMachineScaleSetUpdateProperties{
VirtualMachineProfile: &armcompute.VirtualMachineScaleSetUpdateVMProfile{
StorageProfile: &armcompute.VirtualMachineScaleSetUpdateStorageProfile{
ImageReference: imageReferenceFromImage(imageURI),
},
},
},
}, nil)
if err != nil {
return err
}
if _, err := poller.PollUntilDone(ctx, nil); err != nil {
return err
}
return nil
}
// GetScalingGroupName retrieves the name of a scaling group, as expected by Kubernetes.
// This keeps the casing of the original name, but Kubernetes requires the name to be lowercase,
// so use strings.ToLower() on the result if using the name in a Kubernetes context.
func (c *Client) GetScalingGroupName(scalingGroupID string) (string, error) {
_, _, scaleSet, err := splitVMSSID(scalingGroupID)
if err != nil {
return "", fmt.Errorf("getting scaling group name: %w", err)
}
return scaleSet, nil
}
// GetScalingGroupName retrieves the name of a scaling group as needed by the cluster-autoscaler.
func (c *Client) GetAutoscalingGroupName(scalingGroupID string) (string, error) {
return c.GetScalingGroupName(scalingGroupID)
}
// ListScalingGroups retrieves a list of scaling groups for the cluster.
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
pager := c.scaleSetsAPI.NewListPager(c.config.ResourceGroup, nil)
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
return nil, nil, fmt.Errorf("paging scale sets: %w", err)
}
for _, scaleSet := range page.Value {
if scaleSet == nil || scaleSet.ID == nil {
continue
}
if scaleSet.Tags == nil || scaleSet.Tags["constellation-uid"] == nil || *scaleSet.Tags["constellation-uid"] != uid {
continue
}
if err != nil {
return nil, nil, fmt.Errorf("getting scaling group name: %w", err)
}
switch *scaleSet.Tags["constellation-role"] {
case "control-plane", "controlplane":
controlPlaneGroupIDs = append(controlPlaneGroupIDs, *scaleSet.ID)
case "worker":
workerGroupIDs = append(workerGroupIDs, *scaleSet.ID)
}
}
}
return controlPlaneGroupIDs, workerGroupIDs, nil
}
func imageReferenceFromImage(img string) *armcompute.ImageReference {
ref := &armcompute.ImageReference{}
if strings.HasPrefix(img, "/CommunityGalleries") {
ref.CommunityGalleryImageID = to.Ptr(img)
} else {
ref.ID = to.Ptr(img)
}
return ref
}