2021-02-24 15:34:51 +03:00
|
|
|
package cluster
|
|
|
|
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the Apache License 2.0.
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-11-28 18:45:00 +03:00
|
|
|
"errors"
|
2021-02-24 15:34:51 +03:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
mgmtauthorization "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-09-01-preview/authorization"
|
|
|
|
mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features"
|
|
|
|
"github.com/Azure/go-autorest/autorest/to"
|
|
|
|
operatorv1 "github.com/openshift/api/operator/v1"
|
|
|
|
operatorfake "github.com/openshift/client-go/operator/clientset/versioned/fake"
|
|
|
|
"github.com/sirupsen/logrus"
|
2024-09-25 01:35:34 +03:00
|
|
|
"go.uber.org/mock/gomock"
|
2021-02-24 15:34:51 +03:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2023-08-28 22:23:42 +03:00
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2021-02-24 15:34:51 +03:00
|
|
|
"k8s.io/client-go/kubernetes/fake"
|
2023-11-28 18:45:00 +03:00
|
|
|
fakecorev1 "k8s.io/client-go/kubernetes/typed/core/v1/fake"
|
2023-08-28 22:23:42 +03:00
|
|
|
ktesting "k8s.io/client-go/testing"
|
2024-07-10 02:57:42 +03:00
|
|
|
"sigs.k8s.io/yaml"
|
2021-02-24 15:34:51 +03:00
|
|
|
|
|
|
|
"github.com/Azure/ARO-RP/pkg/api"
|
|
|
|
"github.com/Azure/ARO-RP/pkg/util/arm"
|
2021-02-26 20:53:16 +03:00
|
|
|
mock_authorization "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/authorization"
|
2021-02-24 15:34:51 +03:00
|
|
|
mock_features "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/features"
|
|
|
|
"github.com/Azure/ARO-RP/pkg/util/rbac"
|
2023-04-06 15:15:15 +03:00
|
|
|
utilerror "github.com/Azure/ARO-RP/test/util/error"
|
2023-11-28 18:45:00 +03:00
|
|
|
"github.com/Azure/ARO-RP/test/util/serversideapply"
|
2021-02-24 15:34:51 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
const fakeClusterSPObjectId = "00000000-0000-0000-0000-000000000000"
|
|
|
|
|
|
|
|
func TestCreateOrUpdateClusterServicePrincipalRBAC(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
clusterRGName := "test-cluster"
|
|
|
|
resourceGroupID := fmt.Sprintf("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/%s", clusterRGName)
|
|
|
|
assignmentName := "assignment"
|
|
|
|
|
|
|
|
m := &manager{
|
|
|
|
log: logrus.NewEntry(logrus.StandardLogger()),
|
|
|
|
doc: &api.OpenShiftClusterDocument{
|
|
|
|
OpenShiftCluster: &api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
|
|
|
ClusterProfile: api.ClusterProfile{
|
|
|
|
ResourceGroupID: resourceGroupID,
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
SPObjectID: fakeClusterSPObjectId,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
name string
|
|
|
|
clusterSPObjectID string
|
|
|
|
roleAssignments []mgmtauthorization.RoleAssignment
|
|
|
|
mocksDeployment func(*mock_features.MockDeploymentsClient)
|
2021-03-17 19:15:47 +03:00
|
|
|
mocksAuthz func(*mock_authorization.MockRoleAssignmentsClient, *mock_authorization.MockRoleDefinitionsClient, interface{})
|
2021-02-24 15:34:51 +03:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "noop",
|
|
|
|
roleAssignments: []mgmtauthorization.RoleAssignment{
|
|
|
|
{
|
|
|
|
Name: to.StringPtr(assignmentName),
|
|
|
|
RoleAssignmentPropertiesWithScope: &mgmtauthorization.RoleAssignmentPropertiesWithScope{
|
|
|
|
RoleDefinitionID: to.StringPtr(rbac.RoleContributor),
|
|
|
|
Scope: to.StringPtr(resourceGroupID),
|
|
|
|
PrincipalID: to.StringPtr(fakeClusterSPObjectId),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2021-03-17 19:15:47 +03:00
|
|
|
mocksAuthz: func(roleAssignments *mock_authorization.MockRoleAssignmentsClient, roleDefinitions *mock_authorization.MockRoleDefinitionsClient, result interface{}) {
|
|
|
|
roleAssignments.EXPECT().ListForResourceGroup(gomock.Any(), gomock.Any(), gomock.Any()).Return(result, nil)
|
|
|
|
roleDefinitions.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "needs create",
|
|
|
|
mocksDeployment: func(client *mock_features.MockDeploymentsClient) {
|
|
|
|
var parameters map[string]interface{}
|
|
|
|
client.EXPECT().CreateOrUpdateAndWait(gomock.Any(), clusterRGName, gomock.Any(), mgmtfeatures.Deployment{
|
|
|
|
Properties: &mgmtfeatures.DeploymentProperties{
|
|
|
|
Template: &arm.Template{
|
|
|
|
Schema: "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
|
|
|
ContentVersion: "1.0.0.0",
|
2021-03-15 15:32:38 +03:00
|
|
|
Resources: []*arm.Resource{m.clusterServicePrincipalRBAC()},
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
Parameters: parameters,
|
|
|
|
Mode: mgmtfeatures.Incremental,
|
|
|
|
},
|
|
|
|
}).Return(nil)
|
|
|
|
},
|
2021-03-17 19:15:47 +03:00
|
|
|
mocksAuthz: func(roleAssignments *mock_authorization.MockRoleAssignmentsClient, roleDefinitions *mock_authorization.MockRoleDefinitionsClient, result interface{}) {
|
|
|
|
roleAssignments.EXPECT().ListForResourceGroup(gomock.Any(), gomock.Any(), gomock.Any()).Return(result, nil)
|
|
|
|
roleDefinitions.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
name: "needs delete & create",
|
|
|
|
roleAssignments: []mgmtauthorization.RoleAssignment{
|
|
|
|
{
|
|
|
|
Name: to.StringPtr(assignmentName),
|
|
|
|
RoleAssignmentPropertiesWithScope: &mgmtauthorization.RoleAssignmentPropertiesWithScope{
|
|
|
|
RoleDefinitionID: to.StringPtr(rbac.RoleContributor),
|
|
|
|
Scope: to.StringPtr(resourceGroupID),
|
|
|
|
PrincipalID: to.StringPtr("00000000-0000-0000-0000-000000000001"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
mocksDeployment: func(client *mock_features.MockDeploymentsClient) {
|
|
|
|
var parameters map[string]interface{}
|
|
|
|
client.EXPECT().CreateOrUpdateAndWait(gomock.Any(), clusterRGName, gomock.Any(), mgmtfeatures.Deployment{
|
|
|
|
Properties: &mgmtfeatures.DeploymentProperties{
|
|
|
|
Template: &arm.Template{
|
|
|
|
Schema: "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
|
|
|
ContentVersion: "1.0.0.0",
|
2021-03-15 15:32:38 +03:00
|
|
|
Resources: []*arm.Resource{m.clusterServicePrincipalRBAC()},
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
Parameters: parameters,
|
|
|
|
Mode: mgmtfeatures.Incremental,
|
|
|
|
},
|
|
|
|
}).Return(nil)
|
|
|
|
},
|
2021-03-17 19:15:47 +03:00
|
|
|
mocksAuthz: func(roleAssignments *mock_authorization.MockRoleAssignmentsClient, roleDefinitions *mock_authorization.MockRoleDefinitionsClient, result interface{}) {
|
|
|
|
roleAssignments.EXPECT().ListForResourceGroup(gomock.Any(), gomock.Any(), gomock.Any()).Return(result, nil)
|
|
|
|
roleAssignments.EXPECT().Delete(gomock.Any(), resourceGroupID, assignmentName)
|
|
|
|
roleDefinitions.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
controller := gomock.NewController(t)
|
|
|
|
defer controller.Finish()
|
|
|
|
|
2021-03-17 19:15:47 +03:00
|
|
|
roleAssignments := mock_authorization.NewMockRoleAssignmentsClient(controller)
|
|
|
|
roleDefinitions := mock_authorization.NewMockRoleDefinitionsClient(controller)
|
2021-02-24 15:34:51 +03:00
|
|
|
deployments := mock_features.NewMockDeploymentsClient(controller)
|
|
|
|
|
|
|
|
if tt.mocksDeployment != nil {
|
|
|
|
tt.mocksDeployment(deployments)
|
|
|
|
}
|
|
|
|
|
|
|
|
if tt.mocksAuthz != nil {
|
2021-03-17 19:15:47 +03:00
|
|
|
tt.mocksAuthz(roleAssignments, roleDefinitions, tt.roleAssignments)
|
2021-02-24 15:34:51 +03:00
|
|
|
}
|
|
|
|
|
2021-03-17 19:15:47 +03:00
|
|
|
m.roleAssignments = roleAssignments
|
|
|
|
m.roleDefinitions = roleDefinitions
|
2021-02-24 15:34:51 +03:00
|
|
|
m.deployments = deployments
|
|
|
|
|
|
|
|
err := m.createOrUpdateClusterServicePrincipalRBAC(ctx)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getFakeAROSecret(clientID, secret string) corev1.Secret {
|
|
|
|
name := "azure-cloud-provider"
|
|
|
|
namespace := "kube-system"
|
|
|
|
data := map[string]interface{}{
|
|
|
|
"aadClientId": clientID,
|
|
|
|
"aadClientSecret": secret,
|
|
|
|
}
|
|
|
|
b, err := yaml.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-02-26 20:53:16 +03:00
|
|
|
return corev1.Secret{
|
2021-02-24 15:34:51 +03:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: name,
|
|
|
|
Namespace: namespace,
|
|
|
|
},
|
|
|
|
Data: map[string][]byte{
|
|
|
|
"cloud-config": b,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-28 18:45:00 +03:00
|
|
|
func TestCloudConfigSecretFromChanges(t *testing.T) {
|
|
|
|
for _, tt := range []struct {
|
|
|
|
name string
|
|
|
|
secretIn func() *corev1.Secret
|
|
|
|
cf map[string]interface{}
|
|
|
|
wantSecret func() *corev1.Secret
|
|
|
|
wantErrMsg string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "New CSP (client ID and client secret both changed)",
|
|
|
|
secretIn: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
cf: map[string]interface{}{
|
|
|
|
"aadClientId": "aadClientIdNew",
|
|
|
|
"aadClientSecret": "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantSecret: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientIdNew", "aadClientSecretNew")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Updated secret (client ID stayed the same, client secret changed)",
|
|
|
|
secretIn: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
cf: map[string]interface{}{
|
|
|
|
"aadClientId": "aadClientId",
|
|
|
|
"aadClientSecret": "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantSecret: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecretNew")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "No errors, nothing changed",
|
|
|
|
secretIn: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
cf: map[string]interface{}{
|
|
|
|
"aadClientId": "aadClientId",
|
|
|
|
"aadClientSecret": "aadClientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
secret, err := cloudConfigSecretFromChanges(tt.secretIn(), tt.cf)
|
|
|
|
if tt.wantSecret != nil {
|
|
|
|
wantSecret := tt.wantSecret()
|
|
|
|
if secret == nil {
|
|
|
|
t.Errorf("Did not return a Secret, but expected the following Secret data: %v", string(wantSecret.Data["cloud-config"]))
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(secret, wantSecret) {
|
|
|
|
t.Errorf("\n%+v \n!= \n%+v", string(secret.Data["cloud-config"]), string(wantSecret.Data["cloud-config"]))
|
|
|
|
}
|
|
|
|
} else if tt.wantSecret == nil && secret != nil {
|
|
|
|
t.Errorf("Should not have returned a Secret")
|
|
|
|
}
|
|
|
|
utilerror.AssertErrorMessage(t, err, tt.wantErrMsg)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestServicePrincipalUpdated(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
for _, tt := range []struct {
|
|
|
|
name string
|
|
|
|
kubernetescli func() *fake.Clientset
|
2024-04-22 18:34:09 +03:00
|
|
|
spp *api.ServicePrincipalProfile
|
2023-11-28 18:45:00 +03:00
|
|
|
wantSecret func() *corev1.Secret
|
|
|
|
wantErrMsg string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Secret not found",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
return fake.NewSimpleClientset()
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantErrMsg: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Encounter other error getting Secret",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
cli := fake.NewSimpleClientset()
|
|
|
|
cli.CoreV1().(*fakecorev1.FakeCoreV1).PrependReactor("get", "secrets", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
|
|
|
|
return true, &corev1.Secret{}, errors.New("Error getting Secret")
|
|
|
|
})
|
|
|
|
return cli
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantErrMsg: "Error getting Secret",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Unable to unmarshal cloud-config data",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
secret.Data["cloud-config"] = []byte("This is some random data that is not going to unmarshal properly!")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantErrMsg: "error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type map[string]interface {}",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "New CSP (client ID and client secret both changed)",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientIdNew",
|
|
|
|
ClientSecret: "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantSecret: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientIdNew", "aadClientSecretNew")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Updated secret (client ID stayed the same, client secret changed)",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecretNew",
|
|
|
|
},
|
|
|
|
wantSecret: func() *corev1.Secret {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecretNew")
|
|
|
|
return &secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "No errors, nothing changed",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
2024-04-22 18:34:09 +03:00
|
|
|
spp: &api.ServicePrincipalProfile{
|
2023-11-28 18:45:00 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
m := &manager{
|
|
|
|
kubernetescli: tt.kubernetescli(),
|
|
|
|
doc: &api.OpenShiftClusterDocument{
|
|
|
|
OpenShiftCluster: &api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
|
|
|
ServicePrincipalProfile: tt.spp,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
secret, err := m.servicePrincipalUpdated(ctx)
|
|
|
|
if tt.wantSecret != nil {
|
|
|
|
wantSecret := tt.wantSecret()
|
|
|
|
if secret == nil {
|
|
|
|
t.Errorf("Did not return a Secret, but expected the following Secret data: %v", string(wantSecret.Data["cloud-config"]))
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(secret, wantSecret) {
|
|
|
|
t.Errorf("\n%+v \n!= \n%+v", string(secret.Data["cloud-config"]), string(wantSecret.Data["cloud-config"]))
|
|
|
|
}
|
|
|
|
} else if tt.wantSecret == nil && secret != nil {
|
|
|
|
t.Errorf("Should not have returned a Secret")
|
|
|
|
}
|
|
|
|
utilerror.AssertErrorMessage(t, err, tt.wantErrMsg)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-24 15:34:51 +03:00
|
|
|
func TestUpdateAROSecret(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
type test struct {
|
|
|
|
name string
|
|
|
|
kubernetescli func() *fake.Clientset
|
|
|
|
operatorcli func() *operatorfake.Clientset
|
|
|
|
doc api.OpenShiftCluster
|
|
|
|
expect func() corev1.Secret
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range []*test{
|
|
|
|
{
|
|
|
|
name: "noop",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "aadClientId",
|
|
|
|
ClientSecret: "aadClientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
operatorcli: func() *operatorfake.Clientset {
|
|
|
|
return operatorfake.NewSimpleClientset()
|
|
|
|
},
|
|
|
|
expect: func() corev1.Secret {
|
|
|
|
return getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "update",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeAROSecret("aadClientId", "aadClientSecret")
|
|
|
|
return fake.NewSimpleClientset(&secret)
|
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "new-client-id",
|
|
|
|
ClientSecret: "aadClientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
operatorcli: func() *operatorfake.Clientset {
|
|
|
|
return operatorfake.NewSimpleClientset(
|
|
|
|
&operatorv1.KubeAPIServer{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "cluster",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&operatorv1.KubeControllerManager{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "cluster",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
},
|
|
|
|
expect: func() corev1.Secret {
|
|
|
|
return getFakeAROSecret("new-client-id", "aadClientSecret")
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "not found - no fail",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
return fake.NewSimpleClientset()
|
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "clientID",
|
|
|
|
ClientSecret: "aadClientSecret",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
operatorcli: func() *operatorfake.Clientset {
|
|
|
|
return operatorfake.NewSimpleClientset()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
m := &manager{
|
|
|
|
kubernetescli: tt.kubernetescli(),
|
|
|
|
operatorcli: tt.operatorcli(),
|
|
|
|
doc: &api.OpenShiftClusterDocument{
|
|
|
|
OpenShiftCluster: &tt.doc,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
err := m.updateAROSecret(ctx)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
secret, _ := m.kubernetescli.CoreV1().Secrets("kube-system").Get(ctx, "azure-cloud-provider", metav1.GetOptions{})
|
|
|
|
|
|
|
|
if secret != nil {
|
|
|
|
expect := tt.expect()
|
|
|
|
if !reflect.DeepEqual(secret.Data, expect.Data) {
|
|
|
|
t.Errorf("\n%+v \n!= \n%+v", string(secret.Data["cloud-config"]), string(expect.Data["cloud-config"]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getFakeOpenShiftSecret() corev1.Secret {
|
|
|
|
name := "azure-credentials"
|
|
|
|
namespace := "kube-system"
|
|
|
|
data := map[string][]byte{
|
2023-08-28 22:23:42 +03:00
|
|
|
"azure_subscription_id": {},
|
|
|
|
"azure_resource_prefix": {},
|
|
|
|
"azure_resourcegroup": {},
|
|
|
|
"azure_region": {},
|
|
|
|
"azure_client_id": []byte("azure_client_id_value"),
|
|
|
|
"azure_client_secret": []byte("azure_client_secret_value"),
|
|
|
|
"azure_tenant_id": []byte("azure_tenant_id_value"),
|
2021-02-24 15:34:51 +03:00
|
|
|
}
|
2021-02-26 20:53:16 +03:00
|
|
|
return corev1.Secret{
|
2021-02-24 15:34:51 +03:00
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: name,
|
|
|
|
Namespace: namespace,
|
|
|
|
},
|
|
|
|
Data: data,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUpdateOpenShiftSecret(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
type test struct {
|
|
|
|
name string
|
|
|
|
kubernetescli func() *fake.Clientset
|
|
|
|
doc api.OpenShiftCluster
|
|
|
|
subscriptionDoc api.SubscriptionDocument
|
|
|
|
expect func() corev1.Secret
|
|
|
|
wantErr string
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range []*test{
|
|
|
|
{
|
|
|
|
name: "noop",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeOpenShiftSecret()
|
2023-11-28 18:45:00 +03:00
|
|
|
return serversideapply.CliWithApply([]string{"secrets"}, &secret)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "azure_client_id_value",
|
|
|
|
ClientSecret: "azure_client_secret_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
subscriptionDoc: api.SubscriptionDocument{
|
|
|
|
Subscription: &api.Subscription{
|
|
|
|
Properties: &api.SubscriptionProperties{
|
|
|
|
TenantID: "azure_tenant_id_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expect: func() corev1.Secret {
|
|
|
|
return getFakeOpenShiftSecret()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "update secret",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeOpenShiftSecret()
|
2023-11-28 18:45:00 +03:00
|
|
|
return serversideapply.CliWithApply([]string{"secrets"}, &secret)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "azure_client_id_value",
|
|
|
|
ClientSecret: "new_azure_client_secret_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
subscriptionDoc: api.SubscriptionDocument{
|
|
|
|
Subscription: &api.Subscription{
|
|
|
|
Properties: &api.SubscriptionProperties{
|
|
|
|
TenantID: "azure_tenant_id_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expect: func() corev1.Secret {
|
|
|
|
secret := getFakeOpenShiftSecret()
|
|
|
|
secret.Data["azure_client_secret"] = []byte("new_azure_client_secret_value")
|
|
|
|
return secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "update tenant",
|
|
|
|
kubernetescli: func() *fake.Clientset {
|
|
|
|
secret := getFakeOpenShiftSecret()
|
2023-11-28 18:45:00 +03:00
|
|
|
return serversideapply.CliWithApply([]string{"secrets"}, &secret)
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2021-02-24 15:34:51 +03:00
|
|
|
ClientID: "azure_client_id_value",
|
|
|
|
ClientSecret: "azure_client_secret_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
subscriptionDoc: api.SubscriptionDocument{
|
|
|
|
Subscription: &api.Subscription{
|
|
|
|
Properties: &api.SubscriptionProperties{
|
|
|
|
TenantID: "new_azure_tenant_id_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expect: func() corev1.Secret {
|
|
|
|
secret := getFakeOpenShiftSecret()
|
|
|
|
secret.Data["azure_tenant_id"] = []byte("new_azure_tenant_id_value")
|
|
|
|
return secret
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2023-08-28 22:23:42 +03:00
|
|
|
name: "recreate secret when not found",
|
2021-02-24 15:34:51 +03:00
|
|
|
kubernetescli: func() *fake.Clientset {
|
2023-11-28 18:45:00 +03:00
|
|
|
return serversideapply.CliWithApply([]string{"secrets"})
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
doc: api.OpenShiftCluster{
|
|
|
|
Properties: api.OpenShiftClusterProperties{
|
2024-04-22 18:34:09 +03:00
|
|
|
ServicePrincipalProfile: &api.ServicePrincipalProfile{
|
2023-08-28 22:23:42 +03:00
|
|
|
ClientID: "azure_client_id_value",
|
|
|
|
ClientSecret: "azure_client_secret_value",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
subscriptionDoc: api.SubscriptionDocument{
|
|
|
|
Subscription: &api.Subscription{
|
|
|
|
Properties: &api.SubscriptionProperties{
|
|
|
|
TenantID: "azure_tenant_id_value",
|
|
|
|
},
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
},
|
2023-08-28 22:23:42 +03:00
|
|
|
expect: func() corev1.Secret {
|
|
|
|
return getFakeOpenShiftSecret()
|
|
|
|
},
|
2021-02-24 15:34:51 +03:00
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
m := &manager{
|
|
|
|
kubernetescli: tt.kubernetescli(),
|
|
|
|
doc: &api.OpenShiftClusterDocument{
|
|
|
|
OpenShiftCluster: &tt.doc,
|
|
|
|
},
|
|
|
|
subscriptionDoc: &tt.subscriptionDoc,
|
|
|
|
}
|
|
|
|
|
|
|
|
err := m.updateOpenShiftSecret(ctx)
|
2023-04-06 15:15:15 +03:00
|
|
|
utilerror.AssertErrorMessage(t, err, tt.wantErr)
|
2021-02-24 15:34:51 +03:00
|
|
|
|
|
|
|
secret, _ := m.kubernetescli.CoreV1().Secrets("kube-system").Get(ctx, "azure-credentials", metav1.GetOptions{})
|
|
|
|
|
|
|
|
if secret != nil {
|
|
|
|
expect := tt.expect()
|
|
|
|
if !reflect.DeepEqual(secret.Data, expect.Data) {
|
|
|
|
t.Errorf("\n%+v \n!= \n%+v", secret.Data, expect.Data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|