From b28a38dc575097dc54c195fe1eca7a12a11c981b Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 27 Sep 2023 12:51:10 +0000 Subject: [PATCH 1/5] kola: azure: Switch default publisher/offer to Flatcar Signed-off-by: Jeremi Piotrowski --- cmd/kola/options.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/kola/options.go b/cmd/kola/options.go index bd44c2e34..5c4b84a48 100644 --- a/cmd/kola/options.go +++ b/cmd/kola/options.go @@ -112,8 +112,8 @@ func init() { sv(&kola.AzureOptions.BlobURL, "azure-blob-url", "", "Azure source page blob to be copied from a public/SAS URL, recommended way (from \"plume pre-release\" or \"ore azure upload-blob-arm\")") sv(&kola.AzureOptions.ImageFile, "azure-image-file", "", "Azure image file (local image to upload in the temporary kola resource group)") sv(&kola.AzureOptions.DiskURI, "azure-disk-uri", "", "Azure disk uri (custom images)") - sv(&kola.AzureOptions.Publisher, "azure-publisher", "CoreOS", "Azure image publisher (default \"CoreOS\"") - sv(&kola.AzureOptions.Offer, "azure-offer", "CoreOS", "Azure image offer (default \"CoreOS\"") + sv(&kola.AzureOptions.Publisher, "azure-publisher", "kinvolk", "Azure image publisher (default \"kinvolk\"") + sv(&kola.AzureOptions.Offer, "azure-offer", "flatcar-container-linux-free", "Azure image offer (default \"flatcar-container-linux-free\"") sv(&kola.AzureOptions.Sku, "azure-sku", "alpha", "Azure image sku/channel (default \"alpha\"") sv(&kola.AzureOptions.Version, "azure-version", "", "Azure image version") sv(&kola.AzureOptions.Location, "azure-location", "westus", "Azure location (default \"westus\"") From c891de87c4fdb0d4f4a859653f92081235adf3a2 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 27 Sep 2023 12:55:25 +0000 Subject: [PATCH 2/5] kola: azure: Implement support for managed identities Add support for using a managed identity to authenticate with Azure. This normally requires passing a subscription id through the environment but if the identity only has access to a single subscription we can perform a lookup automatically. Signed-off-by: Jeremi Piotrowski --- auth/azure.go | 30 ++++++- cmd/kola/options.go | 1 + go.mod | 2 +- platform/api/azure/api.go | 151 +++++++++++++++++++++++++--------- platform/api/azure/options.go | 1 + vendor/modules.txt | 1 + 6 files changed, 144 insertions(+), 42 deletions(-) diff --git a/auth/azure.go b/auth/azure.go index fe5963dc3..96f263298 100644 --- a/auth/azure.go +++ b/auth/azure.go @@ -124,21 +124,45 @@ func (ap *AzureProfile) AsOptions() []Options { return o } +type SubFilter struct { + name string + id string +} + +func FilterByName(name string) SubFilter { + return SubFilter{name: name} +} +func FilterByID(id string) SubFilter { + return SubFilter{id: id} +} +func (s *SubFilter) IsEmpty() bool { + return s.name == "" && s.id == "" +} +func (s *SubFilter) Matches(opts *Options) bool { + if s.name != "" && opts.SubscriptionName == s.name { + return true + } + if s.id != "" && opts.SubscriptionID == s.id { + return true + } + return false +} + // SubscriptionOptions returns the name subscription in the Azure profile as a Options struct. // If the subscription name is "", the first subscription is returned. // If there are no subscriptions or the named subscription is not found, SubscriptionOptions returns nil. -func (ap *AzureProfile) SubscriptionOptions(name string) *Options { +func (ap *AzureProfile) SubscriptionOptions(filter SubFilter) *Options { opts := ap.AsOptions() if len(opts) == 0 { return nil } - if name == "" { + if filter.IsEmpty() { return &opts[0] } else { for _, o := range ap.AsOptions() { - if o.SubscriptionName == name { + if filter.Matches(&o) { return &o } } diff --git a/cmd/kola/options.go b/cmd/kola/options.go index 5c4b84a48..ee949be35 100644 --- a/cmd/kola/options.go +++ b/cmd/kola/options.go @@ -122,6 +122,7 @@ func init() { sv(&kola.AzureOptions.VnetSubnetName, "azure-vnet-subnet-name", "", "Use a pre-existing virtual network for created instances. Specify as vnet-name/subnet-name. If subnet name is omitted then \"default\" is assumed") bv(&kola.AzureOptions.UseGallery, "azure-use-gallery", false, "Use gallery image instead of managed image") bv(&kola.AzureOptions.UsePrivateIPs, "azure-use-private-ips", false, "Assume nodes are reachable using private IP addresses") + bv(&kola.AzureOptions.UseIdentity, "azure-identity", false, "Use VM managed identity for authentication (default false)") // do-specific options sv(&kola.DOOptions.ConfigPath, "do-config-file", "", "DigitalOcean config file (default \"~/"+auth.DOConfigPath+"\")") diff --git a/go.mod b/go.mod index 623fa070d..ab70ea647 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( cloud.google.com/go/storage v1.27.0 github.com/Azure/azure-sdk-for-go v56.2.0+incompatible + github.com/Azure/go-autorest/autorest v0.11.19 github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 github.com/Microsoft/azure-vhd-utils v0.0.0-20210818134022-97083698b75f github.com/aws/aws-sdk-go v1.44.46 @@ -54,7 +55,6 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v0.8.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.19 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.14 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect diff --git a/platform/api/azure/api.go b/platform/api/azure/api.go index 23253988f..fecddbc75 100644 --- a/platform/api/azure/api.go +++ b/platform/api/azure/api.go @@ -15,6 +15,7 @@ package azure import ( + "context" "fmt" "math/rand" "os" @@ -27,8 +28,10 @@ import ( "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-03-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-02-01/network" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources" + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions" armStorage "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-01-01/storage" "github.com/Azure/azure-sdk-for-go/storage" + "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/azure/auth" "github.com/coreos/pkg/capnslog" @@ -58,35 +61,17 @@ type Network struct { subnet network.Subnet } -// New creates a new Azure client. If no publish settings file is provided or -// can't be parsed, an anonymous client is created. -func New(opts *Options) (*API, error) { - conf := management.DefaultConfig() - conf.APIVersion = "2015-04-01" - - if opts.ManagementURL != "" { - conf.ManagementURL = opts.ManagementURL - } - - if opts.StorageEndpointSuffix == "" { - opts.StorageEndpointSuffix = storage.DefaultBaseURL - } - +func setOptsFromProfile(opts *Options) error { profiles, err := internalAuth.ReadAzureProfile(opts.AzureProfile) if err != nil { - return nil, fmt.Errorf("couldn't read Azure profile: %v", err) - } - - subOpts := profiles.SubscriptionOptions(opts.AzureSubscription) - if subOpts == nil { - return nil, fmt.Errorf("Azure subscription named %q doesn't exist in %q", opts.AzureSubscription, opts.AzureProfile) + return fmt.Errorf("couldn't read Azure profile: %v", err) } if os.Getenv("AZURE_AUTH_LOCATION") == "" { if opts.AzureAuthLocation == "" { user, err := user.Current() if err != nil { - return nil, err + return err } opts.AzureAuthLocation = filepath.Join(user.HomeDir, internalAuth.AzureAuthPath) } @@ -94,6 +79,20 @@ func New(opts *Options) (*API, error) { os.Setenv("AZURE_AUTH_LOCATION", opts.AzureAuthLocation) } + var subOpts *internalAuth.Options + if opts.AzureSubscription == "" { + settings, err := auth.GetSettingsFromFile() + if err != nil { + return err + } + subOpts = profiles.SubscriptionOptions(internalAuth.FilterByID(settings.GetSubscriptionID())) + } else { + subOpts = profiles.SubscriptionOptions(internalAuth.FilterByName(opts.AzureSubscription)) + } + if subOpts == nil { + return fmt.Errorf("Azure subscription named %q doesn't exist in %q", opts.AzureSubscription, opts.AzureProfile) + } + if opts.SubscriptionID == "" { opts.SubscriptionID = subOpts.SubscriptionID } @@ -114,6 +113,37 @@ func New(opts *Options) (*API, error) { opts.StorageEndpointSuffix = subOpts.StorageEndpointSuffix } + return nil +} + +// New creates a new Azure client. If no publish settings file is provided or +// can't be parsed, an anonymous client is created. +func New(opts *Options) (*API, error) { + var err error + conf := management.DefaultConfig() + conf.APIVersion = "2015-04-01" + + if opts.ManagementURL != "" { + conf.ManagementURL = opts.ManagementURL + } + + if opts.StorageEndpointSuffix == "" { + opts.StorageEndpointSuffix = storage.DefaultBaseURL + } + + if !opts.UseIdentity { + err = setOptsFromProfile(opts) + if err != nil { + return nil, fmt.Errorf("failed to get options from azure profile: %w", err) + } + } else { + subid, err := msiGetSubscriptionID() + if err != nil { + return nil, fmt.Errorf("failed to query subscription id: %w", err) + } + opts.SubscriptionID = subid + } + var client management.Client if opts.ManagementCertificate != nil { client, err = management.NewClientFromConfig(opts.SubscriptionID, opts.ManagementCertificate, conf) @@ -137,50 +167,95 @@ func New(opts *Options) (*API, error) { return api, nil } -func (a *API) SetupClients() error { - auther, err := auth.NewAuthorizerFromFile(resources.DefaultBaseURI) +func (a *API) newAuthorizer(baseURI string) (autorest.Authorizer, error) { + if !a.Opts.UseIdentity { + return auth.NewAuthorizerFromFile(baseURI) + } + settings, err := auth.GetSettingsFromEnvironment() if err != nil { - return err + return nil, err } - settings, err := auth.GetSettingsFromFile() + return settings.GetMSI().Authorizer() +} + +func msiGetSubscriptionID() (string, error) { + settings, err := auth.GetSettingsFromEnvironment() + if err != nil { + return "", err + } + subid := settings.GetSubscriptionID() + if subid != "" { + return subid, nil + } + auther, err := settings.GetMSI().Authorizer() + if err != nil { + return "", err + } + client := subscriptions.NewClient() + client.Authorizer = auther + iter, err := client.ListComplete(context.Background()) + if err != nil { + return "", fmt.Errorf("failed to list subscriptions: %w", err) + } + for sub := iter.Value(); iter.NotDone(); iter.Next() { + // this should never happen + if sub.SubscriptionID == nil { + continue + } + if subid != "" { + return "", fmt.Errorf("multiple subscriptions found; pass one explicitly using the %s environment variable", auth.SubscriptionID) + } + subid = *sub.SubscriptionID + } + if subid == "" { + return "", fmt.Errorf("no subscriptions found; pass one explicitly using the %s environment variable", auth.SubscriptionID) + } + plog.Infof("Using subscription %s", subid) + return subid, nil +} + +func (a *API) SetupClients() error { + auther, err := a.newAuthorizer(resources.DefaultBaseURI) if err != nil { return err } - a.rgClient = resources.NewGroupsClient(settings.GetSubscriptionID()) + subid := a.Opts.SubscriptionID + + a.rgClient = resources.NewGroupsClient(subid) a.rgClient.Authorizer = auther - a.depClient = resources.NewDeploymentsClient(settings.GetSubscriptionID()) + a.depClient = resources.NewDeploymentsClient(subid) a.depClient.Authorizer = auther - auther, err = auth.NewAuthorizerFromFile(compute.DefaultBaseURI) + auther, err = a.newAuthorizer(compute.DefaultBaseURI) if err != nil { return err } - a.imgClient = compute.NewImagesClient(settings.GetSubscriptionID()) + a.imgClient = compute.NewImagesClient(subid) a.imgClient.Authorizer = auther - a.compClient = compute.NewVirtualMachinesClient(settings.GetSubscriptionID()) + a.compClient = compute.NewVirtualMachinesClient(subid) a.compClient.Authorizer = auther - a.vmImgClient = compute.NewVirtualMachineImagesClient(settings.GetSubscriptionID()) + a.vmImgClient = compute.NewVirtualMachineImagesClient(subid) a.vmImgClient.Authorizer = auther - auther, err = auth.NewAuthorizerFromFile(network.DefaultBaseURI) + auther, err = a.newAuthorizer(network.DefaultBaseURI) if err != nil { return err } - a.netClient = network.NewVirtualNetworksClient(settings.GetSubscriptionID()) + a.netClient = network.NewVirtualNetworksClient(subid) a.netClient.Authorizer = auther - a.subClient = network.NewSubnetsClient(settings.GetSubscriptionID()) + a.subClient = network.NewSubnetsClient(subid) a.subClient.Authorizer = auther - a.ipClient = network.NewPublicIPAddressesClient(settings.GetSubscriptionID()) + a.ipClient = network.NewPublicIPAddressesClient(subid) a.ipClient.Authorizer = auther - a.intClient = network.NewInterfacesClient(settings.GetSubscriptionID()) + a.intClient = network.NewInterfacesClient(subid) a.intClient.Authorizer = auther - auther, err = auth.NewAuthorizerFromFile(armStorage.DefaultBaseURI) + auther, err = a.newAuthorizer(armStorage.DefaultBaseURI) if err != nil { return err } - a.accClient = armStorage.NewAccountsClient(settings.GetSubscriptionID()) + a.accClient = armStorage.NewAccountsClient(subid) a.accClient.Authorizer = auther return nil diff --git a/platform/api/azure/options.go b/platform/api/azure/options.go index 0906bdf87..b11a020b5 100644 --- a/platform/api/azure/options.go +++ b/platform/api/azure/options.go @@ -37,6 +37,7 @@ type Options struct { HyperVGeneration string VnetSubnetName string UseGallery bool + UseIdentity bool UsePrivateIPs bool SubscriptionName string diff --git a/vendor/modules.txt b/vendor/modules.txt index 87be2cf7c..3fb304a26 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -28,6 +28,7 @@ github.com/Azure/azure-sdk-for-go/services/classic/management/storageservice github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2021-03-01/compute github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-02-01/network github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources +github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-01-01/storage github.com/Azure/azure-sdk-for-go/storage github.com/Azure/azure-sdk-for-go/version From e885cd3c48276a81bbb82844e648d90145ced9d8 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 27 Sep 2023 12:56:29 +0000 Subject: [PATCH 3/5] vendor: Update after adding new imports to azure platform Signed-off-by: Jeremi Piotrowski --- .../2021-01-01/subscriptions/CHANGELOG.md | 12 + .../mgmt/2021-01-01/subscriptions/_meta.json | 11 + .../mgmt/2021-01-01/subscriptions/client.go | 130 +++ .../mgmt/2021-01-01/subscriptions/enums.go | 124 +++ .../mgmt/2021-01-01/subscriptions/models.go | 755 ++++++++++++++++++ .../2021-01-01/subscriptions/operations.go | 142 ++++ .../2021-01-01/subscriptions/subscriptions.go | 293 +++++++ .../mgmt/2021-01-01/subscriptions/tenants.go | 142 ++++ .../mgmt/2021-01-01/subscriptions/version.go | 19 + 9 files changed, 1628 insertions(+) create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/CHANGELOG.md create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/_meta.json create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/client.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/enums.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/models.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/operations.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/subscriptions.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/tenants.go create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/version.go diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/CHANGELOG.md new file mode 100644 index 000000000..2fd699d40 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change History + +## Additive Changes + +### New Funcs + +1. ErrorAdditionalInfo.MarshalJSON() ([]byte, error) +1. ErrorResponse.MarshalJSON() ([]byte, error) +1. ManagedByTenant.MarshalJSON() ([]byte, error) +1. PairedRegion.MarshalJSON() ([]byte, error) +1. Policies.MarshalJSON() ([]byte, error) +1. TenantIDDescription.MarshalJSON() ([]byte, error) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/_meta.json b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/_meta.json new file mode 100644 index 000000000..eb2bb5556 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/_meta.json @@ -0,0 +1,11 @@ +{ + "commit": "225e4a77704766b9b6529c40c2677b22b58da9b9", + "readme": "/_/azure-rest-api-specs/specification/resources/resource-manager/readme.md", + "tag": "package-subscriptions-2021-01", + "use": "@microsoft.azure/autorest.go@2.1.183", + "repository_url": "https://github.com/Azure/azure-rest-api-specs.git", + "autorest_command": "autorest --use=@microsoft.azure/autorest.go@2.1.183 --tag=package-subscriptions-2021-01 --go-sdk-folder=/_/azure-sdk-for-go --go --verbose --use-onever --version=V2 --go.license-header=MICROSOFT_MIT_NO_VERSION --enum-prefix /_/azure-rest-api-specs/specification/resources/resource-manager/readme.md", + "additional_properties": { + "additional_options": "--go --verbose --use-onever --version=V2 --go.license-header=MICROSOFT_MIT_NO_VERSION --enum-prefix" + } +} \ No newline at end of file diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/client.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/client.go new file mode 100644 index 000000000..56f57259f --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/client.go @@ -0,0 +1,130 @@ +// Package subscriptions implements the Azure ARM Subscriptions service API version 2021-01-01. +// +// All resource groups and resources exist within subscriptions. These operation enable you get information about your +// subscriptions and tenants. A tenant is a dedicated instance of Azure Active Directory (Azure AD) for your +// organization. +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/autorest/validation" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +const ( + // DefaultBaseURI is the default URI used for the service Subscriptions + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Subscriptions. +type BaseClient struct { + autorest.Client + BaseURI string +} + +// New creates an instance of the BaseClient client. +func New() BaseClient { + return NewWithBaseURI(DefaultBaseURI) +} + +// NewWithBaseURI creates an instance of the BaseClient client using a custom endpoint. Use this when interacting with +// an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewWithBaseURI(baseURI string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + } +} + +// CheckResourceName a resource name is valid if it is not a reserved word, does not contains a reserved word and does +// not start with a reserved word +// Parameters: +// resourceNameDefinition - resource object with values for resource name and resource type +func (client BaseClient) CheckResourceName(ctx context.Context, resourceNameDefinition *ResourceName) (result CheckResourceNameResult, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/BaseClient.CheckResourceName") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceNameDefinition, + Constraints: []validation.Constraint{{Target: "resourceNameDefinition", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "resourceNameDefinition.Name", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "resourceNameDefinition.Type", Name: validation.Null, Rule: true, Chain: nil}, + }}}}}); err != nil { + return result, validation.NewError("subscriptions.BaseClient", "CheckResourceName", err.Error()) + } + + req, err := client.CheckResourceNamePreparer(ctx, resourceNameDefinition) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.BaseClient", "CheckResourceName", nil, "Failure preparing request") + return + } + + resp, err := client.CheckResourceNameSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.BaseClient", "CheckResourceName", resp, "Failure sending request") + return + } + + result, err = client.CheckResourceNameResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.BaseClient", "CheckResourceName", resp, "Failure responding to request") + return + } + + return +} + +// CheckResourceNamePreparer prepares the CheckResourceName request. +func (client BaseClient) CheckResourceNamePreparer(ctx context.Context, resourceNameDefinition *ResourceName) (*http.Request, error) { + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/providers/Microsoft.Resources/checkResourceName"), + autorest.WithQueryParameters(queryParameters)) + if resourceNameDefinition != nil { + preparer = autorest.DecoratePreparer(preparer, + autorest.WithJSON(resourceNameDefinition)) + } + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// CheckResourceNameSender sends the CheckResourceName request. The method will close the +// http.Response Body if it receives an error. +func (client BaseClient) CheckResourceNameSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// CheckResourceNameResponder handles the response to the CheckResourceName request. The method always +// closes the http.Response Body. +func (client BaseClient) CheckResourceNameResponder(resp *http.Response) (result CheckResourceNameResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/enums.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/enums.go new file mode 100644 index 000000000..02be36d7b --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/enums.go @@ -0,0 +1,124 @@ +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// LocationType enumerates the values for location type. +type LocationType string + +const ( + // LocationTypeEdgeZone ... + LocationTypeEdgeZone LocationType = "EdgeZone" + // LocationTypeRegion ... + LocationTypeRegion LocationType = "Region" +) + +// PossibleLocationTypeValues returns an array of possible values for the LocationType const type. +func PossibleLocationTypeValues() []LocationType { + return []LocationType{LocationTypeEdgeZone, LocationTypeRegion} +} + +// RegionCategory enumerates the values for region category. +type RegionCategory string + +const ( + // RegionCategoryExtended ... + RegionCategoryExtended RegionCategory = "Extended" + // RegionCategoryOther ... + RegionCategoryOther RegionCategory = "Other" + // RegionCategoryRecommended ... + RegionCategoryRecommended RegionCategory = "Recommended" +) + +// PossibleRegionCategoryValues returns an array of possible values for the RegionCategory const type. +func PossibleRegionCategoryValues() []RegionCategory { + return []RegionCategory{RegionCategoryExtended, RegionCategoryOther, RegionCategoryRecommended} +} + +// RegionType enumerates the values for region type. +type RegionType string + +const ( + // RegionTypeLogical ... + RegionTypeLogical RegionType = "Logical" + // RegionTypePhysical ... + RegionTypePhysical RegionType = "Physical" +) + +// PossibleRegionTypeValues returns an array of possible values for the RegionType const type. +func PossibleRegionTypeValues() []RegionType { + return []RegionType{RegionTypeLogical, RegionTypePhysical} +} + +// ResourceNameStatus enumerates the values for resource name status. +type ResourceNameStatus string + +const ( + // ResourceNameStatusAllowed ... + ResourceNameStatusAllowed ResourceNameStatus = "Allowed" + // ResourceNameStatusReserved ... + ResourceNameStatusReserved ResourceNameStatus = "Reserved" +) + +// PossibleResourceNameStatusValues returns an array of possible values for the ResourceNameStatus const type. +func PossibleResourceNameStatusValues() []ResourceNameStatus { + return []ResourceNameStatus{ResourceNameStatusAllowed, ResourceNameStatusReserved} +} + +// SpendingLimit enumerates the values for spending limit. +type SpendingLimit string + +const ( + // SpendingLimitCurrentPeriodOff ... + SpendingLimitCurrentPeriodOff SpendingLimit = "CurrentPeriodOff" + // SpendingLimitOff ... + SpendingLimitOff SpendingLimit = "Off" + // SpendingLimitOn ... + SpendingLimitOn SpendingLimit = "On" +) + +// PossibleSpendingLimitValues returns an array of possible values for the SpendingLimit const type. +func PossibleSpendingLimitValues() []SpendingLimit { + return []SpendingLimit{SpendingLimitCurrentPeriodOff, SpendingLimitOff, SpendingLimitOn} +} + +// State enumerates the values for state. +type State string + +const ( + // StateDeleted ... + StateDeleted State = "Deleted" + // StateDisabled ... + StateDisabled State = "Disabled" + // StateEnabled ... + StateEnabled State = "Enabled" + // StatePastDue ... + StatePastDue State = "PastDue" + // StateWarned ... + StateWarned State = "Warned" +) + +// PossibleStateValues returns an array of possible values for the State const type. +func PossibleStateValues() []State { + return []State{StateDeleted, StateDisabled, StateEnabled, StatePastDue, StateWarned} +} + +// TenantCategory enumerates the values for tenant category. +type TenantCategory string + +const ( + // TenantCategoryHome ... + TenantCategoryHome TenantCategory = "Home" + // TenantCategoryManagedBy ... + TenantCategoryManagedBy TenantCategory = "ManagedBy" + // TenantCategoryProjectedBy ... + TenantCategoryProjectedBy TenantCategory = "ProjectedBy" +) + +// PossibleTenantCategoryValues returns an array of possible values for the TenantCategory const type. +func PossibleTenantCategoryValues() []TenantCategory { + return []TenantCategory{TenantCategoryHome, TenantCategoryManagedBy, TenantCategoryProjectedBy} +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/models.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/models.go new file mode 100644 index 000000000..b4322705c --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/models.go @@ -0,0 +1,755 @@ +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "encoding/json" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/to" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// The package's fully qualified name. +const fqdn = "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions" + +// CheckResourceNameResult resource Name valid if not a reserved word, does not contain a reserved word and +// does not start with a reserved word +type CheckResourceNameResult struct { + autorest.Response `json:"-"` + // Name - Name of Resource + Name *string `json:"name,omitempty"` + // Type - Type of Resource + Type *string `json:"type,omitempty"` + // Status - Is the resource name Allowed or Reserved. Possible values include: 'ResourceNameStatusAllowed', 'ResourceNameStatusReserved' + Status ResourceNameStatus `json:"status,omitempty"` +} + +// CloudError an error response for a resource management request. +type CloudError struct { + Error *ErrorResponse `json:"error,omitempty"` +} + +// ErrorAdditionalInfo the resource management error additional info. +type ErrorAdditionalInfo struct { + // Type - READ-ONLY; The additional info type. + Type *string `json:"type,omitempty"` + // Info - READ-ONLY; The additional info. + Info interface{} `json:"info,omitempty"` +} + +// MarshalJSON is the custom marshaler for ErrorAdditionalInfo. +func (eai ErrorAdditionalInfo) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// ErrorResponse common error response for all Azure Resource Manager APIs to return error details for +// failed operations. (This also follows the OData error response format.) +type ErrorResponse struct { + // Code - READ-ONLY; The error code. + Code *string `json:"code,omitempty"` + // Message - READ-ONLY; The error message. + Message *string `json:"message,omitempty"` + // Target - READ-ONLY; The error target. + Target *string `json:"target,omitempty"` + // Details - READ-ONLY; The error details. + Details *[]ErrorResponse `json:"details,omitempty"` + // AdditionalInfo - READ-ONLY; The error additional info. + AdditionalInfo *[]ErrorAdditionalInfo `json:"additionalInfo,omitempty"` +} + +// MarshalJSON is the custom marshaler for ErrorResponse. +func (er ErrorResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// ListResult subscription list operation response. +type ListResult struct { + autorest.Response `json:"-"` + // Value - An array of subscriptions. + Value *[]Subscription `json:"value,omitempty"` + // NextLink - The URL to get the next set of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// ListResultIterator provides access to a complete listing of Subscription values. +type ListResultIterator struct { + i int + page ListResultPage +} + +// NextWithContext advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +func (iter *ListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/ListResultIterator.NextWithContext") + defer func() { + sc := -1 + if iter.Response().Response.Response != nil { + sc = iter.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + iter.i++ + if iter.i < len(iter.page.Values()) { + return nil + } + err = iter.page.NextWithContext(ctx) + if err != nil { + iter.i-- + return err + } + iter.i = 0 + return nil +} + +// Next advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (iter *ListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter ListResultIterator) NotDone() bool { + return iter.page.NotDone() && iter.i < len(iter.page.Values()) +} + +// Response returns the raw server response from the last page request. +func (iter ListResultIterator) Response() ListResult { + return iter.page.Response() +} + +// Value returns the current value or a zero-initialized value if the +// iterator has advanced beyond the end of the collection. +func (iter ListResultIterator) Value() Subscription { + if !iter.page.NotDone() { + return Subscription{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the ListResultIterator type. +func NewListResultIterator(page ListResultPage) ListResultIterator { + return ListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (lr ListResult) IsEmpty() bool { + return lr.Value == nil || len(*lr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (lr ListResult) hasNextLink() bool { + return lr.NextLink != nil && len(*lr.NextLink) != 0 +} + +// listResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (lr ListResult) listResultPreparer(ctx context.Context) (*http.Request, error) { + if !lr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(lr.NextLink))) +} + +// ListResultPage contains a page of Subscription values. +type ListResultPage struct { + fn func(context.Context, ListResult) (ListResult, error) + lr ListResult +} + +// NextWithContext advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +func (page *ListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/ListResultPage.NextWithContext") + defer func() { + sc := -1 + if page.Response().Response.Response != nil { + sc = page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + for { + next, err := page.fn(ctx, page.lr) + if err != nil { + return err + } + page.lr = next + if !next.hasNextLink() || !next.IsEmpty() { + break + } + } + return nil +} + +// Next advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (page *ListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page ListResultPage) NotDone() bool { + return !page.lr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page ListResultPage) Response() ListResult { + return page.lr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page ListResultPage) Values() []Subscription { + if page.lr.IsEmpty() { + return nil + } + return *page.lr.Value +} + +// Creates a new instance of the ListResultPage type. +func NewListResultPage(cur ListResult, getNextPage func(context.Context, ListResult) (ListResult, error)) ListResultPage { + return ListResultPage{ + fn: getNextPage, + lr: cur, + } +} + +// Location location information. +type Location struct { + // ID - READ-ONLY; The fully qualified ID of the location. For example, /subscriptions/00000000-0000-0000-0000-000000000000/locations/westus. + ID *string `json:"id,omitempty"` + // SubscriptionID - READ-ONLY; The subscription ID. + SubscriptionID *string `json:"subscriptionId,omitempty"` + // Name - READ-ONLY; The location name. + Name *string `json:"name,omitempty"` + // Type - READ-ONLY; The location type. Possible values include: 'LocationTypeRegion', 'LocationTypeEdgeZone' + Type LocationType `json:"type,omitempty"` + // DisplayName - READ-ONLY; The display name of the location. + DisplayName *string `json:"displayName,omitempty"` + // RegionalDisplayName - READ-ONLY; The display name of the location and its region. + RegionalDisplayName *string `json:"regionalDisplayName,omitempty"` + // Metadata - Metadata of the location, such as lat/long, paired region, and others. + Metadata *LocationMetadata `json:"metadata,omitempty"` +} + +// MarshalJSON is the custom marshaler for Location. +func (l Location) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if l.Metadata != nil { + objectMap["metadata"] = l.Metadata + } + return json.Marshal(objectMap) +} + +// LocationListResult location list operation response. +type LocationListResult struct { + autorest.Response `json:"-"` + // Value - An array of locations. + Value *[]Location `json:"value,omitempty"` +} + +// LocationMetadata location metadata information +type LocationMetadata struct { + // RegionType - READ-ONLY; The type of the region. Possible values include: 'RegionTypePhysical', 'RegionTypeLogical' + RegionType RegionType `json:"regionType,omitempty"` + // RegionCategory - READ-ONLY; The category of the region. Possible values include: 'RegionCategoryRecommended', 'RegionCategoryExtended', 'RegionCategoryOther' + RegionCategory RegionCategory `json:"regionCategory,omitempty"` + // GeographyGroup - READ-ONLY; The geography group of the location. + GeographyGroup *string `json:"geographyGroup,omitempty"` + // Longitude - READ-ONLY; The longitude of the location. + Longitude *string `json:"longitude,omitempty"` + // Latitude - READ-ONLY; The latitude of the location. + Latitude *string `json:"latitude,omitempty"` + // PhysicalLocation - READ-ONLY; The physical location of the Azure location. + PhysicalLocation *string `json:"physicalLocation,omitempty"` + // PairedRegion - The regions paired to this region. + PairedRegion *[]PairedRegion `json:"pairedRegion,omitempty"` + // HomeLocation - READ-ONLY; The home location of an edge zone. + HomeLocation *string `json:"homeLocation,omitempty"` +} + +// MarshalJSON is the custom marshaler for LocationMetadata. +func (lm LocationMetadata) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if lm.PairedRegion != nil { + objectMap["pairedRegion"] = lm.PairedRegion + } + return json.Marshal(objectMap) +} + +// ManagedByTenant information about a tenant managing the subscription. +type ManagedByTenant struct { + // TenantID - READ-ONLY; The tenant ID of the managing tenant. This is a GUID. + TenantID *string `json:"tenantId,omitempty"` +} + +// MarshalJSON is the custom marshaler for ManagedByTenant. +func (mbt ManagedByTenant) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// Operation microsoft.Resources operation +type Operation struct { + // Name - Operation name: {provider}/{resource}/{operation} + Name *string `json:"name,omitempty"` + // Display - The object that represents the operation. + Display *OperationDisplay `json:"display,omitempty"` +} + +// OperationDisplay the object that represents the operation. +type OperationDisplay struct { + // Provider - Service provider: Microsoft.Resources + Provider *string `json:"provider,omitempty"` + // Resource - Resource on which the operation is performed: Profile, endpoint, etc. + Resource *string `json:"resource,omitempty"` + // Operation - Operation type: Read, write, delete, etc. + Operation *string `json:"operation,omitempty"` + // Description - Description of the operation. + Description *string `json:"description,omitempty"` +} + +// OperationListResult result of the request to list Microsoft.Resources operations. It contains a list of +// operations and a URL link to get the next set of results. +type OperationListResult struct { + autorest.Response `json:"-"` + // Value - List of Microsoft.Resources operations. + Value *[]Operation `json:"value,omitempty"` + // NextLink - URL to get the next set of operation list results if there are any. + NextLink *string `json:"nextLink,omitempty"` +} + +// OperationListResultIterator provides access to a complete listing of Operation values. +type OperationListResultIterator struct { + i int + page OperationListResultPage +} + +// NextWithContext advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +func (iter *OperationListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationListResultIterator.NextWithContext") + defer func() { + sc := -1 + if iter.Response().Response.Response != nil { + sc = iter.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + iter.i++ + if iter.i < len(iter.page.Values()) { + return nil + } + err = iter.page.NextWithContext(ctx) + if err != nil { + iter.i-- + return err + } + iter.i = 0 + return nil +} + +// Next advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (iter *OperationListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter OperationListResultIterator) NotDone() bool { + return iter.page.NotDone() && iter.i < len(iter.page.Values()) +} + +// Response returns the raw server response from the last page request. +func (iter OperationListResultIterator) Response() OperationListResult { + return iter.page.Response() +} + +// Value returns the current value or a zero-initialized value if the +// iterator has advanced beyond the end of the collection. +func (iter OperationListResultIterator) Value() Operation { + if !iter.page.NotDone() { + return Operation{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the OperationListResultIterator type. +func NewOperationListResultIterator(page OperationListResultPage) OperationListResultIterator { + return OperationListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (olr OperationListResult) IsEmpty() bool { + return olr.Value == nil || len(*olr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (olr OperationListResult) hasNextLink() bool { + return olr.NextLink != nil && len(*olr.NextLink) != 0 +} + +// operationListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (olr OperationListResult) operationListResultPreparer(ctx context.Context) (*http.Request, error) { + if !olr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(olr.NextLink))) +} + +// OperationListResultPage contains a page of Operation values. +type OperationListResultPage struct { + fn func(context.Context, OperationListResult) (OperationListResult, error) + olr OperationListResult +} + +// NextWithContext advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +func (page *OperationListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationListResultPage.NextWithContext") + defer func() { + sc := -1 + if page.Response().Response.Response != nil { + sc = page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + for { + next, err := page.fn(ctx, page.olr) + if err != nil { + return err + } + page.olr = next + if !next.hasNextLink() || !next.IsEmpty() { + break + } + } + return nil +} + +// Next advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (page *OperationListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page OperationListResultPage) NotDone() bool { + return !page.olr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page OperationListResultPage) Response() OperationListResult { + return page.olr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page OperationListResultPage) Values() []Operation { + if page.olr.IsEmpty() { + return nil + } + return *page.olr.Value +} + +// Creates a new instance of the OperationListResultPage type. +func NewOperationListResultPage(cur OperationListResult, getNextPage func(context.Context, OperationListResult) (OperationListResult, error)) OperationListResultPage { + return OperationListResultPage{ + fn: getNextPage, + olr: cur, + } +} + +// PairedRegion information regarding paired region. +type PairedRegion struct { + // Name - READ-ONLY; The name of the paired region. + Name *string `json:"name,omitempty"` + // ID - READ-ONLY; The fully qualified ID of the location. For example, /subscriptions/00000000-0000-0000-0000-000000000000/locations/westus. + ID *string `json:"id,omitempty"` + // SubscriptionID - READ-ONLY; The subscription ID. + SubscriptionID *string `json:"subscriptionId,omitempty"` +} + +// MarshalJSON is the custom marshaler for PairedRegion. +func (pr PairedRegion) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// Policies subscription policies. +type Policies struct { + // LocationPlacementID - READ-ONLY; The subscription location placement ID. The ID indicates which regions are visible for a subscription. For example, a subscription with a location placement Id of Public_2014-09-01 has access to Azure public regions. + LocationPlacementID *string `json:"locationPlacementId,omitempty"` + // QuotaID - READ-ONLY; The subscription quota ID. + QuotaID *string `json:"quotaId,omitempty"` + // SpendingLimit - READ-ONLY; The subscription spending limit. Possible values include: 'SpendingLimitOn', 'SpendingLimitOff', 'SpendingLimitCurrentPeriodOff' + SpendingLimit SpendingLimit `json:"spendingLimit,omitempty"` +} + +// MarshalJSON is the custom marshaler for Policies. +func (p Policies) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// ResourceName name and Type of the Resource +type ResourceName struct { + // Name - Name of the resource + Name *string `json:"name,omitempty"` + // Type - The type of the resource + Type *string `json:"type,omitempty"` +} + +// Subscription subscription information. +type Subscription struct { + autorest.Response `json:"-"` + // ID - READ-ONLY; The fully qualified ID for the subscription. For example, /subscriptions/00000000-0000-0000-0000-000000000000. + ID *string `json:"id,omitempty"` + // SubscriptionID - READ-ONLY; The subscription ID. + SubscriptionID *string `json:"subscriptionId,omitempty"` + // DisplayName - READ-ONLY; The subscription display name. + DisplayName *string `json:"displayName,omitempty"` + // TenantID - READ-ONLY; The subscription tenant ID. + TenantID *string `json:"tenantId,omitempty"` + // State - READ-ONLY; The subscription state. Possible values are Enabled, Warned, PastDue, Disabled, and Deleted. Possible values include: 'StateEnabled', 'StateWarned', 'StatePastDue', 'StateDisabled', 'StateDeleted' + State State `json:"state,omitempty"` + // SubscriptionPolicies - The subscription policies. + SubscriptionPolicies *Policies `json:"subscriptionPolicies,omitempty"` + // AuthorizationSource - The authorization source of the request. Valid values are one or more combinations of Legacy, RoleBased, Bypassed, Direct and Management. For example, 'Legacy, RoleBased'. + AuthorizationSource *string `json:"authorizationSource,omitempty"` + // ManagedByTenants - An array containing the tenants managing the subscription. + ManagedByTenants *[]ManagedByTenant `json:"managedByTenants,omitempty"` + // Tags - The tags attached to the subscription. + Tags map[string]*string `json:"tags"` +} + +// MarshalJSON is the custom marshaler for Subscription. +func (s Subscription) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if s.SubscriptionPolicies != nil { + objectMap["subscriptionPolicies"] = s.SubscriptionPolicies + } + if s.AuthorizationSource != nil { + objectMap["authorizationSource"] = s.AuthorizationSource + } + if s.ManagedByTenants != nil { + objectMap["managedByTenants"] = s.ManagedByTenants + } + if s.Tags != nil { + objectMap["tags"] = s.Tags + } + return json.Marshal(objectMap) +} + +// TenantIDDescription tenant Id information. +type TenantIDDescription struct { + // ID - READ-ONLY; The fully qualified ID of the tenant. For example, /tenants/00000000-0000-0000-0000-000000000000. + ID *string `json:"id,omitempty"` + // TenantID - READ-ONLY; The tenant ID. For example, 00000000-0000-0000-0000-000000000000. + TenantID *string `json:"tenantId,omitempty"` + // TenantCategory - READ-ONLY; Category of the tenant. Possible values include: 'TenantCategoryHome', 'TenantCategoryProjectedBy', 'TenantCategoryManagedBy' + TenantCategory TenantCategory `json:"tenantCategory,omitempty"` + // Country - READ-ONLY; Country/region name of the address for the tenant. + Country *string `json:"country,omitempty"` + // CountryCode - READ-ONLY; Country/region abbreviation for the tenant. + CountryCode *string `json:"countryCode,omitempty"` + // DisplayName - READ-ONLY; The display name of the tenant. + DisplayName *string `json:"displayName,omitempty"` + // Domains - READ-ONLY; The list of domains for the tenant. + Domains *[]string `json:"domains,omitempty"` + // DefaultDomain - READ-ONLY; The default domain for the tenant. + DefaultDomain *string `json:"defaultDomain,omitempty"` + // TenantType - READ-ONLY; The tenant type. Only available for 'Home' tenant category. + TenantType *string `json:"tenantType,omitempty"` + // TenantBrandingLogoURL - READ-ONLY; The tenant's branding logo URL. Only available for 'Home' tenant category. + TenantBrandingLogoURL *string `json:"tenantBrandingLogoUrl,omitempty"` +} + +// MarshalJSON is the custom marshaler for TenantIDDescription. +func (tid TenantIDDescription) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// TenantListResult tenant Ids information. +type TenantListResult struct { + autorest.Response `json:"-"` + // Value - An array of tenants. + Value *[]TenantIDDescription `json:"value,omitempty"` + // NextLink - The URL to use for getting the next set of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// TenantListResultIterator provides access to a complete listing of TenantIDDescription values. +type TenantListResultIterator struct { + i int + page TenantListResultPage +} + +// NextWithContext advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +func (iter *TenantListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/TenantListResultIterator.NextWithContext") + defer func() { + sc := -1 + if iter.Response().Response.Response != nil { + sc = iter.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + iter.i++ + if iter.i < len(iter.page.Values()) { + return nil + } + err = iter.page.NextWithContext(ctx) + if err != nil { + iter.i-- + return err + } + iter.i = 0 + return nil +} + +// Next advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (iter *TenantListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter TenantListResultIterator) NotDone() bool { + return iter.page.NotDone() && iter.i < len(iter.page.Values()) +} + +// Response returns the raw server response from the last page request. +func (iter TenantListResultIterator) Response() TenantListResult { + return iter.page.Response() +} + +// Value returns the current value or a zero-initialized value if the +// iterator has advanced beyond the end of the collection. +func (iter TenantListResultIterator) Value() TenantIDDescription { + if !iter.page.NotDone() { + return TenantIDDescription{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the TenantListResultIterator type. +func NewTenantListResultIterator(page TenantListResultPage) TenantListResultIterator { + return TenantListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (tlr TenantListResult) IsEmpty() bool { + return tlr.Value == nil || len(*tlr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (tlr TenantListResult) hasNextLink() bool { + return tlr.NextLink != nil && len(*tlr.NextLink) != 0 +} + +// tenantListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (tlr TenantListResult) tenantListResultPreparer(ctx context.Context) (*http.Request, error) { + if !tlr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(tlr.NextLink))) +} + +// TenantListResultPage contains a page of TenantIDDescription values. +type TenantListResultPage struct { + fn func(context.Context, TenantListResult) (TenantListResult, error) + tlr TenantListResult +} + +// NextWithContext advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +func (page *TenantListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/TenantListResultPage.NextWithContext") + defer func() { + sc := -1 + if page.Response().Response.Response != nil { + sc = page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + for { + next, err := page.fn(ctx, page.tlr) + if err != nil { + return err + } + page.tlr = next + if !next.hasNextLink() || !next.IsEmpty() { + break + } + } + return nil +} + +// Next advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (page *TenantListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page TenantListResultPage) NotDone() bool { + return !page.tlr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page TenantListResultPage) Response() TenantListResult { + return page.tlr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page TenantListResultPage) Values() []TenantIDDescription { + if page.tlr.IsEmpty() { + return nil + } + return *page.tlr.Value +} + +// Creates a new instance of the TenantListResultPage type. +func NewTenantListResultPage(cur TenantListResult, getNextPage func(context.Context, TenantListResult) (TenantListResult, error)) TenantListResultPage { + return TenantListResultPage{ + fn: getNextPage, + tlr: cur, + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/operations.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/operations.go new file mode 100644 index 000000000..bd5ea8aba --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/operations.go @@ -0,0 +1,142 @@ +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// OperationsClient is the all resource groups and resources exist within subscriptions. These operation enable you get +// information about your subscriptions and tenants. A tenant is a dedicated instance of Azure Active Directory (Azure +// AD) for your organization. +type OperationsClient struct { + BaseClient +} + +// NewOperationsClient creates an instance of the OperationsClient client. +func NewOperationsClient() OperationsClient { + return NewOperationsClientWithBaseURI(DefaultBaseURI) +} + +// NewOperationsClientWithBaseURI creates an instance of the OperationsClient client using a custom endpoint. Use this +// when interacting with an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewOperationsClientWithBaseURI(baseURI string) OperationsClient { + return OperationsClient{NewWithBaseURI(baseURI)} +} + +// List lists all of the available Microsoft.Resources REST API operations. +func (client OperationsClient) List(ctx context.Context) (result OperationListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationsClient.List") + defer func() { + sc := -1 + if result.olr.Response.Response != nil { + sc = result.olr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.olr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "List", resp, "Failure sending request") + return + } + + result.olr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "List", resp, "Failure responding to request") + return + } + if result.olr.hasNextLink() && result.olr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client OperationsClient) ListPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/providers/Microsoft.Resources/operations"), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListSender sends the List request. The method will close the +// http.Response Body if it receives an error. +func (client OperationsClient) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client OperationsClient) ListResponder(resp *http.Response) (result OperationListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listNextResults retrieves the next set of results, if any. +func (client OperationsClient) listNextResults(ctx context.Context, lastResults OperationListResult) (result OperationListResult, err error) { + req, err := lastResults.operationListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "listNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.OperationsClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client OperationsClient) ListComplete(ctx context.Context) (result OperationListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationsClient.List") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.List(ctx) + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/subscriptions.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/subscriptions.go new file mode 100644 index 000000000..446443ec0 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/subscriptions.go @@ -0,0 +1,293 @@ +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// Client is the all resource groups and resources exist within subscriptions. These operation enable you get +// information about your subscriptions and tenants. A tenant is a dedicated instance of Azure Active Directory (Azure +// AD) for your organization. +type Client struct { + BaseClient +} + +// NewClient creates an instance of the Client client. +func NewClient() Client { + return NewClientWithBaseURI(DefaultBaseURI) +} + +// NewClientWithBaseURI creates an instance of the Client client using a custom endpoint. Use this when interacting +// with an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewClientWithBaseURI(baseURI string) Client { + return Client{NewWithBaseURI(baseURI)} +} + +// Get gets details about a specified subscription. +// Parameters: +// subscriptionID - the ID of the target subscription. +func (client Client) Get(ctx context.Context, subscriptionID string) (result Subscription, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.Get") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + req, err := client.GetPreparer(ctx, subscriptionID) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "Get", nil, "Failure preparing request") + return + } + + resp, err := client.GetSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.Client", "Get", resp, "Failure sending request") + return + } + + result, err = client.GetResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "Get", resp, "Failure responding to request") + return + } + + return +} + +// GetPreparer prepares the Get request. +func (client Client) GetPreparer(ctx context.Context, subscriptionID string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "subscriptionId": autorest.Encode("path", subscriptionID), + } + + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// GetSender sends the Get request. The method will close the +// http.Response Body if it receives an error. +func (client Client) GetSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// GetResponder handles the response to the Get request. The method always +// closes the http.Response Body. +func (client Client) GetResponder(resp *http.Response) (result Subscription, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// List gets all subscriptions for a tenant. +func (client Client) List(ctx context.Context) (result ListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.List") + defer func() { + sc := -1 + if result.lr.Response.Response != nil { + sc = result.lr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.lr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.Client", "List", resp, "Failure sending request") + return + } + + result.lr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "List", resp, "Failure responding to request") + return + } + if result.lr.hasNextLink() && result.lr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client Client) ListPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/subscriptions"), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListSender sends the List request. The method will close the +// http.Response Body if it receives an error. +func (client Client) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client Client) ListResponder(resp *http.Response) (result ListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listNextResults retrieves the next set of results, if any. +func (client Client) listNextResults(ctx context.Context, lastResults ListResult) (result ListResult, err error) { + req, err := lastResults.listResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "subscriptions.Client", "listNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "subscriptions.Client", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client Client) ListComplete(ctx context.Context) (result ListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.List") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.List(ctx) + return +} + +// ListLocations this operation provides all the locations that are available for resource providers; however, each +// resource provider may support a subset of this list. +// Parameters: +// subscriptionID - the ID of the target subscription. +// includeExtendedLocations - whether to include extended locations. +func (client Client) ListLocations(ctx context.Context, subscriptionID string, includeExtendedLocations *bool) (result LocationListResult, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.ListLocations") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + req, err := client.ListLocationsPreparer(ctx, subscriptionID, includeExtendedLocations) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "ListLocations", nil, "Failure preparing request") + return + } + + resp, err := client.ListLocationsSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.Client", "ListLocations", resp, "Failure sending request") + return + } + + result, err = client.ListLocationsResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.Client", "ListLocations", resp, "Failure responding to request") + return + } + + return +} + +// ListLocationsPreparer prepares the ListLocations request. +func (client Client) ListLocationsPreparer(ctx context.Context, subscriptionID string, includeExtendedLocations *bool) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "subscriptionId": autorest.Encode("path", subscriptionID), + } + + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + if includeExtendedLocations != nil { + queryParameters["includeExtendedLocations"] = autorest.Encode("query", *includeExtendedLocations) + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/locations", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListLocationsSender sends the ListLocations request. The method will close the +// http.Response Body if it receives an error. +func (client Client) ListLocationsSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// ListLocationsResponder handles the response to the ListLocations request. The method always +// closes the http.Response Body. +func (client Client) ListLocationsResponder(resp *http.Response) (result LocationListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/tenants.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/tenants.go new file mode 100644 index 000000000..2dbca5c03 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/tenants.go @@ -0,0 +1,142 @@ +package subscriptions + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// TenantsClient is the all resource groups and resources exist within subscriptions. These operation enable you get +// information about your subscriptions and tenants. A tenant is a dedicated instance of Azure Active Directory (Azure +// AD) for your organization. +type TenantsClient struct { + BaseClient +} + +// NewTenantsClient creates an instance of the TenantsClient client. +func NewTenantsClient() TenantsClient { + return NewTenantsClientWithBaseURI(DefaultBaseURI) +} + +// NewTenantsClientWithBaseURI creates an instance of the TenantsClient client using a custom endpoint. Use this when +// interacting with an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewTenantsClientWithBaseURI(baseURI string) TenantsClient { + return TenantsClient{NewWithBaseURI(baseURI)} +} + +// List gets the tenants for your account. +func (client TenantsClient) List(ctx context.Context) (result TenantListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/TenantsClient.List") + defer func() { + sc := -1 + if result.tlr.Response.Response != nil { + sc = result.tlr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.tlr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure sending request") + return + } + + result.tlr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "List", resp, "Failure responding to request") + return + } + if result.tlr.hasNextLink() && result.tlr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client TenantsClient) ListPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2021-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/tenants"), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListSender sends the List request. The method will close the +// http.Response Body if it receives an error. +func (client TenantsClient) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client TenantsClient) ListResponder(resp *http.Response) (result TenantListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listNextResults retrieves the next set of results, if any. +func (client TenantsClient) listNextResults(ctx context.Context, lastResults TenantListResult) (result TenantListResult, err error) { + req, err := lastResults.tenantListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "listNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "subscriptions.TenantsClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client TenantsClient) ListComplete(ctx context.Context) (result TenantListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/TenantsClient.List") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.List(ctx) + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/version.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/version.go new file mode 100644 index 000000000..85a8f54a1 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2021-01-01/subscriptions/version.go @@ -0,0 +1,19 @@ +package subscriptions + +import "github.com/Azure/azure-sdk-for-go/version" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/" + Version() + " subscriptions/2021-01-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return version.Number +} From 518d199ddc666b952d11f7605b1ec059b9603022 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 27 Sep 2023 13:32:07 +0000 Subject: [PATCH 4/5] ore: azure: Support managed identities Signed-off-by: Jeremi Piotrowski --- cmd/ore/azure/azure.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/ore/azure/azure.go b/cmd/ore/azure/azure.go index 23a0f4d66..8da00c54f 100644 --- a/cmd/ore/azure/azure.go +++ b/cmd/ore/azure/azure.go @@ -35,6 +35,7 @@ var ( azureAuth string azureSubscription string azureLocation string + useIdentity bool api *azure.API ) @@ -43,10 +44,12 @@ func init() { cli.WrapPreRun(Azure, preauth) sv := Azure.PersistentFlags().StringVar + bv := Azure.PersistentFlags().BoolVar sv(&azureProfile, "azure-profile", "", "Azure Profile json file") sv(&azureAuth, "azure-auth", "", "Azure auth location (default \"~/"+auth.AzureAuthPath+"\")") sv(&azureSubscription, "azure-subscription", "", "Azure subscription name. If unset, the first is used.") sv(&azureLocation, "azure-location", "westus", "Azure location (default \"westus\")") + bv(&useIdentity, "azure-identity", false, "Use VM managed identity for authentication (default false)") } func preauth(cmd *cobra.Command, args []string) error { @@ -57,6 +60,7 @@ func preauth(cmd *cobra.Command, args []string) error { AzureAuthLocation: azureAuth, AzureSubscription: azureSubscription, Location: azureLocation, + UseIdentity: useIdentity, }) if err != nil { plog.Fatalf("Failed to create Azure API: %v", err) From dbdf00c8c57e2e1391d76f92d2e0aac77294e347 Mon Sep 17 00:00:00 2001 From: Jeremi Piotrowski Date: Wed, 27 Sep 2023 13:32:52 +0000 Subject: [PATCH 5/5] platform/azure: Support "latest" image version This is only used when running kola spawn with marketplace images. This matches what azure-cli does. Signed-off-by: Jeremi Piotrowski --- platform/api/azure/instance.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/api/azure/instance.go b/platform/api/azure/instance.go index 0883a1e37..cfbfa4c7f 100644 --- a/platform/api/azure/instance.go +++ b/platform/api/azure/instance.go @@ -71,6 +71,17 @@ func (a *API) getVMParameters(name, userdata, sshkey, storageAccountURI string, Sku: &a.Opts.Sku, Version: &a.Opts.Version, } + if a.Opts.Version == "latest" { + var top int32 = 1 + list, err := a.vmImgClient.List(context.TODO(), a.Opts.Location, a.Opts.Publisher, a.Opts.Offer, a.Opts.Sku, "", &top, "name desc") + if err != nil { + plog.Warningf("failed to get image list: %v; continuing", err) + } else if list.Value == nil || len(*list.Value) == 0 || (*list.Value)[0].Name == nil { + plog.Warningf("no images found; continuing") + } else { + a.Opts.Version = *(*list.Value)[0].Name + } + } // lookup plan information for image imgInfo, err := a.vmImgClient.Get(context.TODO(), a.Opts.Location, *imgRef.Publisher, *imgRef.Offer, *imgRef.Sku, *imgRef.Version) if err == nil && imgInfo.Plan != nil {