mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-15 22:41:55 +01:00
feat: create azure community gallery image version on release
Create Azure Community Gallery Image Version on release: - Add /hack/cloud-image-uploader/azure.go - Upload vhd file to container for all architectures - Create managed disk from vhd file for all architectures - Create image version from managed disk for all architectures - Modify /hack/cloud-image-uploader/main.go - Start Community Gallery processes concurently with AWS upload - Modify /hack/cloud-image-uploader/options.go - Add additional Options for Community Gallery processes - Modify .drone.jsonnet to use secrets for environment variables - The following secrets need to be created for this to work: - azure_subscription_id - azure_client_id - azure_client_secret - azure_tenant_id Signed-off-by: Christian Rolland <christian.rolland@siderolabs.com> chore: fix linting errors in readme Fix linting errors in readme Signed-off-by: Christian Rolland <christian.rolland@siderolabs.com> chore: fix markdown linting errors Fix markdown linting errors in readme Signed-off-by: Christian Rolland <christian.rolland@siderolabs.com> chore: fix markdown linting errors Fix markdown linting errors in readme Signed-off-by: Christian Rolland <christian.rolland@siderolabs.com> chore: change disk size to match new 10GB cloud image size Change disk size to match 10GB cloud image size Signed-off-by: Christian Rolland <christian.rolland@siderolabs.com>
This commit is contained in:
parent
dd8336c9ee
commit
e0c1585d30
@ -585,10 +585,16 @@ local integration_pipelines = [
|
||||
// E2E pipeline.
|
||||
|
||||
local creds_env_vars = {
|
||||
// AWS creds
|
||||
AWS_ACCESS_KEY_ID: { from_secret: 'aws_access_key_id' },
|
||||
AWS_SECRET_ACCESS_KEY: { from_secret: 'aws_secret_access_key' },
|
||||
AWS_SVC_ACCT: { from_secret: 'aws_svc_acct' },
|
||||
// Azure creds
|
||||
AZURE_SVC_ACCT: { from_secret: 'azure_svc_acct' },
|
||||
AZURE_SUBSCRIPTION_ID: { from_secret: 'azure_subscription_id' },
|
||||
AZURE_CLIENT_ID: { from_secret: 'azure_client_id' },
|
||||
AZURE_CLIENT_SECRET: { from_secret: 'azure_client_secret' },
|
||||
AZURE_TENANT_ID: { from_secret: 'azure_tenant_id' },
|
||||
// TODO(andrewrynhard): Rename this to the GCP convention.
|
||||
GCE_SVC_ACCT: { from_secret: 'gce_svc_acct' },
|
||||
PACKET_AUTH_TOKEN: { from_secret: 'packet_auth_token' },
|
||||
|
||||
@ -822,6 +822,9 @@ ENV GOLANGCI_LINT_CACHE /.cache/lint
|
||||
RUN --mount=type=cache,target=/.cache golangci-lint run --config .golangci.yml
|
||||
WORKDIR /src/pkg/machinery
|
||||
RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci.yml
|
||||
COPY ./hack/cloud-image-uploader /src/hack/cloud-image-uploader
|
||||
WORKDIR /src/hack/cloud-image-uploader
|
||||
RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci.yml
|
||||
WORKDIR /src
|
||||
RUN --mount=type=cache,target=/.cache importvet github.com/siderolabs/talos/...
|
||||
|
||||
|
||||
@ -6,3 +6,86 @@ Role should be pre-created before running this command.
|
||||
|
||||
aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json
|
||||
aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json
|
||||
|
||||
## Azure Pre-requisites
|
||||
|
||||
### Configuring the Portal
|
||||
|
||||
Community Gallery (preview) information can be found [here](https://learn.microsoft.com/en-us/azure/virtual-machines/share-gallery-community?tabs=cli).
|
||||
|
||||
- Create **Resource Group**: `SideroGallery`
|
||||
- [Azure Documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal)
|
||||
- Create **Storage Account**: `siderogallery`
|
||||
- [Azure Documentation](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal)
|
||||
- Create storage **Container**: `images`
|
||||
- [Azure Documentation](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
|
||||
- Create **Azure Compute Gallery**: `SideroLabs`
|
||||
- [Azure Documentation](https://learn.microsoft.com/en-us/azure/virtual-machines/azure-compute-gallery)
|
||||
- Search for **Azure Compute Gallery** in the portal search bar.
|
||||
- Select **Create**.
|
||||
- Fill in the required information.
|
||||
- In the **Sharing** Tab select **RBAC + share to public community gallery (PREVIEW)**
|
||||
- Select **Review + create**
|
||||
- Create Compute Gallery **Image Definition**: `talos-arm64`, `talos-x64
|
||||
- [Azure Documentation](https://learn.microsoft.com/en-us/azure/virtual-machines/azure-compute-gallery)
|
||||
- Select the `SideroLabs` Compute Gallery.
|
||||
- Select the notification at the top of the page to share the gallery.
|
||||
- Select **New Image Definition**
|
||||
- Create an Image definition for each architecture type:
|
||||
- This is where V2 must be selected for the VM generation in order for an arm64 image version to be created in the definition.
|
||||
- **Publisher**: `siderolabs`
|
||||
- **Offer**: `talos`
|
||||
- SKU: must be unique
|
||||
- Do not create an image version yet.
|
||||
|
||||
### App Registration
|
||||
|
||||
The App Registration is what we will use to authenticate to Azure for uploading blobs and creating resources.
|
||||
|
||||
[Azure Documentation](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
|
||||
|
||||
#### Create an App Registration
|
||||
|
||||
- Search for and Select **Azure Active Directory**.
|
||||
- Select **App registrations**, then select **New registration**.
|
||||
- Name the application, for example "example-app".
|
||||
- Select a supported account type, which determines who can use the application.
|
||||
- Under **Redirect URI**, select **Web** for the type of application you want to create, enter the URI where the access token is sent to.
|
||||
- Select **Register**.
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
Get the following values for azure-go-sdk
|
||||
|
||||
- **Subscription ID**
|
||||
-Login into your Azure account
|
||||
- Select Subscriptions in the left sidebar
|
||||
- Select whichever subscription is needed
|
||||
- Click on Overview
|
||||
- Copy the Subscription ID
|
||||
- **Client ID**
|
||||
- **Client Secret**
|
||||
- **Tenant ID**
|
||||
|
||||
These are stored as Drone secrets as:
|
||||
|
||||
- azure_subscription_id
|
||||
- azure_client_id
|
||||
- azure_client_secret
|
||||
- azure_tenant_id
|
||||
|
||||
#### Add permissions for App Registration
|
||||
|
||||
The App registration only needs permissions to the Compute Gallery and the Storage Account.
|
||||
|
||||
- Compute Gallery:
|
||||
|
||||
- Select the `SideroLabs` Compute Gallery
|
||||
- Select Access control (IAM)
|
||||
- Select Add role assignment
|
||||
- Select the **Contributer** role
|
||||
- Storage Account:
|
||||
- Select the `siderolabs` Storage Account
|
||||
- Select Access control (IAM)
|
||||
- Select Add role assignment
|
||||
- Select the **Storage Blob Data Contributor** role
|
||||
|
||||
@ -161,6 +161,7 @@ func (au *AWSUploader) registerAMI(ctx context.Context, region string, svc *ec2.
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (au *AWSUploader) registerAMIArch(ctx context.Context, region string, svc *ec2.EC2, arch, bucketName string, uploader *s3manager.Uploader) error {
|
||||
err := retry.Constant(5*time.Minute, retry.WithUnits(time.Second)).Retry(func() error {
|
||||
source, err := os.Open(au.Options.AWSImage(arch))
|
||||
|
||||
62
hack/cloud-image-uploader/azure-disk-template.json
Normal file
62
hack/cloud-image-uploader/azure-disk-template.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"disk_name": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"storage_account": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"vhd_name": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"region": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"architecture": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
}
|
||||
},
|
||||
"variables": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Compute/disks",
|
||||
"apiVersion": "2022-07-02",
|
||||
"name": "[parameters('disk_name')]",
|
||||
"location": "[parameters('region')]",
|
||||
"sku": {
|
||||
"name": "Premium_LRS",
|
||||
"tier": "Premium"
|
||||
},
|
||||
"properties": {
|
||||
"osType": "Linux",
|
||||
"hyperVGeneration": "V2",
|
||||
"supportedCapabilities": {
|
||||
"architecture": "[parameters('architecture')]"
|
||||
},
|
||||
"creationData": {
|
||||
"createOption": "Import",
|
||||
"storageAccountId": "[concat('/subscriptions/7f739b7d-f399-4b97-9a9f-f1962309ee6e/resourceGroups/SideroGallery/providers/Microsoft.Storage/storageAccounts/', parameters('storage_account'))]",
|
||||
"sourceUri": "[concat('https://siderogallery.blob.core.windows.net/images/talos/', parameters('vhd_name'))]"
|
||||
},
|
||||
"diskSizeGB": 10,
|
||||
"diskIOPSReadWrite": 120,
|
||||
"diskMBpsReadWrite": 25,
|
||||
"encryption": {
|
||||
"type": "EncryptionAtRestWithPlatformKey"
|
||||
},
|
||||
"networkAccessPolicy": "AllowAll",
|
||||
"publicNetworkAccess": "Enabled",
|
||||
"dataAccessAuthMode": "None",
|
||||
"diskState": "Unattached",
|
||||
"tier": "P2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
61
hack/cloud-image-uploader/azure-image-version-template.json
Normal file
61
hack/cloud-image-uploader/azure-image-version-template.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"gallery_name": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"disk_name": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"image_version": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"definition_name": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"region": {
|
||||
"defaultValue": null,
|
||||
"type": "String"
|
||||
},
|
||||
"resourceGroupName": {
|
||||
"type": "String"
|
||||
},
|
||||
"targetRegions": {
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"variables": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Compute/galleries/images/versions",
|
||||
"apiVersion": "2022-03-03",
|
||||
"name": "[concat(parameters('gallery_name'), '/', parameters('definition_name'), '/', parameters('image_version'))]",
|
||||
"location": "[parameters('region')]",
|
||||
"properties": {
|
||||
"publishingProfile": {
|
||||
"targetRegions": "[parameters('targetRegions')]",
|
||||
"replicaCount": 1,
|
||||
"excludeFromLatest": false,
|
||||
"storageAccountType": "Standard_LRS",
|
||||
"replicationMode": "Full"
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDiskImage": {
|
||||
"hostCaching": "None",
|
||||
"source": {
|
||||
"id": "[concat('/subscriptions/7f739b7d-f399-4b97-9a9f-f1962309ee6e/resourceGroups/SIDEROGALLERY/providers/Microsoft.Compute/disks/', parameters('disk_name'))]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"safetyProfile": {
|
||||
"allowDeletionOfReplicatedLocations": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
441
hack/cloud-image-uploader/azure.go
Normal file
441
hack/cloud-image-uploader/azure.go
Normal file
@ -0,0 +1,441 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/resources/mgmt/resources"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure/auth"
|
||||
"github.com/siderolabs/gen/channel"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
const (
|
||||
resourceGroupName = "SideroGallery"
|
||||
defaultRegion = "eastus"
|
||||
galleryName = "SideroLabs"
|
||||
storageAccount = "siderogallery"
|
||||
)
|
||||
|
||||
//go:embed azure-disk-template.json
|
||||
var azureDiskTemplate []byte
|
||||
|
||||
//go:embed azure-image-version-template.json
|
||||
var azureImageVersionTemplate []byte
|
||||
|
||||
// TargetRegion describes the region to upload to.
|
||||
type TargetRegion struct {
|
||||
Name string `json:"name"`
|
||||
RegionalReplicaCount int `json:"regionalReplicaCount"`
|
||||
StorageAccountType string `json:"storageAccountType"`
|
||||
}
|
||||
|
||||
// Mapping CPU architectures to Azure architectures.
|
||||
var azureArchitectures = map[string]string{
|
||||
"amd64": "x64",
|
||||
"arm64": "arm64",
|
||||
}
|
||||
|
||||
// AzureUploader represents an object that has the capability to upload to Azure.
|
||||
type AzureUploader struct {
|
||||
Options Options
|
||||
|
||||
helper azureHelper
|
||||
}
|
||||
|
||||
// AzureGalleryUpload uploads the image to Azure.
|
||||
func (azu *AzureUploader) AzureGalleryUpload(ctx context.Context) error {
|
||||
var err error
|
||||
|
||||
var g *errgroup.Group
|
||||
g, ctx = errgroup.WithContext(ctx)
|
||||
|
||||
fmt.Println("Setting default creds")
|
||||
|
||||
err = azu.helper.setDefaultAzureCreds()
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Println("Getting locations")
|
||||
|
||||
err = azu.helper.getAzureLocations(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
// Upload blob
|
||||
fmt.Printf("Architectures: %+v\n", azu.Options.Architectures)
|
||||
|
||||
for _, arch := range azu.Options.Architectures {
|
||||
arch := arch
|
||||
|
||||
g.Go(func() error {
|
||||
fmt.Printf("Starting upload blob for %s\n", arch)
|
||||
err = azu.uploadAzureBlob(ctx, arch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error uploading page blob for %s: %w", arch, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Starting disk creation for %s\n", arch)
|
||||
err = azu.createAzureDisk(ctx, azureDiskTemplate, arch)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Starting image version creation for %s\n", arch)
|
||||
err = azu.createAzureImageVersion(ctx, azureImageVersionTemplate, arch)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (azu *AzureUploader) uploadAzureBlob(ctx context.Context, arch string) error {
|
||||
blobURL := fmt.Sprintf("https://siderogallery.blob.core.windows.net/images/talos/talos-%s-%s.vhd", arch, azu.Options.Tag)
|
||||
|
||||
pageBlobClient, err := pageblob.NewClient(blobURL, azu.helper.cred, nil)
|
||||
if err != nil {
|
||||
log.Printf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
source, err := os.Open(azu.Options.AzureImage(arch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer source.Close() //nolint:errcheck
|
||||
|
||||
// calculate totalSize
|
||||
file, err := ExtractFileFromTarGz("disk.vhd", source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error extracting file from tar.gz: %w", err)
|
||||
}
|
||||
|
||||
totalSize, err := io.Copy(io.Discard, file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error calculating totalSize: %w", err)
|
||||
}
|
||||
|
||||
// second pass: read chunks and upload
|
||||
// seek back to the beginning of the source file
|
||||
_, err = source.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error seeking back: %w", err)
|
||||
}
|
||||
|
||||
file, err = ExtractFileFromTarGz("disk.vhd", source)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error extracting file from tar.gz: %w", err)
|
||||
}
|
||||
|
||||
// Check if the file size is a multiple of 512 bytes
|
||||
if totalSize%pageblob.PageBytes != 0 {
|
||||
panic("The file size must be a multiple of 512 bytes")
|
||||
}
|
||||
|
||||
_, err = pageBlobClient.Create(ctx, totalSize, nil)
|
||||
if err != nil {
|
||||
log.Printf("Error: %v\n", err)
|
||||
}
|
||||
|
||||
type work struct {
|
||||
chunk []byte
|
||||
offset int64
|
||||
}
|
||||
|
||||
const (
|
||||
concurrency = 8
|
||||
chunkSize = 4 * 1024 * 1024
|
||||
)
|
||||
|
||||
workCh := make(chan work)
|
||||
|
||||
var g *errgroup.Group
|
||||
g, ctx = errgroup.WithContext(ctx)
|
||||
|
||||
for i := 0; i < concurrency; i++ {
|
||||
g.Go(func() error {
|
||||
for w := range workCh {
|
||||
_, err = pageBlobClient.UploadPages(
|
||||
ctx,
|
||||
streaming.NopCloser(bytes.NewReader(w.chunk)),
|
||||
blob.HTTPRange{Offset: w.offset, Count: int64(len(w.chunk))},
|
||||
nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error uploading chunk at offset %d: %w", w.offset, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var offset int64
|
||||
|
||||
uploadLoop:
|
||||
for {
|
||||
buf := make([]byte, chunkSize)
|
||||
|
||||
var n int
|
||||
|
||||
n, err = io.ReadFull(file, buf)
|
||||
switch {
|
||||
case err == io.ErrUnexpectedEOF:
|
||||
// this is the last (incomplete) chunk
|
||||
case err == io.EOF:
|
||||
// end of file, stop
|
||||
break uploadLoop
|
||||
case err != nil:
|
||||
return fmt.Errorf("error reading chunk: %w", err)
|
||||
}
|
||||
|
||||
if !channel.SendWithContext(ctx, workCh, work{chunk: buf[:n], offset: offset}) {
|
||||
break uploadLoop
|
||||
}
|
||||
|
||||
offset += int64(n)
|
||||
|
||||
if offset%(chunkSize*10) == 0 {
|
||||
log.Printf("azure: uploaded %d bytes\n", offset)
|
||||
}
|
||||
}
|
||||
|
||||
close(workCh)
|
||||
|
||||
if err = g.Wait(); err != nil {
|
||||
return fmt.Errorf("error uploading chunks: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (azu *AzureUploader) createAzureDisk(ctx context.Context, armTemplate []byte, arch string) error {
|
||||
diskParameters := map[string]interface{}{
|
||||
"disk_name": map[string]string{
|
||||
"value": "talos-" + arch + "-" + azu.Options.Tag,
|
||||
},
|
||||
"storage_account": map[string]string{
|
||||
"value": storageAccount,
|
||||
},
|
||||
"vhd_name": map[string]string{
|
||||
"value": "talos-" + arch + "-" + azu.Options.Tag + ".vhd",
|
||||
},
|
||||
"region": map[string]string{
|
||||
"value": defaultRegion,
|
||||
},
|
||||
"architecture": map[string]string{
|
||||
"value": azureArchitectures[arch],
|
||||
},
|
||||
}
|
||||
|
||||
deploymentName := "disk-talos-" + arch + "-" + azu.Options.Tag
|
||||
|
||||
if err := azu.helper.deployResourceFromTemplate(ctx, armTemplate, diskParameters, deploymentName); err != nil {
|
||||
return fmt.Errorf("error applying Azure disk template: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (azu *AzureUploader) createAzureImageVersion(ctx context.Context, armTemplate []byte, arch string) error {
|
||||
targetRegions := make([]TargetRegion, 0, len(azu.helper.locations))
|
||||
|
||||
for _, region := range azu.helper.locations {
|
||||
targetRegions = append(targetRegions, TargetRegion{
|
||||
Name: region.Name,
|
||||
RegionalReplicaCount: 1,
|
||||
StorageAccountType: "Standard_LRS",
|
||||
})
|
||||
}
|
||||
|
||||
versionParameters := map[string]interface{}{
|
||||
"disk_name": map[string]string{
|
||||
"value": "talos-" + arch + "-" + azu.Options.Tag,
|
||||
},
|
||||
"image_version": map[string]string{
|
||||
"value": azu.Options.Tag,
|
||||
},
|
||||
"gallery_name": map[string]string{
|
||||
"value": galleryName,
|
||||
},
|
||||
"definition_name": map[string]string{
|
||||
"value": "talos-" + azureArchitectures[arch],
|
||||
},
|
||||
"region": map[string]string{
|
||||
"value": defaultRegion,
|
||||
},
|
||||
"resourceGroupName": map[string]string{
|
||||
"value": resourceGroupName,
|
||||
},
|
||||
"targetRegions": map[string]interface{}{
|
||||
"value": targetRegions,
|
||||
},
|
||||
}
|
||||
|
||||
deploymentName := "imgversion-talos-" + arch + "-" + azu.Options.Tag
|
||||
|
||||
if err := azu.helper.deployResourceFromTemplate(ctx, armTemplate, versionParameters, deploymentName); err != nil {
|
||||
return fmt.Errorf("error applying Azure image version template: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type azureHelper struct {
|
||||
subscriptionID string
|
||||
cred *azidentity.DefaultAzureCredential
|
||||
authorizer autorest.Authorizer
|
||||
providersClient resources.ProvidersClient
|
||||
locations map[string]Location
|
||||
}
|
||||
|
||||
func (helper *azureHelper) setDefaultAzureCreds() error {
|
||||
helper.subscriptionID = os.Getenv("AZURE_SUBSCRIPTION_ID")
|
||||
if len(helper.subscriptionID) == 0 {
|
||||
log.Fatalln("AZURE_SUBSCRIPTION_ID is not set.")
|
||||
}
|
||||
|
||||
authFromEnvironment, err := auth.NewAuthorizerFromEnvironment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
helper.authorizer = authFromEnvironment
|
||||
|
||||
// Create a new instance of the DefaultAzureCredential
|
||||
helper.cred, err = azidentity.NewDefaultAzureCredential(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Initialize the Storage Accounts Client
|
||||
var storageClientFactory *armstorage.ClientFactory
|
||||
|
||||
storageClientFactory, err = armstorage.NewClientFactory(helper.subscriptionID, helper.cred, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = storageClientFactory.NewAccountsClient()
|
||||
helper.providersClient = resources.NewProvidersClient(helper.subscriptionID)
|
||||
helper.providersClient.Authorizer = helper.authorizer
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (helper *azureHelper) getAzureLocations(ctx context.Context) error {
|
||||
providers, err := helper.listProviders(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var computeProvider resources.Provider
|
||||
|
||||
for _, provider := range providers {
|
||||
if provider.Namespace != nil && *provider.Namespace == "Microsoft.Compute" {
|
||||
computeProvider = provider
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
helper.locations = make(map[string]Location)
|
||||
|
||||
if computeProvider.ResourceTypes != nil {
|
||||
for _, rt := range *computeProvider.ResourceTypes {
|
||||
if rt.ResourceType != nil && *rt.ResourceType == "virtualMachines" {
|
||||
if rt.Locations != nil {
|
||||
for _, region := range *rt.Locations {
|
||||
abbr := strings.ReplaceAll(region, " ", "")
|
||||
abbr = strings.ToLower(abbr)
|
||||
helper.locations[abbr] = Location{Abbreviation: abbr, Name: region}
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (helper *azureHelper) listProviders(ctx context.Context) (result []resources.Provider, err error) {
|
||||
for list, err := helper.providersClient.List(ctx, ""); list.NotDone(); err = list.NextWithContext(ctx) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting providers list: %v", err)
|
||||
}
|
||||
|
||||
result = append(result, list.Values()...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (helper *azureHelper) deployResourceFromTemplate(ctx context.Context, templateBytes []byte, parameters map[string]interface{}, deploymentName string) error {
|
||||
// Create a new instance of the DeploymentsClient
|
||||
deploymentsClient, err := armresources.NewDeploymentsClient(helper.subscriptionID, helper.cred, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Replace these variables with your own values
|
||||
resourceGroupName := "SideroGallery"
|
||||
|
||||
// Parse the template JSON
|
||||
var template map[string]interface{}
|
||||
|
||||
if err = json.Unmarshal(templateBytes, &template); err != nil {
|
||||
return fmt.Errorf("failed to parse template JSON: %w", err)
|
||||
}
|
||||
|
||||
deployment := armresources.Deployment{
|
||||
Properties: &armresources.DeploymentProperties{
|
||||
Template: template,
|
||||
Parameters: parameters,
|
||||
Mode: to.Ptr(armresources.DeploymentModeIncremental),
|
||||
},
|
||||
}
|
||||
|
||||
poller, err := deploymentsClient.BeginCreateOrUpdate(ctx, resourceGroupName, deploymentName, deployment, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create deployment: %w", err)
|
||||
}
|
||||
|
||||
// PollUntilDone requires a context and a poll interval
|
||||
result, err := poller.PollUntilDone(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to poll deployment status: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Deployment operation for %s: %+v\n", *result.Name, *result.Properties.ProvisioningState)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -3,15 +3,41 @@ module github.com/siderolabs/cloud-image-uploader
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0
|
||||
github.com/Azure/go-autorest/autorest v0.11.29
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12
|
||||
github.com/aws/aws-sdk-go v1.44.264
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/siderolabs/gen v0.4.5
|
||||
github.com/siderolabs/go-retry v0.3.2
|
||||
github.com/spf13/pflag v1.0.5
|
||||
golang.org/x/sync v0.2.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
)
|
||||
|
||||
@ -1,49 +1,125 @@
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0 h1:LcJtQjCXJUm1s7JpUHZvu+bpgURhCatxVNbGADXniX0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.3.0/go.mod h1:+OgGVo0Httq7N5oayfvaLQ/Jq+2gJdqfp++Hyyl7Tws=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
|
||||
github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
|
||||
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
|
||||
github.com/aws/aws-sdk-go v1.44.264 h1:5klL62ebn6uv3oJ0ixF7K12hKItj8lV3QqWeQPlkFSs=
|
||||
github.com/aws/aws-sdk-go v1.44.264/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
|
||||
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/siderolabs/gen v0.4.5 h1:rwXUVJlL7hYza1LrSVXfT905ZC9Rgei37jMKKs/+eP0=
|
||||
github.com/siderolabs/gen v0.4.5/go.mod h1:wS8tFq7sn5vqKAuyS30vJUig3tX5v6q79VG4KfUnILM=
|
||||
github.com/siderolabs/go-retry v0.3.2 h1:FzWslFm4y8RY1wU0gIskm0oZHOpsSibZqlR8N8/k4Eo=
|
||||
github.com/siderolabs/go-retry v0.3.2/go.mod h1:Ac8HIh0nAYDQm04FGZHNofVAXteyd4xR9oujTRrtvK0=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
@ -51,4 +127,4 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package main implements Talos cloud image uploader.
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -9,6 +10,7 @@ import (
|
||||
cryptorand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
@ -46,6 +48,12 @@ func pushResult(image CloudImage) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
log.Fatalf("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
var err error
|
||||
|
||||
DefaultOptions.AWSRegions, err = GetAWSDefaultRegions()
|
||||
@ -62,11 +70,11 @@ func main() {
|
||||
pflag.Parse()
|
||||
|
||||
seed := make([]byte, 8)
|
||||
if _, err := cryptorand.Read(seed); err != nil {
|
||||
if _, err = cryptorand.Read(seed); err != nil {
|
||||
log.Fatalf("error seeding rand: %s", err)
|
||||
}
|
||||
|
||||
rand.Seed(int64(binary.LittleEndian.Uint64(seed)))
|
||||
rand.Seed(int64(binary.LittleEndian.Uint64(seed))) //nolint:staticcheck
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@ -83,18 +91,27 @@ func main() {
|
||||
return aws.Upload(ctx)
|
||||
})
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
log.Fatalf("failed: %s", err)
|
||||
g.Go(func() error {
|
||||
azure := AzureUploader{
|
||||
Options: DefaultOptions,
|
||||
}
|
||||
|
||||
return azure.AzureGalleryUpload(ctx)
|
||||
})
|
||||
|
||||
if err = g.Wait(); err != nil {
|
||||
return fmt.Errorf("failed: %w", err)
|
||||
}
|
||||
|
||||
f, err := os.Create(filepath.Join(DefaultOptions.ArtifactsPath, "cloud-images.json"))
|
||||
if err != nil {
|
||||
log.Fatalf("failed: %s", err)
|
||||
return fmt.Errorf("failed: %w", err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
e := json.NewEncoder(io.MultiWriter(os.Stdout, f))
|
||||
e.SetIndent("", " ")
|
||||
e.Encode(&result) //nolint:errcheck
|
||||
|
||||
return e.Encode(&result)
|
||||
}
|
||||
|
||||
@ -15,7 +15,17 @@ type Options struct {
|
||||
ArtifactsPath string
|
||||
Architectures []string
|
||||
|
||||
// AWS options.
|
||||
AWSRegions []string
|
||||
|
||||
// Azure options.
|
||||
AzureRegions []Location
|
||||
}
|
||||
|
||||
// Location is the struct for the Azure Regions Options.
|
||||
type Location struct {
|
||||
Abbreviation string
|
||||
Name string
|
||||
}
|
||||
|
||||
// DefaultOptions used throughout the cli.
|
||||
@ -28,3 +38,8 @@ var DefaultOptions = Options{
|
||||
func (o *Options) AWSImage(architecture string) string {
|
||||
return filepath.Join(o.ArtifactsPath, fmt.Sprintf("aws-%s.tar.gz", architecture))
|
||||
}
|
||||
|
||||
// AzureImage returns path to AWS pre-built image.
|
||||
func (o *Options) AzureImage(architecture string) string {
|
||||
return filepath.Join(o.ArtifactsPath, fmt.Sprintf("azure-%s.tar.gz", architecture))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user