mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-03 12:36:09 -04:00
cli: install helm charts in cli instead of bootstrapper (#2136)
* init * fixup! init * gcp working? * fixup! fixup! init * azure cfg for microService installation * fixup! azure cfg for microService installation * fixup! azure cfg for microService installation * cleanup bootstrapper code * cleanup helminstall code * fixup! cleanup helminstall code * Update internal/deploy/helm/install.go Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> * daniel feedback * TODO add provider (also to CreateCluster) so we can ensure that provider specific output * fixup! daniel feedback * use debugLog in helm installer * placeholderHelmInstaller * rename to stub --------- Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
This commit is contained in:
parent
ef60d00a60
commit
26305e8f80
38 changed files with 775 additions and 970 deletions
|
@ -17,7 +17,6 @@ package azure
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
|
@ -99,61 +98,6 @@ func New(ctx context.Context) (*Cloud, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// GetCCMConfig returns the configuration needed for the Kubernetes Cloud Controller Manager on Azure.
|
||||
func (c *Cloud) GetCCMConfig(ctx context.Context, providerID string, cloudServiceAccountURI string) ([]byte, error) {
|
||||
subscriptionID, resourceGroup, err := azureshared.BasicsFromProviderID(providerID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing provider ID: %w", err)
|
||||
}
|
||||
creds, err := azureshared.ApplicationCredentialsFromURI(cloudServiceAccountURI)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing service account URI: %w", err)
|
||||
}
|
||||
uid, err := c.imds.uid(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving instance UID: %w", err)
|
||||
}
|
||||
|
||||
securityGroupName, err := c.getNetworkSecurityGroupName(ctx, resourceGroup, uid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving network security group name: %w", err)
|
||||
}
|
||||
|
||||
loadBalancer, err := c.getLoadBalancer(ctx, resourceGroup, uid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving load balancer: %w", err)
|
||||
}
|
||||
if loadBalancer == nil || loadBalancer.Name == nil {
|
||||
return nil, fmt.Errorf("could not dereference load balancer name")
|
||||
}
|
||||
|
||||
var uamiClientID string
|
||||
useManagedIdentityExtension := creds.PreferredAuthMethod == azureshared.AuthMethodUserAssignedIdentity
|
||||
if useManagedIdentityExtension {
|
||||
uamiClientID, err = c.getUAMIClientIDFromURI(ctx, providerID, creds.UamiResourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving user-assigned managed identity client ID: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
config := cloudConfig{
|
||||
Cloud: "AzurePublicCloud",
|
||||
TenantID: creds.TenantID,
|
||||
SubscriptionID: subscriptionID,
|
||||
ResourceGroup: resourceGroup,
|
||||
LoadBalancerSku: "standard",
|
||||
SecurityGroupName: securityGroupName,
|
||||
LoadBalancerName: *loadBalancer.Name,
|
||||
UseInstanceMetadata: true,
|
||||
VMType: "vmss",
|
||||
Location: creds.Location,
|
||||
UseManagedIdentityExtension: useManagedIdentityExtension,
|
||||
UserAssignedIdentityID: uamiClientID,
|
||||
}
|
||||
|
||||
return json.Marshal(config)
|
||||
}
|
||||
|
||||
// GetLoadBalancerEndpoint retrieves the first load balancer IP from cloud provider metadata.
|
||||
//
|
||||
// The returned string is an IP address without a port, but the method name needs to satisfy the
|
||||
|
@ -286,24 +230,6 @@ func (c *Cloud) getInstance(ctx context.Context, providerID string) (metadata.In
|
|||
return instance, nil
|
||||
}
|
||||
|
||||
func (c *Cloud) getUAMIClientIDFromURI(ctx context.Context, providerID, resourceID string) (string, error) {
|
||||
// userAssignedIdentityURI := "/subscriptions/{subscription-id}/resourcegroups/{resource-group}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identity-name}"
|
||||
_, resourceGroup, scaleSet, instanceID, err := azureshared.ScaleSetInformationFromProviderID(providerID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid provider ID: %w", err)
|
||||
}
|
||||
vmResp, err := c.scaleSetsVMAPI.Get(ctx, resourceGroup, scaleSet, instanceID, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("retrieving instance: %w", err)
|
||||
}
|
||||
for rID, v := range vmResp.Identity.UserAssignedIdentities {
|
||||
if rID == resourceID {
|
||||
return *v.ClientID, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no user assinged identity found for resource ID %s", resourceID)
|
||||
}
|
||||
|
||||
// getNetworkSecurityGroupName returns the security group name of the resource group.
|
||||
func (c *Cloud) getNetworkSecurityGroupName(ctx context.Context, resourceGroup, uid string) (string, error) {
|
||||
pager := c.secGroupAPI.NewListPager(resourceGroup, nil)
|
||||
|
@ -462,26 +388,6 @@ func (c *Cloud) getLoadBalancerDNSName(ctx context.Context) (string, error) {
|
|||
}
|
||||
*/
|
||||
|
||||
type cloudConfig struct {
|
||||
Cloud string `json:"cloud,omitempty"`
|
||||
TenantID string `json:"tenantId,omitempty"`
|
||||
SubscriptionID string `json:"subscriptionId,omitempty"`
|
||||
ResourceGroup string `json:"resourceGroup,omitempty"`
|
||||
Location string `json:"location,omitempty"`
|
||||
SubnetName string `json:"subnetName,omitempty"`
|
||||
SecurityGroupName string `json:"securityGroupName,omitempty"`
|
||||
SecurityGroupResourceGroup string `json:"securityGroupResourceGroup,omitempty"`
|
||||
LoadBalancerName string `json:"loadBalancerName,omitempty"`
|
||||
LoadBalancerSku string `json:"loadBalancerSku,omitempty"`
|
||||
VNetName string `json:"vnetName,omitempty"`
|
||||
VNetResourceGroup string `json:"vnetResourceGroup,omitempty"`
|
||||
CloudProviderBackoff bool `json:"cloudProviderBackoff,omitempty"`
|
||||
UseInstanceMetadata bool `json:"useInstanceMetadata,omitempty"`
|
||||
VMType string `json:"vmType,omitempty"`
|
||||
UseManagedIdentityExtension bool `json:"useManagedIdentityExtension,omitempty"`
|
||||
UserAssignedIdentityID string `json:"userAssignedIdentityID,omitempty"`
|
||||
}
|
||||
|
||||
// convertToInstanceMetadata converts a armcomputev2.VirtualMachineScaleSetVM to a metadata.InstanceMetadata.
|
||||
func convertToInstanceMetadata(vm armcompute.VirtualMachineScaleSetVM, networkInterfaces []armnetwork.Interface,
|
||||
) (metadata.InstanceMetadata, error) {
|
||||
|
|
|
@ -8,7 +8,6 @@ package azure
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
|
@ -28,336 +27,6 @@ func TestMain(m *testing.M) {
|
|||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
|
||||
func TestGetCCMConfig(t *testing.T) {
|
||||
someErr := errors.New("failed")
|
||||
goodLB := armnetwork.LoadBalancer{
|
||||
Name: to.Ptr("load-balancer"),
|
||||
Tags: map[string]*string{
|
||||
cloud.TagUID: to.Ptr("uid"),
|
||||
},
|
||||
Properties: &armnetwork.LoadBalancerPropertiesFormat{
|
||||
FrontendIPConfigurations: []*armnetwork.FrontendIPConfiguration{
|
||||
{
|
||||
Properties: &armnetwork.FrontendIPConfigurationPropertiesFormat{
|
||||
PublicIPAddress: &armnetwork.PublicIPAddress{ID: to.Ptr("/subscriptions/subscription/resourceGroups/resourceGroup/providers/Microsoft.Network/publicIPAddresses/pubIPName")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
goodSecurityGroup := armnetwork.SecurityGroup{
|
||||
Tags: map[string]*string{
|
||||
cloud.TagUID: to.Ptr("uid"),
|
||||
},
|
||||
Name: to.Ptr("security-group"),
|
||||
}
|
||||
|
||||
uamiClientID := "uami-client-id"
|
||||
|
||||
testCases := map[string]struct {
|
||||
imdsAPI imdsAPI
|
||||
loadBalancerAPI loadBalancerAPI
|
||||
secGroupAPI securityGroupsAPI
|
||||
scaleSetsVMAPI virtualMachineScaleSetVMsAPI
|
||||
providerID string
|
||||
cloudServiceAccountURI string
|
||||
wantErr bool
|
||||
wantConfig cloudConfig
|
||||
}{
|
||||
"success": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
scaleSetsVMAPI: &stubVirtualMachineScaleSetVMsAPI{
|
||||
getVM: armcompute.VirtualMachineScaleSetVM{
|
||||
Identity: &armcompute.VirtualMachineIdentity{
|
||||
UserAssignedIdentities: map[string]*armcompute.UserAssignedIdentitiesValue{
|
||||
"subscriptions/9b352db0-82af-408c-a02c-36fbffbf7015/resourceGroups/resourceGroupName/providers/Microsoft.ManagedIdentity/userAssignedIdentities/UAMIName": {ClientID: &uamiClientID},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope&preferred_auth_method=userassignedidentity&uami_resource_id=subscriptions%2F9b352db0-82af-408c-a02c-36fbffbf7015%2FresourceGroups%2FresourceGroupName%2Fproviders%2FMicrosoft.ManagedIdentity%2FuserAssignedIdentities%2FUAMIName",
|
||||
wantConfig: cloudConfig{
|
||||
Cloud: "AzurePublicCloud",
|
||||
TenantID: "tenant-id",
|
||||
SubscriptionID: "subscription-id",
|
||||
ResourceGroup: "resource-group",
|
||||
LoadBalancerSku: "standard",
|
||||
SecurityGroupName: "security-group",
|
||||
LoadBalancerName: "load-balancer",
|
||||
UseInstanceMetadata: true,
|
||||
UseManagedIdentityExtension: true,
|
||||
UserAssignedIdentityID: uamiClientID,
|
||||
VMType: "vmss",
|
||||
Location: "westeurope",
|
||||
},
|
||||
},
|
||||
"no app registration": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&location=westeurope",
|
||||
wantConfig: cloudConfig{
|
||||
Cloud: "AzurePublicCloud",
|
||||
TenantID: "tenant-id",
|
||||
SubscriptionID: "subscription-id",
|
||||
ResourceGroup: "resource-group",
|
||||
LoadBalancerSku: "standard",
|
||||
SecurityGroupName: "security-group",
|
||||
LoadBalancerName: "load-balancer",
|
||||
UseInstanceMetadata: true,
|
||||
VMType: "vmss",
|
||||
Location: "westeurope",
|
||||
},
|
||||
},
|
||||
"missing UID tag": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{
|
||||
{
|
||||
Name: to.Ptr("load-balancer"),
|
||||
Properties: &armnetwork.LoadBalancerPropertiesFormat{
|
||||
FrontendIPConfigurations: []*armnetwork.FrontendIPConfiguration{
|
||||
{
|
||||
Properties: &armnetwork.FrontendIPConfigurationPropertiesFormat{
|
||||
PublicIPAddress: &armnetwork.PublicIPAddress{ID: to.Ptr("/subscriptions/subscription/resourceGroups/resourceGroup/providers/Microsoft.Network/publicIPAddresses/pubIPName")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"only correct UID is chosen": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{
|
||||
{
|
||||
Name: to.Ptr("load-balancer"),
|
||||
Tags: map[string]*string{
|
||||
cloud.TagUID: to.Ptr("different-uid"),
|
||||
},
|
||||
Properties: &armnetwork.LoadBalancerPropertiesFormat{
|
||||
FrontendIPConfigurations: []*armnetwork.FrontendIPConfiguration{
|
||||
{
|
||||
Properties: &armnetwork.FrontendIPConfigurationPropertiesFormat{
|
||||
PublicIPAddress: &armnetwork.PublicIPAddress{ID: to.Ptr("/subscriptions/subscription/resourceGroups/resourceGroup/providers/Microsoft.Network/publicIPAddresses/pubIPName")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
goodLB,
|
||||
},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantConfig: cloudConfig{
|
||||
Cloud: "AzurePublicCloud",
|
||||
TenantID: "tenant-id",
|
||||
SubscriptionID: "subscription-id",
|
||||
ResourceGroup: "resource-group",
|
||||
LoadBalancerSku: "standard",
|
||||
SecurityGroupName: "security-group",
|
||||
LoadBalancerName: "load-balancer",
|
||||
UseInstanceMetadata: true,
|
||||
VMType: "vmss",
|
||||
Location: "westeurope",
|
||||
},
|
||||
},
|
||||
"load balancer list error": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
fetchErr: someErr,
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"missing load balancer name": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{{
|
||||
Tags: map[string]*string{
|
||||
cloud.TagUID: to.Ptr("uid"),
|
||||
},
|
||||
Properties: &armnetwork.LoadBalancerPropertiesFormat{
|
||||
FrontendIPConfigurations: []*armnetwork.FrontendIPConfiguration{
|
||||
{
|
||||
Properties: &armnetwork.FrontendIPConfigurationPropertiesFormat{
|
||||
PublicIPAddress: &armnetwork.PublicIPAddress{ID: to.Ptr("/subscriptions/subscription/resourceGroups/resourceGroup/providers/Microsoft.Network/publicIPAddresses/pubIPName")},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"security group list error": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
fetchErr: someErr,
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"invalid provider ID": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "invalid:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"invalid cloud service account URI": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidVal: "uid",
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "invalid://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
"imds error": {
|
||||
imdsAPI: &stubIMDSAPI{
|
||||
uidErr: someErr,
|
||||
},
|
||||
loadBalancerAPI: &stubLoadBalancersAPI{
|
||||
pager: &stubLoadBalancersClientListPager{
|
||||
list: []armnetwork.LoadBalancer{goodLB},
|
||||
},
|
||||
},
|
||||
secGroupAPI: &stubSecurityGroupsAPI{
|
||||
pager: &stubSecurityGroupsClientListPager{
|
||||
list: []armnetwork.SecurityGroup{goodSecurityGroup},
|
||||
},
|
||||
},
|
||||
providerID: "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set/virtualMachines/0",
|
||||
cloudServiceAccountURI: "serviceaccount://azure?tenant_id=tenant-id&client_id=client-id&client_secret=client-secret&location=westeurope",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
cloud := &Cloud{
|
||||
imds: tc.imdsAPI,
|
||||
loadBalancerAPI: tc.loadBalancerAPI,
|
||||
secGroupAPI: tc.secGroupAPI,
|
||||
scaleSetsVMAPI: tc.scaleSetsVMAPI,
|
||||
}
|
||||
config, err := cloud.GetCCMConfig(context.Background(), tc.providerID, tc.cloudServiceAccountURI)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
|
||||
wantConfig, err := json.Marshal(tc.wantConfig)
|
||||
require.NoError(err)
|
||||
assert.JSONEq(string(wantConfig), string(config))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstance(t *testing.T) {
|
||||
someErr := errors.New("failed")
|
||||
sampleProviderID := "azure:///subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id"
|
||||
|
|
|
@ -9,13 +9,21 @@ package azureshared
|
|||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
subscriptionPattern = regexp.MustCompile(`subscriptions/([^/]+)/`)
|
||||
rgPattern = regexp.MustCompile(`resourceGroups/([^/]+)/`)
|
||||
)
|
||||
|
||||
// ApplicationCredentials is a set of Azure API credentials.
|
||||
// It can contain a client secret and carries the preferred authentication method.
|
||||
// It is the equivalent of a service account key in other cloud providers.
|
||||
type ApplicationCredentials struct {
|
||||
SubscriptionID string
|
||||
ResourceGroup string
|
||||
TenantID string
|
||||
AppClientID string
|
||||
ClientSecretValue string
|
||||
|
@ -37,8 +45,14 @@ func ApplicationCredentialsFromURI(cloudServiceAccountURI string) (ApplicationCr
|
|||
return ApplicationCredentials{}, fmt.Errorf("invalid service account URI: invalid host: %s", uri.Host)
|
||||
}
|
||||
query := uri.Query()
|
||||
|
||||
subscriptionID := getFirstMatchOrEmpty(subscriptionPattern, query.Get("uami_resource_id"))
|
||||
resourceGroup := getFirstMatchOrEmpty(rgPattern, query.Get("uami_resource_id"))
|
||||
|
||||
preferredAuthMethod := FromString(query.Get("preferred_auth_method"))
|
||||
return ApplicationCredentials{
|
||||
SubscriptionID: subscriptionID,
|
||||
ResourceGroup: resourceGroup,
|
||||
TenantID: query.Get("tenant_id"),
|
||||
AppClientID: query.Get("client_id"),
|
||||
ClientSecretValue: query.Get("client_secret"),
|
||||
|
@ -48,6 +62,15 @@ func ApplicationCredentialsFromURI(cloudServiceAccountURI string) (ApplicationCr
|
|||
}, nil
|
||||
}
|
||||
|
||||
func getFirstMatchOrEmpty(pattern *regexp.Regexp, str string) string {
|
||||
subscriptionMatches := pattern.FindStringSubmatch(str)
|
||||
var subscriptionID string
|
||||
if len(subscriptionMatches) > 1 {
|
||||
subscriptionID = subscriptionMatches[1]
|
||||
}
|
||||
return subscriptionID
|
||||
}
|
||||
|
||||
// ToCloudServiceAccountURI converts the ApplicationCredentials into a cloud service account URI.
|
||||
func (c ApplicationCredentials) ToCloudServiceAccountURI() string {
|
||||
query := url.Values{}
|
||||
|
|
|
@ -27,12 +27,16 @@ func TestApplicationCredentialsFromURI(t *testing.T) {
|
|||
Location: "location",
|
||||
UamiResourceID: "subscriptions/9b352db0-82af-408c-a02c-36fbffbf7015/resourceGroups/resourceGroupName/providers/Microsoft.ManagedIdentity/userAssignedIdentities/UAMIName",
|
||||
PreferredAuthMethod: AuthMethodServicePrincipal,
|
||||
SubscriptionID: "9b352db0-82af-408c-a02c-36fbffbf7015",
|
||||
ResourceGroup: "resourceGroupName",
|
||||
}
|
||||
credsWithoutSecret := ApplicationCredentials{
|
||||
TenantID: "tenant-id",
|
||||
Location: "location",
|
||||
UamiResourceID: "subscriptions/9b352db0-82af-408c-a02c-36fbffbf7015/resourceGroups/resourceGroupName/providers/Microsoft.ManagedIdentity/userAssignedIdentities/UAMIName",
|
||||
PreferredAuthMethod: AuthMethodUserAssignedIdentity,
|
||||
SubscriptionID: "9b352db0-82af-408c-a02c-36fbffbf7015",
|
||||
ResourceGroup: "resourceGroupName",
|
||||
}
|
||||
credsWithoutPreferrredAuthMethod := ApplicationCredentials{
|
||||
TenantID: "tenant-id",
|
||||
|
|
|
@ -11,10 +11,8 @@ go_library(
|
|||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/constants",
|
||||
"//internal/logger",
|
||||
"//internal/retry",
|
||||
"@io_k8s_apimachinery//pkg/util/wait",
|
||||
"@org_uber_go_zap//:zap",
|
||||
"@sh_helm_helm_v3//pkg/action",
|
||||
"@sh_helm_helm_v3//pkg/chart",
|
||||
"@sh_helm_helm_v3//pkg/chart/loader",
|
||||
|
|
|
@ -14,9 +14,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/edgelesssys/constellation/v2/internal/retry"
|
||||
"go.uber.org/zap"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
|
@ -31,20 +29,25 @@ const (
|
|||
maximumRetryAttempts = 3
|
||||
)
|
||||
|
||||
type debugLog interface {
|
||||
Debugf(format string, args ...any)
|
||||
Sync()
|
||||
}
|
||||
|
||||
// Installer is a wrapper for a helm install action.
|
||||
type Installer struct {
|
||||
*action.Install
|
||||
log *logger.Logger
|
||||
log debugLog
|
||||
}
|
||||
|
||||
// NewInstaller creates a new Installer with the given logger.
|
||||
func NewInstaller(log *logger.Logger, kubeconfig string) (*Installer, error) {
|
||||
func NewInstaller(kubeconfig string, logger debugLog) (*Installer, error) {
|
||||
settings := cli.New()
|
||||
settings.KubeConfig = kubeconfig
|
||||
|
||||
actionConfig := &action.Configuration{}
|
||||
if err := actionConfig.Init(settings.RESTClientGetter(), constants.HelmNamespace,
|
||||
"secret", log.Infof); err != nil {
|
||||
"secret", logger.Debugf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -53,13 +56,12 @@ func NewInstaller(log *logger.Logger, kubeconfig string) (*Installer, error) {
|
|||
action.Timeout = timeout
|
||||
|
||||
return &Installer{
|
||||
action,
|
||||
log,
|
||||
Install: action,
|
||||
log: logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InstallChart is the generic install function for helm charts.
|
||||
// When timeout is nil, the default timeout is used.
|
||||
func (h *Installer) InstallChart(ctx context.Context, release Release) error {
|
||||
return h.InstallChartWithValues(ctx, release, nil)
|
||||
}
|
||||
|
@ -115,7 +117,7 @@ func (h *Installer) install(ctx context.Context, chartRaw []byte, values map[str
|
|||
return fmt.Errorf("helm install: %w", err)
|
||||
}
|
||||
retryLoopFinishDuration := time.Since(retryLoopStartTime)
|
||||
h.log.With(zap.String("chart", chart.Name()), zap.Duration("duration", retryLoopFinishDuration)).Infof("Helm chart installation finished")
|
||||
h.log.Debugf("Helm chart %q installation finished after %s", chart.Name(), retryLoopFinishDuration)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -143,15 +145,14 @@ type installDoer struct {
|
|||
Installer *Installer
|
||||
chart *chart.Chart
|
||||
values map[string]any
|
||||
log *logger.Logger
|
||||
log debugLog
|
||||
}
|
||||
|
||||
// Do logs which chart is installed and tries to install it.
|
||||
func (i installDoer) Do(ctx context.Context) error {
|
||||
i.log.With(zap.String("chart", i.chart.Name())).Infof("Trying to install Helm chart")
|
||||
|
||||
i.log.Debugf("Trying to install Helm chart %s", i.chart.Name())
|
||||
if _, err := i.Installer.RunWithContext(ctx, i.chart, i.values); err != nil {
|
||||
i.log.With(zap.Error(err), zap.String("chart", i.chart.Name())).Errorf("Helm chart installation failed")
|
||||
i.log.Debugf("Helm chart installation % failed: %v", i.chart.Name(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue