[node operator] Read azure config from k8s secret

Signed-off-by: Malte Poll <mp@edgeless.systems>
This commit is contained in:
Malte Poll 2022-07-22 16:28:09 +02:00 committed by Malte Poll
parent 3495ec1c07
commit 50ed6777c8
8 changed files with 134 additions and 5 deletions

View file

@ -4,6 +4,7 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
"github.com/edgelesssys/constellation/operators/constellation-node-operator/internal/poller"
"github.com/spf13/afero"
)
// Client is a client for the Azure Cloud.
@ -15,17 +16,22 @@ type Client struct {
}
// NewFromDefault creates a client with initialized clients.
func NewFromDefault(subscriptionID, tenantID string) (*Client, error) {
func NewFromDefault(configPath string) (*Client, error) {
config, err := loadConfig(afero.NewOsFs(), configPath)
if err != nil {
return nil, err
}
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return nil, err
}
scaleSetAPI, err := armcomputev2.NewVirtualMachineScaleSetsClient(subscriptionID, cred, nil)
scaleSetAPI, err := armcomputev2.NewVirtualMachineScaleSetsClient(config.SubscriptionID, cred, nil)
if err != nil {
return nil, err
}
virtualMachineScaleSetVMsAPI, err := armcomputev2.NewVirtualMachineScaleSetVMsClient(subscriptionID, cred, nil)
virtualMachineScaleSetVMsAPI, err := armcomputev2.NewVirtualMachineScaleSetVMsClient(config.SubscriptionID, cred, nil)
if err != nil {
return nil, err
}

View file

@ -0,0 +1,32 @@
package client
import (
"encoding/json"
"errors"
"github.com/spf13/afero"
)
// cloudConfig uses same format as azure cloud controller manager to share the same kubernetes secret.
// this definition only contains the fields we need.
// reference: https://cloud-provider-azure.sigs.k8s.io/install/configs/ .
type cloudConfig struct {
TenantID string `json:"tenantId,omitempty"`
SubscriptionID string `json:"subscriptionId,omitempty"`
}
// loadConfig loads the cloud config from the given path.
func loadConfig(fs afero.Fs, path string) (*cloudConfig, error) {
rawConfig, err := afero.ReadFile(fs, path)
if err != nil {
return nil, err
}
var config cloudConfig
if err := json.Unmarshal(rawConfig, &config); err != nil {
return nil, err
}
if config.TenantID == "" || config.SubscriptionID == "" {
return nil, errors.New("invalid config: tenantId and subscriptionId are required")
}
return &config, nil
}

View file

@ -0,0 +1,56 @@
package client
import (
"testing"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLoadConfig(t *testing.T) {
testCases := map[string]struct {
rawConfig string
skipWrite bool
wantTenantID string
wantSubscriptionID string
wantErr bool
}{
"valid config": {
rawConfig: `{"tenantId":"tenantId","subscriptionId":"subscriptionId"}`,
wantTenantID: "tenantId",
wantSubscriptionID: "subscriptionId",
},
"invalid config": {
rawConfig: `{"tenantId":"tenantId","subscriptionId":""}`,
wantErr: true,
},
"config is empty": {
wantErr: true,
},
"config does not exist": {
skipWrite: true,
wantErr: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
fs := afero.NewMemMapFs()
if !tc.skipWrite {
require.NoError(afero.WriteFile(fs, "config.json", []byte(tc.rawConfig), 0o644))
}
gotConfig, err := loadConfig(fs, "config.json")
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.wantTenantID, gotConfig.TenantID)
assert.Equal(tc.wantSubscriptionID, gotConfig.SubscriptionID)
})
}
}