mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
107 lines
4.0 KiB
Go
107 lines
4.0 KiB
Go
|
package azure
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"regexp"
|
||
|
|
||
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute"
|
||
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
|
||
|
"github.com/Azure/go-autorest/autorest/to"
|
||
|
"github.com/edgelesssys/constellation/coordinator/cloudprovider"
|
||
|
"github.com/edgelesssys/constellation/coordinator/core"
|
||
|
)
|
||
|
|
||
|
// getVM tries to get a single azure vm.
|
||
|
func (m *Metadata) getVM(ctx context.Context, providerID string) (core.Instance, error) {
|
||
|
_, resourceGroup, instanceName, err := splitVMProviderID(providerID)
|
||
|
if err != nil {
|
||
|
return core.Instance{}, err
|
||
|
}
|
||
|
vmResp, err := m.virtualMachinesAPI.Get(ctx, resourceGroup, instanceName, nil)
|
||
|
if err != nil {
|
||
|
return core.Instance{}, err
|
||
|
}
|
||
|
interfaceIPConfigurations, err := m.getVMInterfaces(ctx, vmResp.VirtualMachine, resourceGroup)
|
||
|
if err != nil {
|
||
|
return core.Instance{}, err
|
||
|
}
|
||
|
return convertVMToCoreInstance(vmResp.VirtualMachine, interfaceIPConfigurations)
|
||
|
}
|
||
|
|
||
|
// listVMs lists all individual VMs in the current resource group.
|
||
|
func (m *Metadata) listVMs(ctx context.Context, resourceGroup string) ([]core.Instance, error) {
|
||
|
instances := []core.Instance{}
|
||
|
pager := m.virtualMachinesAPI.List(resourceGroup, nil)
|
||
|
for pager.NextPage(ctx) {
|
||
|
for _, vm := range pager.PageResponse().Value {
|
||
|
if vm == nil {
|
||
|
continue
|
||
|
}
|
||
|
interfaces, err := m.getVMInterfaces(ctx, *vm, resourceGroup)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
instance, err := convertVMToCoreInstance(*vm, interfaces)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
instances = append(instances, instance)
|
||
|
}
|
||
|
}
|
||
|
return instances, nil
|
||
|
}
|
||
|
|
||
|
// setTag merges key-value pair into VM tags.
|
||
|
func (m *Metadata) setTag(ctx context.Context, key, value string) error {
|
||
|
instanceMetadata, err := m.imdsAPI.Retrieve(ctx)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
_, err = m.tagsAPI.UpdateAtScope(ctx, instanceMetadata.Compute.ResourceID, armresources.TagsPatchResource{
|
||
|
Operation: armresources.TagsPatchOperationMerge.ToPtr(),
|
||
|
Properties: &armresources.Tags{
|
||
|
Tags: map[string]*string{
|
||
|
key: to.StringPtr(value),
|
||
|
},
|
||
|
},
|
||
|
}, nil)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// splitVMProviderID splits a provider's id belonging to a single azure instance into core components.
|
||
|
// A providerID for individual VMs is build after the following schema:
|
||
|
// - 'azure:///subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Compute/virtualMachines/<instance-name>'
|
||
|
func splitVMProviderID(providerID string) (subscriptionID, resourceGroup, instanceName string, err error) {
|
||
|
// providerIDregex is a regex matching an azure vm providerID with each part of the URI being a submatch.
|
||
|
providerIDregex := regexp.MustCompile(`^azure:///subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/Microsoft.Compute/virtualMachines/([^/]+)$`)
|
||
|
matches := providerIDregex.FindStringSubmatch(providerID)
|
||
|
if len(matches) != 4 {
|
||
|
return "", "", "", errors.New("error splitting providerID")
|
||
|
}
|
||
|
return matches[1], matches[2], matches[3], nil
|
||
|
}
|
||
|
|
||
|
// convertVMToCoreInstance converts an azure virtual machine with interface configurations into a core.Instance.
|
||
|
func convertVMToCoreInstance(vm armcompute.VirtualMachine, interfaceIPConfigs []*armnetwork.InterfaceIPConfiguration) (core.Instance, error) {
|
||
|
if vm.Name == nil || vm.ID == nil {
|
||
|
return core.Instance{}, fmt.Errorf("retrieving instance from armcompute API client returned invalid instance Name (%v) or ID (%v)", vm.Name, vm.ID)
|
||
|
}
|
||
|
var sshKeys map[string][]string
|
||
|
if vm.Properties == nil || vm.Properties.OSProfile == nil || vm.Properties.OSProfile.LinuxConfiguration == nil || vm.Properties.OSProfile.LinuxConfiguration.SSH == nil {
|
||
|
sshKeys = map[string][]string{}
|
||
|
} else {
|
||
|
sshKeys = extractSSHKeys(*vm.Properties.OSProfile.LinuxConfiguration.SSH)
|
||
|
}
|
||
|
metadata := extractInstanceTags(vm.Tags)
|
||
|
return core.Instance{
|
||
|
Name: *vm.Name,
|
||
|
ProviderID: "azure://" + *vm.ID,
|
||
|
Role: cloudprovider.ExtractRole(metadata),
|
||
|
IPs: extractPrivateIPs(interfaceIPConfigs),
|
||
|
SSHKeys: sshKeys,
|
||
|
}, nil
|
||
|
}
|