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

port to new azure SDK #532

Merged
merged 8 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
345 changes: 172 additions & 173 deletions platform/api/azure/api.go

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions platform/api/azure/gallery-image-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"resources": [
{
"apiVersion": "2022-08-03",
"apiVersion": "2023-07-03",
"location": "[parameters('location')]",
"name": "[parameters('galleries_name')]",
"properties": {
Expand All @@ -54,7 +54,7 @@
"type": "Microsoft.Compute/galleries"
},
{
"apiVersion": "2022-08-03",
"apiVersion": "2023-07-03",
"dependsOn": [
"[resourceId('Microsoft.Compute/galleries', parameters('galleries_name'))]"
],
Expand Down Expand Up @@ -90,7 +90,7 @@
"type": "Microsoft.Compute/galleries/images"
},
{
"apiVersion": "2022-08-03",
"apiVersion": "2023-07-03",
"dependsOn": [
"[resourceId('Microsoft.Compute/galleries/images', parameters('galleries_name'), parameters('image_name'))]",
"[resourceId('Microsoft.Compute/galleries', parameters('galleries_name'))]"
Expand Down
64 changes: 37 additions & 27 deletions platform/api/azure/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,56 +18,66 @@ import (
"context"
"time"

"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources"

"github.com/flatcar/mantle/util"
azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
)

func (a *API) CreateResourceGroup(prefix string) (string, error) {
name := randomName(prefix)
tags := map[string]*string{
"createdAt": util.StrToPtr(time.Now().Format(time.RFC3339)),
"createdBy": util.StrToPtr("mantle"),
"createdAt": to.Ptr(time.Now().Format(time.RFC3339)),
"createdBy": to.Ptr("mantle"),
}
plog.Infof("Creating ResourceGroup %s", name)
_, err := a.rgClient.CreateOrUpdate(context.TODO(), name, resources.Group{
r, err := a.rgClient.CreateOrUpdate(context.TODO(), name, armresources.ResourceGroup{
Location: &a.Opts.Location,
Tags: tags,
})
}, nil)
if err != nil {
return "", err
}
if r.Name == nil {
return name, nil
}

return name, nil
return *r.Name, nil
}

func (a *API) TerminateResourceGroup(name string) error {
resp, err := a.rgClient.CheckExistence(context.TODO(), name)
if err != nil {
return err
}
if resp.StatusCode != 204 {
return nil
{
r, err := a.rgClient.CheckExistence(context.TODO(), name, nil)
if err != nil {
return err
}
if !r.Success {
return nil
}
}

_, err = a.rgClient.Delete(context.TODO(), name)
opts := &armresources.ResourceGroupsClientBeginDeleteOptions{
ForceDeletionTypes: to.Ptr("Microsoft.Compute/virtualMachines,Microsoft.Compute/virtualMachineScaleSets"),
}
poller, err := a.rgClient.BeginDelete(context.TODO(), name, opts)
pollOpts := &azruntime.PollUntilDoneOptions{
Frequency: 15 * time.Second,
}
_, err = poller.PollUntilDone(context.TODO(), pollOpts)
return err
}

func (a *API) ListResourceGroups(filter string) (resources.GroupListResult, error) {
iter, err := a.rgClient.ListComplete(context.TODO(), filter, nil)
if err != nil {
return resources.GroupListResult{}, err
func (a *API) ListResourceGroups(filter string) ([]*armresources.ResourceGroup, error) {
opts := &armresources.ResourceGroupsClientListOptions{
Filter: &filter,
}
var results resources.GroupListResult
arr := make([]resources.Group, 0)
results.Value = &arr

for ; iter.NotDone(); err = iter.NextWithContext(context.TODO()) {
pager := a.rgClient.NewListPager(opts)
var list []*armresources.ResourceGroup
for pager.More() {
page, err := pager.NextPage(context.TODO())
if err != nil {
return resources.GroupListResult{}, err
return nil, err
}
arr = append(arr, iter.Value())
list = append(list, page.Value...)
}
return results, err
return list, nil
}
95 changes: 25 additions & 70 deletions platform/api/azure/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,62 +19,15 @@ import (
"context"
_ "embed"
"encoding/json"
"encoding/xml"
"fmt"
"net/http"
"strings"

"github.com/Azure/azure-sdk-for-go/services/classic/management"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-08-01/compute"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
)

// OSImage struct for https://msdn.microsoft.com/en-us/library/azure/jj157192.aspx call.
//
// XXX: the field ordering is important!
type OSImage struct {
XMLName xml.Name `xml:"http://schemas.microsoft.com/windowsazure OSImage"`
Category string `xml:",omitempty"` // Public || Private || MSDN
Label string `xml:",omitempty"` // Specifies an identifier for the image.
MediaLink string `xml:",omitempty"` // Specifies the location of the vhd file for the image. The storage account where the vhd is located must be associated with the specified subscription.
Name string // Specifies the name of the operating system image. This is the name that is used when creating one or more virtual machines using the image.
OS string // Linux || Windows
Eula string `xml:",omitempty"` // Specifies the End User License Agreement that is associated with the image. The value for this element is a string, but it is recommended that the value be a URL that points to a EULA.
Description string `xml:",omitempty"` // Specifies the description of the image.
ImageFamily string `xml:",omitempty"` // Specifies a value that can be used to group images.
PublishedDate string `xml:",omitempty"` // Specifies the date when the image was added to the image repository.
ShowInGui bool // Specifies whether the image should appear in the image gallery.
PrivacyURI string `xml:"PrivacyUri,omitempty"` // Specifies the URI that points to a document that contains the privacy policy related to the image.
IconURI string `xml:"IconUri,omitempty"` // Specifies the Uri to the icon that is displayed for the image in the Management Portal.
RecommendedVMSize string `xml:",omitempty"` // Specifies the size to use for the virtual machine that is created from the image.
SmallIconURI string `xml:"SmallIconUri,omitempty"` // Specifies the URI to the small icon that is displayed when the image is presented in the Microsoft Azure Management Portal.
Language string `xml:",omitempty"` // Specifies the language of the image.

LogicalSizeInGB float64 `xml:",omitempty"` //Specifies the size, in GB, of the image.
Location string `xml:",omitempty"` // The geo-location in which this media is located. The Location value is derived from storage account that contains the blob in which the media is located. If the storage account belongs to an affinity group the value is NULL.
AffinityGroup string `xml:",omitempty"` // Specifies the affinity in which the media is located. The AffinityGroup value is derived from storage account that contains the blob in which the media is located. If the storage account does not belong to an affinity group the value is NULL and the element is not displayed in the response. This value is NULL for platform images.
IsPremium string `xml:",omitempty"` // Indicates whether the image contains software or associated services that will incur charges above the core price for the virtual machine. For additional details, see the PricingDetailLink element.
PublisherName string `xml:",omitempty"` // The name of the publisher of the image. All user images have a publisher name of User.
PricingDetailLink string `xml:",omitempty"` // Specifies a URL for an image with IsPremium set to true, which contains the pricing details for a virtual machine that is created from the image.
}

var azureImageShareURL = "services/images/%s/share?permission=%s"

func (a *API) ShareImage(image, permission string) error {
url := fmt.Sprintf(azureImageShareURL, image, permission)
op, err := a.client.SendAzurePutRequest(url, "", nil)
if err != nil {
return err
}

return a.client.WaitForOperation(op, nil)
}

func IsConflictError(err error) bool {
azerr, ok := err.(management.AzureError)
return ok && azerr.Code == "ConflictError"
}

//go:embed gallery-image-template.json
var galleryImageTemplate []byte

Expand All @@ -87,6 +40,7 @@ const (
type paramValue struct {
Value string `json:"value"`
}

type galleryParams struct {
GalleriesName paramValue `json:"galleries_name"`
ImageName paramValue `json:"image_name"`
Expand Down Expand Up @@ -137,54 +91,55 @@ func (a *API) CreateGalleryImage(name, resourceGroup, storageAccount, blobURI st
return "", fmt.Errorf("failed to unmarshal gallery params: %w", err)
}

future, err := a.depClient.CreateOrUpdate(context.TODO(),
poller, err := a.depClient.BeginCreateOrUpdate(context.TODO(),
resourceGroup,
deploymentName,
resources.Deployment{
Properties: &resources.DeploymentProperties{
Template: template,
armresources.Deployment{
Properties: &armresources.DeploymentProperties{
Mode: to.Ptr(armresources.DeploymentModeIncremental),
Parameters: params,
Mode: resources.DeploymentModeIncremental,
Template: template,
},
},
nil,
)
if err != nil {
return "", err
}
err = future.WaitForCompletionRef(context.TODO(), a.depClient.Client)
_, err = poller.PollUntilDone(context.TODO(), nil)
if err != nil {
return "", err
}
id := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/galleries/%s/images/%s/versions/%s",
a.Opts.SubscriptionID, resourceGroup, galleryName, name, imageVersion)
a.subID, resourceGroup, galleryName, name, imageVersion)
return id, nil
}

// CreateImage creates a managed image referencing the blob as the disk
func (a *API) CreateImage(name, resourceGroup, blobURI string) (compute.Image, error) {
func (a *API) CreateImage(name, resourceGroup, blobURI string) (armcompute.Image, error) {
plog.Infof("Creating Image %s", name)
future, err := a.imgClient.CreateOrUpdate(context.TODO(), resourceGroup, name, compute.Image{
poller, err := a.imgClient.BeginCreateOrUpdate(context.TODO(), resourceGroup, name, armcompute.Image{
Name: &name,
Location: &a.Opts.Location,
ImageProperties: &compute.ImageProperties{
HyperVGeneration: compute.HyperVGenerationTypes(a.Opts.HyperVGeneration),
StorageProfile: &compute.ImageStorageProfile{
OsDisk: &compute.ImageOSDisk{
OsType: compute.OperatingSystemTypesLinux,
OsState: compute.Generalized,
Properties: &armcompute.ImageProperties{
HyperVGeneration: to.Ptr(armcompute.HyperVGenerationTypes(a.Opts.HyperVGeneration)),
StorageProfile: &armcompute.ImageStorageProfile{
OSDisk: &armcompute.ImageOSDisk{
OSType: to.Ptr(armcompute.OperatingSystemTypesLinux),
OSState: to.Ptr(armcompute.OperatingSystemStateTypesGeneralized),
BlobURI: &blobURI,
},
},
},
})
}, nil)
if err != nil {
return compute.Image{}, err
return armcompute.Image{}, err
}
err = future.WaitForCompletionRef(context.TODO(), a.imgClient.Client)
r, err := poller.PollUntilDone(context.TODO(), nil)
if err != nil {
return compute.Image{}, err
return armcompute.Image{}, err
}
return future.Result(a.imgClient)
return r.Image, nil
}

// resolveImage is used to ensure that either a Version or DiskURI/BlobURL/ImageFile
Expand Down
Loading