* Add Cosmos DB container for PlatformWorkloadIdentityRoleSets

* Revert change to AKS k8s version - committed by mistake

* Fix bug in converter

When I first wrote the converter, I thought Go would treat the the slice
we `make` few lines above these changes as a slice full of zero-value
structs, but it actually treats it as an empty slice, which led to
out-of-bound issues when I first tried to use this converter to work on
the API endpoints.

* Add the PlatformWorkloadIdentityRoleSetConverter to the API register

* Implement the change feed for role sets in the easiest, most naive way

* Implement the external API endpoint for listing role sets

* Fix a small oversight from earlier on

* Add unit tests for the list endpoint

* Add unit tests for changefeed changes

* Uncomment the static validator

* Fix more slice out of bounds bugs in the converters...

* Add converter and static validator to the admin API register

* Add list and put endpoints

* Fix name of function to match convention

* Fix bug in static validator

I originally wrote the code the way I did so that we could aggregate
errors so that we could provide a better UX in cases where there are
multiple similar errors in the request content. I found while writing
unit tests that aggregating the errors in this way and not wrapping them
in a CloudError causes the RP to return an internal server error instead
of a 400 bad request.

Is there a way we can aggregate the errors and still wrap them in a
CloudError? I'm not sure of the formatting requirements for the text of
CloudErrors.

* Add unit tests for new API endpoints

* Fix typo

* Appease the linter

* Appease the linter

* Add TODO comment re: the number of parameters

* Update static validator to return multiple validation issues at the same time where applicable for better UX

* Add a simple utility function to make semver comparisons of OpenShift minor version more readable

* Log error before returning 500 to user

* Log errors before returning 500 to user

* Improve naming of unit test cases

* Add additional unit test cases
This commit is contained in:
Kipp Morris 2024-06-06 09:15:44 -05:00 коммит произвёл GitHub
Родитель b038645848
Коммит 31c72522fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
60 изменённых файлов: 2175 добавлений и 179 удалений

Просмотреть файл

@ -163,6 +163,11 @@ func rp(ctx context.Context, log, audit *logrus.Entry) error {
return err
}
dbPlatformWorkloadIdentityRoleSets, err := database.NewPlatformWorkloadIdentityRoleSets(ctx, dbc, dbName)
if err != nil {
return err
}
go database.EmitMetrics(ctx, log, dbOpenShiftClusters, metrics)
feAead, err := encryption.NewMulti(ctx, _env.ServiceKeyvault(), env.FrontendEncryptionSecretV2Name, env.FrontendEncryptionSecretName)
@ -173,7 +178,7 @@ func rp(ctx context.Context, log, audit *logrus.Entry) error {
if err != nil {
return err
}
f, err := frontend.NewFrontend(ctx, audit, log.WithField("component", "frontend"), _env, dbAsyncOperations, dbClusterManagerConfiguration, dbOpenShiftClusters, dbSubscriptions, dbOpenShiftVersions, api.APIs, metrics, clusterm, feAead, hiveClusterManager, adminactions.NewKubeActions, adminactions.NewAzureActions, clusterdata.NewParallelEnricher(metrics, _env))
f, err := frontend.NewFrontend(ctx, audit, log.WithField("component", "frontend"), _env, dbAsyncOperations, dbClusterManagerConfiguration, dbOpenShiftClusters, dbSubscriptions, dbOpenShiftVersions, dbPlatformWorkloadIdentityRoleSets, api.APIs, metrics, clusterm, feAead, hiveClusterManager, adminactions.NewKubeActions, adminactions.NewAzureActions, clusterdata.NewParallelEnricher(metrics, _env))
if err != nil {
return err
}

Просмотреть файл

@ -33,14 +33,14 @@ type PlatformWorkloadIdentityRoleSetProperties struct {
// PlatformWorkloadIdentityRole represents a mapping from a particular OCP operator to the built-in role that should be assigned to that operator's corresponding managed identity.
type PlatformWorkloadIdentityRole struct {
// OperatorName represents the name of the operator that this role is for.
OperatorName string `json:"operatorName,omitempty" mutable:"true"`
OperatorName string `json:"operatorName,omitempty" mutable:"true" validate:"required"`
// RoleDefinitionName represents the name of the role.
RoleDefinitionName string `json:"roleDefinitionName,omitempty" mutable:"true"`
RoleDefinitionName string `json:"roleDefinitionName,omitempty" mutable:"true" validate:"required"`
// RoleDefinitionID represents the resource ID of the role definition.
RoleDefinitionID string `json:"roleDefinitionId,omitempty" mutable:"true"`
RoleDefinitionID string `json:"roleDefinitionId,omitempty" mutable:"true" validate:"required"`
// ServiceAccounts represents the set of service accounts associated with the given operator, since each service account needs its own federated credential.
ServiceAccounts []string `json:"serviceAccounts,omitempty" mutable:"true"`
ServiceAccounts []string `json:"serviceAccounts,omitempty" mutable:"true" validate:"required"`
}

Просмотреть файл

@ -1,11 +1,10 @@
package admin
import "github.com/Azure/ARO-RP/pkg/api"
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
/*
TODO: Uncomment once API endpoints have been implemented and this code is being used.
type platformWorkloadIdentityRoleSetConverter struct{}
// platformWorkloadIdentityRoleSetConverter.ToExternal returns a new external representation
@ -21,12 +20,17 @@ func (c platformWorkloadIdentityRoleSetConverter) ToExternal(s *api.PlatformWork
},
}
for i, r := range s.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = make([]string, 0, len(r.ServiceAccounts))
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = append(out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts, r.ServiceAccounts...)
for _, r := range s.Properties.PlatformWorkloadIdentityRoles {
role := PlatformWorkloadIdentityRole{
OperatorName: r.OperatorName,
RoleDefinitionName: r.RoleDefinitionName,
RoleDefinitionID: r.RoleDefinitionID,
ServiceAccounts: make([]string, 0, len(r.ServiceAccounts)),
}
role.ServiceAccounts = append(role.ServiceAccounts, r.ServiceAccounts...)
out.Properties.PlatformWorkloadIdentityRoles = append(out.Properties.PlatformWorkloadIdentityRoles, role)
}
return out
@ -56,12 +60,16 @@ func (c platformWorkloadIdentityRoleSetConverter) ToInternal(_new interface{}, o
out.Properties.OpenShiftVersion = new.Properties.OpenShiftVersion
out.Properties.PlatformWorkloadIdentityRoles = make([]api.PlatformWorkloadIdentityRole, 0, len(new.Properties.PlatformWorkloadIdentityRoles))
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = make([]string, 0, len(r.ServiceAccounts))
out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts = append(out.Properties.PlatformWorkloadIdentityRoles[i].ServiceAccounts, r.ServiceAccounts...)
for _, r := range new.Properties.PlatformWorkloadIdentityRoles {
role := api.PlatformWorkloadIdentityRole{
OperatorName: r.OperatorName,
RoleDefinitionName: r.RoleDefinitionName,
RoleDefinitionID: r.RoleDefinitionID,
ServiceAccounts: make([]string, 0, len(r.ServiceAccounts)),
}
role.ServiceAccounts = append(role.ServiceAccounts, r.ServiceAccounts...)
out.Properties.PlatformWorkloadIdentityRoles = append(out.Properties.PlatformWorkloadIdentityRoles, role)
}
}
*/

Просмотреть файл

@ -1,11 +1,17 @@
package admin
import (
"fmt"
"net/http"
"strings"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/util/immutable"
)
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
/*
TODO: Uncomment once API endpoints have been implemented and this code is being used.
type platformWorkloadIdentityRoleSetStaticValidator struct{}
func (sv platformWorkloadIdentityRoleSetStaticValidator) Static(_new interface{}, _current *api.PlatformWorkloadIdentityRoleSet) error {
@ -37,27 +43,31 @@ func (sv platformWorkloadIdentityRoleSetStaticValidator) validate(new *PlatformW
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "properties.platformWorkloadIdentityRoles", "Must be provided and must be non-empty")
}
errs := []error{}
missingProperties := []string{}
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
if r.OperatorName == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].operatorName", i), "Must be provided"))
missingProperties = append(missingProperties, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].operatorName", i))
}
if r.RoleDefinitionName == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionName", i), "Must be provided"))
missingProperties = append(missingProperties, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionName", i))
}
if r.RoleDefinitionID == "" {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionId", i), "Must be provided"))
missingProperties = append(missingProperties, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].roleDefinitionId", i))
}
if r.ServiceAccounts == nil || len(r.ServiceAccounts) == 0 {
errs = append(errs, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].serviceAccounts", i), "Must be provided and must be non-empty"))
missingProperties = append(missingProperties, fmt.Sprintf("properties.platformWorkloadIdentityRoles[%d].serviceAccounts", i))
}
}
return errors.Join(errs...)
if len(missingProperties) > 0 {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, strings.Join(missingProperties, ", "), "Must be provided")
}
return nil
}
func (sv platformWorkloadIdentityRoleSetStaticValidator) validateDelta(new, current *PlatformWorkloadIdentityRoleSet) error {
@ -68,4 +78,3 @@ func (sv platformWorkloadIdentityRoleSetStaticValidator) validateDelta(new, curr
}
return nil
}
*/

Просмотреть файл

@ -12,9 +12,11 @@ const APIVersion = "admin"
func init() {
api.APIs[APIVersion] = &api.Version{
OpenShiftClusterConverter: openShiftClusterConverter{},
OpenShiftClusterStaticValidator: openShiftClusterStaticValidator{},
OpenShiftVersionConverter: openShiftVersionConverter{},
OpenShiftVersionStaticValidator: openShiftVersionStaticValidator{},
OpenShiftClusterConverter: openShiftClusterConverter{},
OpenShiftClusterStaticValidator: openShiftClusterStaticValidator{},
OpenShiftVersionConverter: openShiftVersionConverter{},
OpenShiftVersionStaticValidator: openShiftVersionStaticValidator{},
PlatformWorkloadIdentityRoleSetConverter: platformWorkloadIdentityRoleSetConverter{},
PlatformWorkloadIdentityRoleSetStaticValidator: platformWorkloadIdentityRoleSetStaticValidator{},
}
}

Просмотреть файл

@ -37,6 +37,16 @@ type OpenShiftVersionStaticValidator interface {
Static(interface{}, *OpenShiftVersion) error
}
type PlatformWorkloadIdentityRoleSetConverter interface {
ToExternal(*PlatformWorkloadIdentityRoleSet) interface{}
ToExternalList([]*PlatformWorkloadIdentityRoleSet) interface{}
ToInternal(interface{}, *PlatformWorkloadIdentityRoleSet)
}
type PlatformWorkloadIdentityRoleSetStaticValidator interface {
Static(interface{}, *PlatformWorkloadIdentityRoleSet) error
}
type SyncSetConverter interface {
ToExternal(*SyncSet) interface{}
ToExternalList([]*SyncSet) interface{}
@ -63,18 +73,20 @@ type SecretConverter interface {
// Version is a set of endpoints implemented by each API version
type Version struct {
OpenShiftClusterConverter OpenShiftClusterConverter
OpenShiftClusterStaticValidator OpenShiftClusterStaticValidator
OpenShiftClusterCredentialsConverter OpenShiftClusterCredentialsConverter
OpenShiftClusterAdminKubeconfigConverter OpenShiftClusterAdminKubeconfigConverter
OpenShiftVersionConverter OpenShiftVersionConverter
OpenShiftVersionStaticValidator OpenShiftVersionStaticValidator
OperationList OperationList
SyncSetConverter SyncSetConverter
MachinePoolConverter MachinePoolConverter
SyncIdentityProviderConverter SyncIdentityProviderConverter
SecretConverter SecretConverter
ClusterManagerStaticValidator ClusterManagerStaticValidator
OpenShiftClusterConverter OpenShiftClusterConverter
OpenShiftClusterStaticValidator OpenShiftClusterStaticValidator
OpenShiftClusterCredentialsConverter OpenShiftClusterCredentialsConverter
OpenShiftClusterAdminKubeconfigConverter OpenShiftClusterAdminKubeconfigConverter
OpenShiftVersionConverter OpenShiftVersionConverter
OpenShiftVersionStaticValidator OpenShiftVersionStaticValidator
PlatformWorkloadIdentityRoleSetConverter PlatformWorkloadIdentityRoleSetConverter
PlatformWorkloadIdentityRoleSetStaticValidator PlatformWorkloadIdentityRoleSetStaticValidator
OperationList OperationList
SyncSetConverter SyncSetConverter
MachinePoolConverter MachinePoolConverter
SyncIdentityProviderConverter SyncIdentityProviderConverter
SecretConverter SecretConverter
ClusterManagerStaticValidator ClusterManagerStaticValidator
}
// APIs is the map of registered API versions

Просмотреть файл

@ -24,10 +24,13 @@ func (c platformWorkloadIdentityRoleSetConverter) ToExternal(s *api.PlatformWork
},
}
for i, r := range s.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
for _, r := range s.Properties.PlatformWorkloadIdentityRoles {
role := PlatformWorkloadIdentityRole{
OperatorName: r.OperatorName,
RoleDefinitionName: r.RoleDefinitionName,
RoleDefinitionID: r.RoleDefinitionID,
}
out.Properties.PlatformWorkloadIdentityRoles = append(out.Properties.PlatformWorkloadIdentityRoles, role)
}
return out
@ -57,9 +60,12 @@ func (c platformWorkloadIdentityRoleSetConverter) ToInternal(_new interface{}, o
out.Properties.OpenShiftVersion = new.Properties.OpenShiftVersion
out.Properties.PlatformWorkloadIdentityRoles = make([]api.PlatformWorkloadIdentityRole, 0, len(new.Properties.PlatformWorkloadIdentityRoles))
for i, r := range new.Properties.PlatformWorkloadIdentityRoles {
out.Properties.PlatformWorkloadIdentityRoles[i].OperatorName = r.OperatorName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionName = r.RoleDefinitionName
out.Properties.PlatformWorkloadIdentityRoles[i].RoleDefinitionID = r.RoleDefinitionID
for _, r := range new.Properties.PlatformWorkloadIdentityRoles {
role := api.PlatformWorkloadIdentityRole{
OperatorName: r.OperatorName,
RoleDefinitionName: r.RoleDefinitionName,
RoleDefinitionID: r.RoleDefinitionID,
}
out.Properties.PlatformWorkloadIdentityRoles = append(out.Properties.PlatformWorkloadIdentityRoles, role)
}
}

Просмотреть файл

@ -22,6 +22,7 @@ func init() {
OpenShiftClusterCredentialsConverter: openShiftClusterCredentialsConverter{},
OpenShiftClusterAdminKubeconfigConverter: openShiftClusterAdminKubeconfigConverter{},
OpenShiftVersionConverter: openShiftVersionConverter{},
PlatformWorkloadIdentityRoleSetConverter: platformWorkloadIdentityRoleSetConverter{},
OperationList: api.OperationList{
Operations: []api.Operation{
api.OperationResultsRead,

Просмотреть файл

@ -90,10 +90,10 @@ func Test_getAdminHiveClusterDeployment(t *testing.T) {
clusterManager := mock_hive.NewMockClusterManager(controller)
clusterManager.EXPECT().GetClusterDeployment(gomock.Any(), gomock.Any()).Return(&clusterDeployment, nil).Times(tt.expectedGetClusterDeploymentCallCount)
f, err = NewFrontend(ctx, ti.audit, ti.log, _env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase,
ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, clusterManager, nil, nil, nil)
ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, clusterManager, nil, nil, nil)
} else {
f, err = NewFrontend(ctx, ti.audit, ti.log, _env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase,
ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
}
if err != nil {

Просмотреть файл

@ -91,7 +91,7 @@ func TestAdminApproveCSR(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)

Просмотреть файл

@ -152,7 +152,7 @@ func TestAdminCordonUncordonNode(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)

Просмотреть файл

@ -113,7 +113,7 @@ func TestAdminDeleteManagedResource(t *testing.T) {
a := mock_adminactions.NewMockAzureActions(ti.controller)
tt.mocks(tt, a)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -84,7 +84,7 @@ func TestAdminDrainNode(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)

Просмотреть файл

@ -536,6 +536,7 @@ func TestAdminEtcdCertificateRenew(t *testing.T) {
ti.openShiftClustersDatabase,
ti.subscriptionsDatabase,
nil,
nil,
api.APIs,
&noop.Noop{},
&noop.Noop{},
@ -753,6 +754,7 @@ func TestAdminEtcdCertificateRecovery(t *testing.T) {
ti.openShiftClustersDatabase,
ti.subscriptionsDatabase,
nil,
nil,
api.APIs,
&noop.Noop{},
&noop.Noop{},

Просмотреть файл

@ -167,6 +167,7 @@ func TestAdminEtcdRecovery(t *testing.T) {
ti.openShiftClustersDatabase,
ti.subscriptionsDatabase,
nil,
nil,
api.APIs,
&noop.Noop{},
&noop.Noop{},

Просмотреть файл

@ -262,7 +262,7 @@ func TestAdminKubernetesObjectsGetAndDelete(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)
if err != nil {
@ -411,7 +411,7 @@ func TestAdminPostKubernetesObjects(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)
if err != nil {

Просмотреть файл

@ -125,7 +125,7 @@ func TestAdminKubernetesGetPodLogs(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster) (adminactions.KubeActions, error) {
return k, nil
}, nil, nil)
if err != nil {

Просмотреть файл

@ -124,7 +124,7 @@ func TestAdminListOpenShiftCluster(t *testing.T) {
ti.openShiftClustersClient.SetError(tt.throwsError)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, aead, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, aead, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -84,7 +84,7 @@ func TestAdminRedeployVM(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -93,7 +93,7 @@ func TestAdminListResourcesList(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)
mockResponder := mock_frontend.NewMockStreamResponder(ti.controller)

Просмотреть файл

@ -84,7 +84,7 @@ func TestAdminStartVM(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -86,7 +86,7 @@ func TestAdminStopVM(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -202,7 +202,7 @@ func TestAdminVMResize(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil,
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil,
func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -136,7 +136,7 @@ func TestAdminListVMSizeList(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -110,7 +110,7 @@ func TestOpenShiftVersionList(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)

Просмотреть файл

@ -266,7 +266,7 @@ func TestOpenShiftVersionPut(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -0,0 +1,47 @@
package frontend
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"encoding/json"
"net/http"
"path/filepath"
"sort"
"github.com/sirupsen/logrus"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/admin"
"github.com/Azure/ARO-RP/pkg/frontend/middleware"
"github.com/Azure/ARO-RP/pkg/util/version"
)
func (f *frontend) getAdminPlatformWorkloadIdentityRoleSets(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log := ctx.Value(middleware.ContextKeyLog).(*logrus.Entry)
r.URL.Path = filepath.Dir(r.URL.Path)
converter := f.apis[admin.APIVersion].PlatformWorkloadIdentityRoleSetConverter
docs, err := f.dbPlatformWorkloadIdentityRoleSets.ListAll(ctx)
if err != nil {
log.Error(err)
api.WriteError(w, http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "Internal server error.")
return
}
var roleSets []*api.PlatformWorkloadIdentityRoleSet
if docs != nil {
for _, doc := range docs.PlatformWorkloadIdentityRoleSetDocuments {
roleSets = append(roleSets, doc.PlatformWorkloadIdentityRoleSet)
}
}
sort.Slice(roleSets, func(i, j int) bool {
return version.CreateSemverFromMinorVersionString(roleSets[i].Properties.OpenShiftVersion).LessThan(*version.CreateSemverFromMinorVersionString(roleSets[j].Properties.OpenShiftVersion))
})
b, err := json.MarshalIndent(converter.ToExternalList(roleSets), "", " ")
adminReply(log, w, nil, b, err)
}

Просмотреть файл

@ -0,0 +1,281 @@
package frontend
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"errors"
"net/http"
"sort"
"testing"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/admin"
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
"github.com/Azure/ARO-RP/pkg/metrics/noop"
"github.com/Azure/ARO-RP/pkg/util/version"
testdatabase "github.com/Azure/ARO-RP/test/database"
)
func TestPlatformWorkloadIdentityRoleSetList(t *testing.T) {
ctx := context.Background()
type test struct {
name string
fixture func(f *testdatabase.Fixture)
cosmosdb func(c *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient)
wantStatusCode int
wantResponse *admin.PlatformWorkloadIdentityRoleSetList
wantError string
}
for _, tt := range []*test{
{
name: "GET request returns empty result with StatusOK",
fixture: func(f *testdatabase.Fixture) {},
wantStatusCode: http.StatusOK,
wantResponse: &admin.PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*admin.PlatformWorkloadIdentityRoleSet{},
},
},
{
name: "GET request returns non-empty result with StatusOK",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
)
},
wantStatusCode: http.StatusOK,
wantResponse: &admin.PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*admin.PlatformWorkloadIdentityRoleSet{
{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
},
{
name: "GET request with StatusOK returns results in correct order even if Cosmos DB returns them in a different order",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
)
},
cosmosdb: func(c *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient) {
// Sort the documents in descending order rather than ascending order, which
// is the order we expect to see in the response.
c.SetSorter(func(roleSets []*api.PlatformWorkloadIdentityRoleSetDocument) {
sort.Slice(roleSets, func(i, j int) bool {
return version.CreateSemverFromMinorVersionString(roleSets[j].PlatformWorkloadIdentityRoleSet.Properties.OpenShiftVersion).LessThan(*version.CreateSemverFromMinorVersionString(roleSets[i].PlatformWorkloadIdentityRoleSet.Properties.OpenShiftVersion))
})
})
},
wantStatusCode: http.StatusOK,
wantResponse: &admin.PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*admin.PlatformWorkloadIdentityRoleSet{
{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
},
{
name: "GET request results in StatusInternalServerError due to issues with Cosmos DB",
fixture: func(f *testdatabase.Fixture) {},
cosmosdb: func(c *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient) {
c.SetError(errors.New("Well shoot, Cosmos DB isn't working!"))
},
wantStatusCode: http.StatusInternalServerError,
wantResponse: &admin.PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*admin.PlatformWorkloadIdentityRoleSet{},
},
wantError: api.NewCloudError(http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "Internal server error.").Error(),
},
} {
t.Run(tt.name, func(t *testing.T) {
ti := newTestInfra(t).WithPlatformWorkloadIdentityRoleSets()
defer ti.done()
if tt.cosmosdb != nil {
tt.cosmosdb(ti.platformWorkloadIdentityRoleSetsClient)
}
err := ti.buildFixtures(tt.fixture)
if err != nil {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, nil, ti.platformWorkloadIdentityRoleSetsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
go f.Run(ctx, nil, nil)
resp, b, err := ti.request(http.MethodGet, "https://server/admin/platformworkloadidentityrolesets",
nil, nil)
if err != nil {
t.Fatal(err)
}
err = validateResponse(resp, b, tt.wantStatusCode, tt.wantError, tt.wantResponse)
if err != nil {
t.Error(err)
}
})
}
}

Просмотреть файл

@ -0,0 +1,96 @@
package frontend
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"encoding/json"
"net/http"
"path/filepath"
"github.com/sirupsen/logrus"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/admin"
"github.com/Azure/ARO-RP/pkg/frontend/middleware"
)
func (f *frontend) putAdminPlatformWorkloadIdentityRoleSet(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log := ctx.Value(middleware.ContextKeyLog).(*logrus.Entry)
r.URL.Path = filepath.Dir(r.URL.Path)
converter := f.apis[admin.APIVersion].PlatformWorkloadIdentityRoleSetConverter
staticValidator := f.apis[admin.APIVersion].PlatformWorkloadIdentityRoleSetStaticValidator
body := r.Context().Value(middleware.ContextKeyBody).([]byte)
if len(body) == 0 || !json.Valid(body) {
api.WriteError(w, http.StatusBadRequest, api.CloudErrorCodeInvalidRequestContent, "", "The request content was invalid and could not be deserialized.")
return
}
var ext *admin.PlatformWorkloadIdentityRoleSet
err := json.Unmarshal(body, &ext)
if err != nil {
api.WriteError(w, http.StatusBadRequest, api.CloudErrorCodeInvalidRequestContent, "", "The request content could not be deserialized: "+err.Error())
return
}
docs, err := f.dbPlatformWorkloadIdentityRoleSets.ListAll(ctx)
if err != nil {
log.Error(err)
api.WriteError(w, http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "Internal server error.")
return
}
var roleSetDoc *api.PlatformWorkloadIdentityRoleSetDocument
if docs != nil {
for _, doc := range docs.PlatformWorkloadIdentityRoleSetDocuments {
if doc.PlatformWorkloadIdentityRoleSet.Properties.OpenShiftVersion == ext.Properties.OpenShiftVersion {
roleSetDoc = doc
break
}
}
}
isCreate := roleSetDoc == nil
if isCreate {
err = staticValidator.Static(ext, nil)
roleSetDoc = &api.PlatformWorkloadIdentityRoleSetDocument{
ID: f.dbPlatformWorkloadIdentityRoleSets.NewUUID(),
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{},
}
} else {
err = staticValidator.Static(ext, roleSetDoc.PlatformWorkloadIdentityRoleSet)
}
if err != nil {
adminReply(log, w, nil, []byte{}, err)
return
}
converter.ToInternal(ext, roleSetDoc.PlatformWorkloadIdentityRoleSet)
if isCreate {
roleSetDoc, err = f.dbPlatformWorkloadIdentityRoleSets.Create(ctx, roleSetDoc)
if err != nil {
log.Error(err)
api.WriteError(w, http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "Internal server error.")
return
}
} else {
roleSetDoc, err = f.dbPlatformWorkloadIdentityRoleSets.Update(ctx, roleSetDoc)
if err != nil {
log.Error(err)
api.WriteError(w, http.StatusInternalServerError, api.CloudErrorCodeInternalServerError, "", "Internal server error.")
return
}
}
b, err := json.MarshalIndent(converter.ToExternal(roleSetDoc.PlatformWorkloadIdentityRoleSet), "", " ")
if err == nil {
if isCreate {
err = statusCodeError(http.StatusCreated)
}
}
adminReply(log, w, nil, b, err)
}

Просмотреть файл

@ -0,0 +1,788 @@
package frontend
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"net/http"
"testing"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/admin"
"github.com/Azure/ARO-RP/pkg/metrics/noop"
testdatabase "github.com/Azure/ARO-RP/test/database"
)
func TestPlatformWorkloadIdentityRoleSetPut(t *testing.T) {
ctx := context.Background()
type test struct {
name string
fixture func(f *testdatabase.Fixture)
body *admin.PlatformWorkloadIdentityRoleSet
wantStatusCode int
wantResponse *admin.PlatformWorkloadIdentityRoleSet
wantError string
wantDocuments []*api.PlatformWorkloadIdentityRoleSetDocument
}
for _, tt := range []*test{
{
name: "PUT to update an existing entry updates it in-place and results in StatusOK",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
wantStatusCode: http.StatusOK,
wantResponse: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
},
{
name: "PUT to add a new entry creates it successfully and results in StatusOK",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
wantStatusCode: http.StatusCreated,
wantResponse: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
{
ID: "08080808-0808-0808-0808-080808080002",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing request body results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {},
body: &admin.PlatformWorkloadIdentityRoleSet{},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.openShiftVersion: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{},
},
{
name: "PUT with missing OpenShiftVersion results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.openShiftVersion: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRoles results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles: Must be provided and must be non-empty",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRole.OperatorName results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles[0].operatorName: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRole.RoleDefinitionName results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles[0].roleDefinitionName: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRole.RoleDefinitionID results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles[0].roleDefinitionId: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRole.ServiceAccounts results in StatusBadRequest",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles[0].serviceAccounts: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
{
name: "PUT with missing PlatformWorkloadIdentityRole.RoleDefinitionId and PlatformWorkloadIdentityRole.ServiceAccounts results in StatusBadRequest - tests the case where multiple attributes are missing and error message consists of messages about multiple missing properties joined together",
fixture: func(f *testdatabase.Fixture) {
f.AddPlatformWorkloadIdentityRoleSetDocuments(
&api.PlatformWorkloadIdentityRoleSetDocument{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
)
},
body: &admin.PlatformWorkloadIdentityRoleSet{
Properties: admin.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []admin.PlatformWorkloadIdentityRole{
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
},
},
},
},
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidParameter: properties.platformWorkloadIdentityRoles[0].roleDefinitionId, properties.platformWorkloadIdentityRoles[0].serviceAccounts: Must be provided",
wantDocuments: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
ID: "08080808-0808-0808-0808-080808080001",
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
ti := newTestInfra(t).WithPlatformWorkloadIdentityRoleSets()
defer ti.done()
err := ti.buildFixtures(tt.fixture)
if err != nil {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, nil, ti.platformWorkloadIdentityRoleSetsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
go f.Run(ctx, nil, nil)
resp, b, err := ti.request(http.MethodPut, "https://server/admin/platformworkloadidentityrolesets",
http.Header{
"Content-Type": []string{"application/json"},
}, tt.body)
if err != nil {
t.Fatal(err)
}
err = validateResponse(resp, b, tt.wantStatusCode, tt.wantError, tt.wantResponse)
if err != nil {
t.Error(err)
}
if tt.wantDocuments != nil {
ti.checker.AddPlatformWorkloadIdentityRoleSetDocuments(tt.wantDocuments...)
for _, err := range ti.checker.CheckPlatformWorkloadIdentityRoleSets(ti.platformWorkloadIdentityRoleSetsClient) {
t.Error(err)
}
}
})
}
}

Просмотреть файл

@ -136,7 +136,7 @@ func TestGetAsyncOperationResult(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -183,7 +183,7 @@ func TestGetAsyncOperationsStatus(t *testing.T) {
ti.asyncOperationsClient.SetError(tt.dbError)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -12,7 +12,7 @@ import (
"github.com/Azure/ARO-RP/pkg/util/recover"
)
func (f *frontend) changefeed(ctx context.Context) {
func (f *frontend) changefeedOcpVersions(ctx context.Context) {
defer recover.Panic(f.baseLog)
// f.dbOpenShiftVersions will be nil when running unit tests. Return here to avoid nil pointer panic
@ -20,15 +20,30 @@ func (f *frontend) changefeed(ctx context.Context) {
return
}
frontendIterator := f.dbOpenShiftVersions.ChangeFeed()
ocpVersionsIterator := f.dbOpenShiftVersions.ChangeFeed()
t := time.NewTicker(10 * time.Second)
defer t.Stop()
f.updateFromIterator(ctx, t, frontendIterator)
f.updateFromIteratorOcpVersions(ctx, t, ocpVersionsIterator)
}
func (f *frontend) updateFromIterator(ctx context.Context, ticker *time.Ticker, frontendIterator cosmosdb.OpenShiftVersionDocumentIterator) {
func (f *frontend) changefeedRoleSets(ctx context.Context) {
defer recover.Panic(f.baseLog)
if f.dbPlatformWorkloadIdentityRoleSets == nil {
return
}
roleSetsIterator := f.dbPlatformWorkloadIdentityRoleSets.ChangeFeed()
t := time.NewTicker(10 * time.Second)
defer t.Stop()
f.updateFromIteratorRoleSets(ctx, t, roleSetsIterator)
}
func (f *frontend) updateFromIteratorOcpVersions(ctx context.Context, ticker *time.Ticker, frontendIterator cosmosdb.OpenShiftVersionDocumentIterator) {
for {
successful := true
@ -47,7 +62,7 @@ func (f *frontend) updateFromIterator(ctx context.Context, ticker *time.Ticker,
}
if successful {
f.lastChangefeed.Store(time.Now())
f.lastOcpVersionsChangefeed.Store(time.Now())
}
select {
@ -60,8 +75,8 @@ func (f *frontend) updateFromIterator(ctx context.Context, ticker *time.Ticker,
// updateOcpVersions adds enabled versions to the frontend cache
func (f *frontend) updateOcpVersions(docs []*api.OpenShiftVersionDocument) {
f.mu.Lock()
defer f.mu.Unlock()
f.ocpVersionsMu.Lock()
defer f.ocpVersionsMu.Unlock()
for _, doc := range docs {
if doc.OpenShiftVersion.Deleting || !doc.OpenShiftVersion.Properties.Enabled {
@ -75,3 +90,47 @@ func (f *frontend) updateOcpVersions(docs []*api.OpenShiftVersionDocument) {
}
}
}
func (f *frontend) updateFromIteratorRoleSets(ctx context.Context, ticker *time.Ticker, frontendIterator cosmosdb.PlatformWorkloadIdentityRoleSetDocumentIterator) {
for {
successful := true
for {
docs, err := frontendIterator.Next(ctx, -1)
if err != nil {
successful = false
f.baseLog.Error(err)
break
}
if docs == nil {
break
}
f.updatePlatformWorkloadIdentityRoleSets(docs.PlatformWorkloadIdentityRoleSetDocuments)
}
if successful {
f.lastPlatformWorkloadIdentityRoleSetsChangefeed.Store(time.Now())
}
select {
case <-ticker.C:
case <-ctx.Done():
return
}
}
}
func (f *frontend) updatePlatformWorkloadIdentityRoleSets(docs []*api.PlatformWorkloadIdentityRoleSetDocument) {
f.platformWorkloadIdentityRoleSetsMu.Lock()
defer f.platformWorkloadIdentityRoleSetsMu.Unlock()
for _, doc := range docs {
if doc.PlatformWorkloadIdentityRoleSet.Deleting {
// https://docs.microsoft.com/en-us/azure/cosmos-db/change-feed-design-patterns#deletes
delete(f.availablePlatformWorkloadIdentityRoleSets, doc.PlatformWorkloadIdentityRoleSet.Properties.OpenShiftVersion)
} else {
f.availablePlatformWorkloadIdentityRoleSets[doc.PlatformWorkloadIdentityRoleSet.Properties.OpenShiftVersion] = doc.PlatformWorkloadIdentityRoleSet
}
}
}

Просмотреть файл

@ -14,7 +14,7 @@ import (
"github.com/Azure/ARO-RP/pkg/util/cmp"
)
func TestUpdateFromIterator(t *testing.T) {
func TestUpdateFromIteratorOcpVersions(t *testing.T) {
for _, tt := range []struct {
name string
docsInIterator []*api.OpenShiftVersionDocument
@ -22,7 +22,7 @@ func TestUpdateFromIterator(t *testing.T) {
wantVersions map[string]*api.OpenShiftVersion
}{
{
name: "add to empty",
name: "Add a new doc from the changefeed to an empty frontend cache",
docsInIterator: []*api.OpenShiftVersionDocument{
{
OpenShiftVersion: &api.OpenShiftVersion{
@ -44,7 +44,7 @@ func TestUpdateFromIterator(t *testing.T) {
},
},
{
name: "do nothing",
name: "Docs in changefeed match docs in frontend cache - no changes needed",
docsInIterator: []*api.OpenShiftVersionDocument{
{
OpenShiftVersion: &api.OpenShiftVersion{
@ -73,7 +73,7 @@ func TestUpdateFromIterator(t *testing.T) {
},
},
{
name: "add to not empty",
name: "Add a new doc from the iterator to a non-empty frontend cache",
docsInIterator: []*api.OpenShiftVersionDocument{
{
OpenShiftVersion: &api.OpenShiftVersion{
@ -108,7 +108,7 @@ func TestUpdateFromIterator(t *testing.T) {
},
},
{
name: "remove existing",
name: "A doc present in the frontend cache is marked deleting in the changefeed - remove it from the cache",
docsInIterator: []*api.OpenShiftVersionDocument{
{
OpenShiftVersion: &api.OpenShiftVersion{
@ -152,7 +152,7 @@ func TestUpdateFromIterator(t *testing.T) {
},
},
{
name: "remove disabled versions",
name: "A doc present in the frontend cache is marked disabled in the changefeed - remove it from the cache",
docsInIterator: []*api.OpenShiftVersionDocument{
{
OpenShiftVersion: &api.OpenShiftVersion{
@ -184,7 +184,7 @@ func TestUpdateFromIterator(t *testing.T) {
fakeIterator := cosmosdb.NewFakeOpenShiftVersionDocumentIterator(tt.docsInIterator, 0)
go frontend.updateFromIterator(ctx, ticker, fakeIterator)
go frontend.updateFromIteratorOcpVersions(ctx, ticker, fakeIterator)
time.Sleep(time.Second)
cancel()
@ -194,3 +194,345 @@ func TestUpdateFromIterator(t *testing.T) {
})
}
}
func TestUpdateFromIteratorRoleSets(t *testing.T) {
for _, tt := range []struct {
name string
docsInIterator []*api.PlatformWorkloadIdentityRoleSetDocument
roleSets map[string]*api.PlatformWorkloadIdentityRoleSet
wantRoleSets map[string]*api.PlatformWorkloadIdentityRoleSet
}{
{
name: "add to empty",
docsInIterator: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
roleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{},
wantRoleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
{
name: "do nothing",
docsInIterator: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
roleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
wantRoleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
},
{
name: "add to not empty",
docsInIterator: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
roleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
},
wantRoleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
"4.15": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
{
name: "remove existing",
docsInIterator: []*api.PlatformWorkloadIdentityRoleSetDocument{
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
Deleting: true,
},
},
{
PlatformWorkloadIdentityRoleSet: &api.PlatformWorkloadIdentityRoleSet{
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
roleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
"4.15": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
wantRoleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.15": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
ticker := time.NewTicker(1)
ctx, cancel := context.WithCancel(context.TODO())
frontend := frontend{
availablePlatformWorkloadIdentityRoleSets: tt.roleSets,
}
fakeIterator := cosmosdb.NewFakePlatformWorkloadIdentityRoleSetDocumentIterator(tt.docsInIterator, 0)
go frontend.updateFromIteratorRoleSets(ctx, ticker, fakeIterator)
time.Sleep(time.Second)
cancel()
if !reflect.DeepEqual(frontend.availablePlatformWorkloadIdentityRoleSets, tt.wantRoleSets) {
t.Error(cmp.Diff(frontend.availablePlatformWorkloadIdentityRoleSets, tt.wantRoleSets))
}
})
}
}

Просмотреть файл

@ -120,7 +120,7 @@ func TestDeleteClusterManagerConfiguration(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, nil, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, nil, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -123,7 +123,7 @@ func TestGetClusterManagerConfiguration(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, nil, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, nil, nil, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -201,7 +201,7 @@ func TestPutOrPatchClusterManagerConfiguration(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -523,6 +523,7 @@ func TestFixEtcd(t *testing.T) {
ti.openShiftClustersDatabase,
ti.subscriptionsDatabase,
nil,
nil,
api.APIs,
&noop.Noop{},
&noop.Noop{},

Просмотреть файл

@ -57,18 +57,22 @@ type frontend struct {
apiVersionMiddleware middleware.ApiVersionValidator
maintenanceMiddleware middleware.MaintenanceMiddleware
dbAsyncOperations database.AsyncOperations
dbClusterManagerConfiguration database.ClusterManagerConfigurations
dbOpenShiftClusters database.OpenShiftClusters
dbSubscriptions database.Subscriptions
dbOpenShiftVersions database.OpenShiftVersions
dbAsyncOperations database.AsyncOperations
dbClusterManagerConfiguration database.ClusterManagerConfigurations
dbOpenShiftClusters database.OpenShiftClusters
dbSubscriptions database.Subscriptions
dbOpenShiftVersions database.OpenShiftVersions
dbPlatformWorkloadIdentityRoleSets database.PlatformWorkloadIdentityRoleSets
defaultOcpVersion string // always enabled
enabledOcpVersions map[string]*api.OpenShiftVersion
apis map[string]*api.Version
defaultOcpVersion string // always enabled
enabledOcpVersions map[string]*api.OpenShiftVersion
availablePlatformWorkloadIdentityRoleSets map[string]*api.PlatformWorkloadIdentityRoleSet
apis map[string]*api.Version
lastChangefeed atomic.Value //time.Time
mu sync.RWMutex
lastOcpVersionsChangefeed atomic.Value //time.Time
lastPlatformWorkloadIdentityRoleSetsChangefeed atomic.Value
ocpVersionsMu sync.RWMutex
platformWorkloadIdentityRoleSetsMu sync.RWMutex
aead encryption.AEAD
@ -107,6 +111,7 @@ type Runnable interface {
Run(context.Context, <-chan struct{}, chan<- struct{})
}
// TODO: Get the number of function parameters under control :D
// NewFrontend returns a new runnable frontend
func NewFrontend(ctx context.Context,
auditLog *logrus.Entry,
@ -117,6 +122,7 @@ func NewFrontend(ctx context.Context,
dbOpenShiftClusters database.OpenShiftClusters,
dbSubscriptions database.Subscriptions,
dbOpenShiftVersions database.OpenShiftVersions,
dbPlatformWorkloadIdentityRoleSets database.PlatformWorkloadIdentityRoleSets,
apis map[string]*api.Version,
m metrics.Emitter,
clusterm metrics.Emitter,
@ -148,18 +154,19 @@ func NewFrontend(ctx context.Context,
AdminAuth: _env.AdminClientAuthorizer(),
ArmAuth: _env.ArmClientAuthorizer(),
},
dbAsyncOperations: dbAsyncOperations,
dbClusterManagerConfiguration: dbClusterManagerConfiguration,
dbOpenShiftClusters: dbOpenShiftClusters,
dbSubscriptions: dbSubscriptions,
dbOpenShiftVersions: dbOpenShiftVersions,
apis: apis,
m: middleware.MetricsMiddleware{Emitter: m},
maintenanceMiddleware: middleware.MaintenanceMiddleware{Emitter: clusterm},
aead: aead,
hiveClusterManager: hiveClusterManager,
kubeActionsFactory: kubeActionsFactory,
azureActionsFactory: azureActionsFactory,
dbAsyncOperations: dbAsyncOperations,
dbClusterManagerConfiguration: dbClusterManagerConfiguration,
dbOpenShiftClusters: dbOpenShiftClusters,
dbSubscriptions: dbSubscriptions,
dbOpenShiftVersions: dbOpenShiftVersions,
dbPlatformWorkloadIdentityRoleSets: dbPlatformWorkloadIdentityRoleSets,
apis: apis,
m: middleware.MetricsMiddleware{Emitter: m},
maintenanceMiddleware: middleware.MaintenanceMiddleware{Emitter: clusterm},
aead: aead,
hiveClusterManager: hiveClusterManager,
kubeActionsFactory: kubeActionsFactory,
azureActionsFactory: azureActionsFactory,
quotaValidator: quotaValidator{},
skuValidator: skuValidator{},
@ -167,7 +174,8 @@ func NewFrontend(ctx context.Context,
clusterEnricher: enricher,
enabledOcpVersions: map[string]*api.OpenShiftVersion{},
enabledOcpVersions: map[string]*api.OpenShiftVersion{},
availablePlatformWorkloadIdentityRoleSets: map[string]*api.PlatformWorkloadIdentityRoleSet{},
bucketAllocator: &bucket.Random{},
@ -277,6 +285,8 @@ func (f *frontend) chiAuthenticatedRoutes(router chi.Router) {
r.Get("/operationresults/{operationId}", f.getAsyncOperationResult)
r.Get("/openshiftversions", f.listInstallVersions)
r.Get("/platformworkloadidentityrolesets", f.listPlatformWorkloadIdentityRoleSets)
})
})
})
@ -288,6 +298,10 @@ func (f *frontend) chiAuthenticatedRoutes(router chi.Router) {
r.Get("/", f.getAdminOpenShiftVersions)
r.Put("/", f.putAdminOpenShiftVersion)
})
r.Route("/platformworkloadidentityrolesets", func(r chi.Router) {
r.Get("/", f.getAdminPlatformWorkloadIdentityRoleSets)
r.Put("/", f.putAdminPlatformWorkloadIdentityRoleSet)
})
r.Get("/supportedvmsizes", f.supportedvmsizes)
r.Route("/subscriptions/{subscriptionId}", func(r chi.Router) {
@ -372,7 +386,8 @@ func (f *frontend) setupRouter() chi.Router {
func (f *frontend) Run(ctx context.Context, stop <-chan struct{}, done chan<- struct{}) {
defer recover.Panic(f.baseLog)
go f.changefeed(ctx)
go f.changefeedOcpVersions(ctx)
go f.changefeedRoleSets(ctx)
if stop != nil {
go func() {

Просмотреть файл

@ -97,7 +97,7 @@ func TestAppLensDetectors(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, func(*logrus.Entry, env.Interface, *api.OpenShiftCluster, *api.SubscriptionDocument) (adminactions.AzureActions, error) {
return a, nil
}, nil)

Просмотреть файл

@ -114,7 +114,7 @@ func TestDeleteOpenShiftCluster(t *testing.T) {
ti.subscriptionsClient.SetError(tt.dbError)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -95,7 +95,7 @@ func TestGetOpenShiftCluster(t *testing.T) {
ti.openShiftClustersClient.SetError(tt.dbError)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -204,7 +204,7 @@ func TestListOpenShiftCluster(t *testing.T) {
aead := testdatabase.NewFakeAEAD()
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, aead, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, aead, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -158,14 +158,14 @@ func TestPreflightValidation(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, ti.platformWorkloadIdentityRoleSetsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
oc := tt.preflightRequest()
go f.Run(ctx, nil, nil)
f.mu.Lock()
f.ocpVersionsMu.Lock()
f.defaultOcpVersion = "4.10.0"
f.enabledOcpVersions = map[string]*api.OpenShiftVersion{
f.defaultOcpVersion: {
@ -174,7 +174,7 @@ func TestPreflightValidation(t *testing.T) {
},
},
}
f.mu.Unlock()
f.ocpVersionsMu.Unlock()
headers := http.Header{
"Content-Type": []string{"application/json"},

Просмотреть файл

@ -1727,7 +1727,7 @@ func TestPutOrPatchOpenShiftClusterAdminAPI(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}
@ -2800,7 +2800,7 @@ func TestPutOrPatchOpenShiftCluster(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, ti.platformWorkloadIdentityRoleSetsDatabase, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}
@ -2817,14 +2817,14 @@ func TestPutOrPatchOpenShiftCluster(t *testing.T) {
}
go f.Run(ctx, nil, nil)
f.mu.Lock()
f.ocpVersionsMu.Lock()
f.enabledOcpVersions = tt.changeFeed
for key, doc := range tt.changeFeed {
if doc.Properties.Default {
f.defaultOcpVersion = key
}
}
f.mu.Unlock()
f.ocpVersionsMu.Unlock()
oc := &v20200430.OpenShiftCluster{}
if tt.request != nil {
@ -3133,7 +3133,7 @@ func TestPutOrPatchOpenShiftClusterValidated(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, ti.openShiftVersionsDatabase, ti.platformWorkloadIdentityRoleSetsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, ti.enricher)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -267,7 +267,7 @@ func TestPostOpenShiftClusterCredentials(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -242,7 +242,7 @@ func TestPostOpenShiftClusterKubeConfigCredentials(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, apis, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -35,11 +35,11 @@ func (f *frontend) listInstallVersions(w http.ResponseWriter, r *http.Request) {
func (f *frontend) getEnabledInstallVersions(ctx context.Context) []*api.OpenShiftVersion {
versions := make([]*api.OpenShiftVersion, 0)
f.mu.RLock()
f.ocpVersionsMu.RLock()
for _, v := range f.enabledOcpVersions {
versions = append(versions, v)
}
f.mu.RUnlock()
f.ocpVersionsMu.RUnlock()
return versions
}

Просмотреть файл

@ -78,21 +78,21 @@ func TestListInstallVersions(t *testing.T) {
ti := newTestInfra(t).WithSubscriptions().WithOpenShiftVersions()
defer ti.done()
frontend, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
frontend, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, ti.openShiftVersionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
go frontend.Run(ctx, nil, nil)
frontend.mu.Lock()
frontend.ocpVersionsMu.Lock()
frontend.enabledOcpVersions = tt.changeFeed
for key, doc := range tt.changeFeed {
if doc.Properties.Enabled {
frontend.defaultOcpVersion = key
}
}
frontend.mu.Unlock()
frontend.ocpVersionsMu.Unlock()
resp, b, err := ti.request(method,
fmt.Sprintf("https://server/subscriptions/%s/providers/Microsoft.RedHatOpenShift/locations/%s/openshiftversions?api-version=%s", mockSubID, ti.env.Location(), tt.apiVersion),

Просмотреть файл

@ -0,0 +1,45 @@
package frontend
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/sirupsen/logrus"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/frontend/middleware"
)
func (f *frontend) listPlatformWorkloadIdentityRoleSets(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log := ctx.Value(middleware.ContextKeyLog).(*logrus.Entry)
apiVersion := r.URL.Query().Get(api.APIVersionKey)
resourceProviderNamespace := chi.URLParam(r, "resourceProviderNamespace")
if f.apis[apiVersion].PlatformWorkloadIdentityRoleSetConverter == nil {
api.WriteError(w, http.StatusBadRequest, api.CloudErrorCodeInvalidResourceType, "", "The endpoint could not be found in the namespace '%s' for api version '%s'.", resourceProviderNamespace, apiVersion)
return
}
roleSets := f.getAvailablePlatformWorkloadIdentityRoleSets(ctx)
converter := f.apis[apiVersion].PlatformWorkloadIdentityRoleSetConverter
b, err := json.MarshalIndent(converter.ToExternalList(roleSets), "", " ")
reply(log, w, nil, b, err)
}
func (f *frontend) getAvailablePlatformWorkloadIdentityRoleSets(ctx context.Context) []*api.PlatformWorkloadIdentityRoleSet {
roleSets := make([]*api.PlatformWorkloadIdentityRoleSet, 0)
f.platformWorkloadIdentityRoleSetsMu.RLock()
for _, pwirs := range f.availablePlatformWorkloadIdentityRoleSets {
roleSets = append(roleSets, pwirs)
}
f.platformWorkloadIdentityRoleSetsMu.RUnlock()
return roleSets
}

Просмотреть файл

@ -0,0 +1,176 @@
package frontend
import (
"context"
"encoding/json"
"fmt"
"net/http"
"sort"
"testing"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/api/v20240812preview"
"github.com/Azure/ARO-RP/pkg/metrics/noop"
"github.com/Azure/ARO-RP/pkg/util/version"
)
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
func TestListPlatformWorkloadIdentityRoleSets(t *testing.T) {
mockSubID := "00000000-0000-0000-0000-000000000000"
method := http.MethodGet
ctx := context.Background()
for _, tt := range []struct {
name string
changeFeed map[string]*api.PlatformWorkloadIdentityRoleSet
apiVersion string
wantStatusCode int
wantResponse v20240812preview.PlatformWorkloadIdentityRoleSetList
wantError string
}{
{
name: "GET request results in StatusOK",
changeFeed: map[string]*api.PlatformWorkloadIdentityRoleSet{
"4.14": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
},
},
},
"4.15": {
Properties: api.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []api.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
ServiceAccounts: []string{
"openshift-cloud-controller-manager:cloud-controller-manager",
},
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
ServiceAccounts: []string{
"openshift-ingress-operator:ingress-operator",
},
},
},
},
},
},
apiVersion: "2024-08-12-preview",
wantStatusCode: 200,
wantResponse: v20240812preview.PlatformWorkloadIdentityRoleSetList{
PlatformWorkloadIdentityRoleSets: []*v20240812preview.PlatformWorkloadIdentityRoleSet{
{
Properties: v20240812preview.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.14",
PlatformWorkloadIdentityRoles: []v20240812preview.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
},
},
},
},
{
Properties: v20240812preview.PlatformWorkloadIdentityRoleSetProperties{
OpenShiftVersion: "4.15",
PlatformWorkloadIdentityRoles: []v20240812preview.PlatformWorkloadIdentityRole{
{
OperatorName: "CloudControllerManager",
RoleDefinitionName: "Azure RedHat OpenShift Cloud Controller Manager Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/a1f96423-95ce-4224-ab27-4e3dc72facd4",
},
{
OperatorName: "ClusterIngressOperator",
RoleDefinitionName: "Azure RedHat OpenShift Cluster Ingress Operator Role",
RoleDefinitionID: "/providers/Microsoft.Authorization/roleDefinitions/0336e1d3-7a87-462b-b6db-342b63f7802c",
},
},
},
},
},
},
},
{
name: "GET request with non-existent API version results in StatusBadRequest",
apiVersion: "invalid",
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidResourceType: : The resource type '' could not be found in the namespace 'microsoft.redhatopenshift' for api version 'invalid'.",
},
{
name: "GET request with old API version that doesn't support MIWI results in StatusBadRequest",
apiVersion: "2022-09-04",
wantStatusCode: http.StatusBadRequest,
wantError: "400: InvalidResourceType: : The endpoint could not be found in the namespace 'microsoft.redhatopenshift' for api version '2022-09-04'.",
},
} {
t.Run(tt.name, func(t *testing.T) {
ti := newTestInfra(t).WithSubscriptions().WithPlatformWorkloadIdentityRoleSets()
defer ti.done()
frontend, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, nil, nil, nil, nil, nil, ti.platformWorkloadIdentityRoleSetsDatabase, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
go frontend.Run(ctx, nil, nil)
frontend.platformWorkloadIdentityRoleSetsMu.Lock()
frontend.availablePlatformWorkloadIdentityRoleSets = tt.changeFeed
frontend.platformWorkloadIdentityRoleSetsMu.Unlock()
resp, b, err := ti.request(method,
fmt.Sprintf("https://server/subscriptions/%s/providers/Microsoft.RedHatOpenShift/locations/%s/platformworkloadidentityrolesets?api-version=%s", mockSubID, ti.env.Location(), tt.apiVersion),
nil, nil)
if err != nil {
t.Fatal(err)
}
// sort the response as the version order might be changed
if b != nil && resp.StatusCode == http.StatusOK {
var r v20240812preview.PlatformWorkloadIdentityRoleSetList
if err = json.Unmarshal(b, &r); err != nil {
t.Error(err)
}
sort.Slice(r.PlatformWorkloadIdentityRoleSets, func(i, j int) bool {
return version.CreateSemverFromMinorVersionString(r.PlatformWorkloadIdentityRoleSets[i].Properties.OpenShiftVersion).LessThan(*version.CreateSemverFromMinorVersionString(r.PlatformWorkloadIdentityRoleSets[j].Properties.OpenShiftVersion))
})
b, err = json.Marshal(r)
if err != nil {
t.Error(err)
}
}
// marshal the expected response into a []byte otherwise
// it will compare zero values to omitempty json tags
want, err := json.Marshal(tt.wantResponse)
if err != nil {
t.Error(err)
}
err = validateResponse(resp, b, tt.wantStatusCode, tt.wantError, want)
if err != nil {
t.Error(err)
}
})
}
}

Просмотреть файл

@ -21,9 +21,10 @@ func (f *frontend) checkReady() bool {
return false
}
_, ok := f.lastChangefeed.Load().(time.Time)
_, okOcpVersions := f.lastOcpVersionsChangefeed.Load().(time.Time)
_, okPlatformWorkloadIdentityRoleSets := f.lastPlatformWorkloadIdentityRoleSetsChangefeed.Load().(time.Time)
return ok &&
return okOcpVersions && okPlatformWorkloadIdentityRoleSets &&
f.ready.Load().(bool) &&
f.env.ArmClientAuthorizer().IsReady() &&
f.env.AdminClientAuthorizer().IsReady()

Просмотреть файл

@ -77,14 +77,15 @@ func TestSecurity(t *testing.T) {
log := logrus.NewEntry(logrus.StandardLogger())
auditHook, auditEntry := testlog.NewAudit()
f, err := NewFrontend(ctx, auditEntry, log, _env, nil, nil, nil, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, auditEntry, log, _env, nil, nil, nil, nil, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
// enable /healthz to return 200
f.startTime = time.Time{}
f.lastChangefeed.Store(time.Time{})
f.lastOcpVersionsChangefeed.Store(time.Time{})
f.lastPlatformWorkloadIdentityRoleSetsChangefeed.Store(time.Time{})
go f.Run(ctx, nil, nil)

Просмотреть файл

@ -68,18 +68,20 @@ type testInfra struct {
fixture *testdatabase.Fixture
checker *testdatabase.Checker
openShiftClustersClient *cosmosdb.FakeOpenShiftClusterDocumentClient
openShiftClustersDatabase database.OpenShiftClusters
asyncOperationsClient *cosmosdb.FakeAsyncOperationDocumentClient
asyncOperationsDatabase database.AsyncOperations
billingClient *cosmosdb.FakeBillingDocumentClient
billingDatabase database.Billing
clusterManagerClient *cosmosdb.FakeClusterManagerConfigurationDocumentClient
clusterManagerDatabase database.ClusterManagerConfigurations
subscriptionsClient *cosmosdb.FakeSubscriptionDocumentClient
subscriptionsDatabase database.Subscriptions
openShiftVersionsClient *cosmosdb.FakeOpenShiftVersionDocumentClient
openShiftVersionsDatabase database.OpenShiftVersions
openShiftClustersClient *cosmosdb.FakeOpenShiftClusterDocumentClient
openShiftClustersDatabase database.OpenShiftClusters
asyncOperationsClient *cosmosdb.FakeAsyncOperationDocumentClient
asyncOperationsDatabase database.AsyncOperations
billingClient *cosmosdb.FakeBillingDocumentClient
billingDatabase database.Billing
clusterManagerClient *cosmosdb.FakeClusterManagerConfigurationDocumentClient
clusterManagerDatabase database.ClusterManagerConfigurations
subscriptionsClient *cosmosdb.FakeSubscriptionDocumentClient
subscriptionsDatabase database.Subscriptions
openShiftVersionsClient *cosmosdb.FakeOpenShiftVersionDocumentClient
openShiftVersionsDatabase database.OpenShiftVersions
platformWorkloadIdentityRoleSetsClient *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient
platformWorkloadIdentityRoleSetsDatabase database.PlatformWorkloadIdentityRoleSets
}
func newTestInfra(t *testing.T) *testInfra {
@ -179,6 +181,13 @@ func (ti *testInfra) WithOpenShiftVersions() *testInfra {
return ti
}
func (ti *testInfra) WithPlatformWorkloadIdentityRoleSets() *testInfra {
uuid := deterministicuuid.NewTestUUIDGenerator(8)
ti.platformWorkloadIdentityRoleSetsDatabase, ti.platformWorkloadIdentityRoleSetsClient = testdatabase.NewFakePlatformWorkloadIdentityRoleSets(uuid)
ti.fixture.WithPlatformWorkloadIdentityRoleSets(ti.platformWorkloadIdentityRoleSetsDatabase, uuid)
return ti
}
func (ti *testInfra) WithClusterManagerConfigurations() *testInfra {
ti.clusterManagerDatabase, ti.clusterManagerClient = testdatabase.NewFakeClusterManager()
ti.fixture.WithClusterManagerConfigurations(ti.clusterManagerDatabase)

Просмотреть файл

@ -244,7 +244,7 @@ func TestPutSubscription(t *testing.T) {
t.Fatal(err)
}
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
f, err := NewFrontend(ctx, ti.audit, ti.log, ti.env, ti.asyncOperationsDatabase, ti.clusterManagerDatabase, ti.openShiftClustersDatabase, ti.subscriptionsDatabase, nil, nil, api.APIs, &noop.Noop{}, &noop.Noop{}, nil, nil, nil, nil, nil)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -203,14 +203,14 @@ func validateAdminMasterVMSize(vmSize string) error {
// validateInstallVersion validates the install version set in the clusterprofile.version
// TODO convert this into static validation instead of this receiver function in the validation for frontend.
func (f *frontend) validateInstallVersion(ctx context.Context, oc *api.OpenShiftCluster) error {
f.mu.RLock()
f.ocpVersionsMu.RLock()
// If this request is from an older API or the user did not specify
// the version to install, use the default version.
if oc.Properties.ClusterProfile.Version == "" {
oc.Properties.ClusterProfile.Version = f.defaultOcpVersion
}
_, ok := f.enabledOcpVersions[oc.Properties.ClusterProfile.Version]
f.mu.RUnlock()
f.ocpVersionsMu.RUnlock()
if !ok || !validate.RxInstallVersion.MatchString(oc.Properties.ClusterProfile.Version) {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, "properties.clusterProfile.version", "The requested OpenShift version '%s' is invalid.", oc.Properties.ClusterProfile.Version)

Просмотреть файл

@ -0,0 +1,17 @@
package version
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"github.com/coreos/go-semver/semver"
)
// CreateSemverFromMinorVersionString takes in a string representing a semantic version number that is
// missing the patch version from the end (ex.: "4.13") and appends a ".0" and returns a semver.Version.
// It results in a panic if v + ".0" does not turn out to be a valid semantic version number. This function
// is useful for applications such as making it easier to compare strings that represent OpenShift minor
// versions.
func CreateSemverFromMinorVersionString(v string) *semver.Version {
return semver.New(v + ".0")
}

Просмотреть файл

@ -18,14 +18,15 @@ import (
const deletionTimeSetSentinel = 123456789
type Checker struct {
openshiftClusterDocuments []*api.OpenShiftClusterDocument
subscriptionDocuments []*api.SubscriptionDocument
billingDocuments []*api.BillingDocument
asyncOperationDocuments []*api.AsyncOperationDocument
portalDocuments []*api.PortalDocument
gatewayDocuments []*api.GatewayDocument
openShiftVersionDocuments []*api.OpenShiftVersionDocument
validationResult []*api.ValidationResult
openshiftClusterDocuments []*api.OpenShiftClusterDocument
subscriptionDocuments []*api.SubscriptionDocument
billingDocuments []*api.BillingDocument
asyncOperationDocuments []*api.AsyncOperationDocument
portalDocuments []*api.PortalDocument
gatewayDocuments []*api.GatewayDocument
openShiftVersionDocuments []*api.OpenShiftVersionDocument
platformWorkloadIdentityRoleSetDocuments []*api.PlatformWorkloadIdentityRoleSetDocument
validationResult []*api.ValidationResult
}
func NewChecker() *Checker {
@ -109,6 +110,17 @@ func (f *Checker) AddOpenShiftVersionDocuments(docs ...*api.OpenShiftVersionDocu
}
}
func (f *Checker) AddPlatformWorkloadIdentityRoleSetDocuments(docs ...*api.PlatformWorkloadIdentityRoleSetDocument) {
for _, doc := range docs {
docCopy, err := deepCopy(doc)
if err != nil {
panic(err)
}
f.platformWorkloadIdentityRoleSetDocuments = append(f.platformWorkloadIdentityRoleSetDocuments, docCopy.(*api.PlatformWorkloadIdentityRoleSetDocument))
}
}
func (f *Checker) AddValidationResult(docs ...*api.ValidationResult) {
for _, doc := range docs {
docCopy, err := deepCopy(doc)
@ -273,3 +285,27 @@ func (f *Checker) CheckOpenShiftVersions(versions *cosmosdb.FakeOpenShiftVersion
return errs
}
func (f *Checker) CheckPlatformWorkloadIdentityRoleSets(roleSets *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient) (errs []error) {
ctx := context.Background()
all, err := roleSets.ListAll(ctx, nil)
if err != nil {
return []error{err}
}
sort.Slice(all.PlatformWorkloadIdentityRoleSetDocuments, func(i, j int) bool {
return all.PlatformWorkloadIdentityRoleSetDocuments[i].ID < all.PlatformWorkloadIdentityRoleSetDocuments[j].ID
})
if len(f.platformWorkloadIdentityRoleSetDocuments) != 0 && len(all.PlatformWorkloadIdentityRoleSetDocuments) == len(f.platformWorkloadIdentityRoleSetDocuments) {
diff := deep.Equal(all.PlatformWorkloadIdentityRoleSetDocuments, f.platformWorkloadIdentityRoleSetDocuments)
for _, i := range diff {
errs = append(errs, errors.New(i))
}
} else if len(all.PlatformWorkloadIdentityRoleSetDocuments) != 0 || len(f.platformWorkloadIdentityRoleSetDocuments) != 0 {
errs = append(errs, fmt.Errorf("role sets length different, %d vs %d", len(all.PlatformWorkloadIdentityRoleSetDocuments), len(f.platformWorkloadIdentityRoleSetDocuments)))
}
return errs
}

Просмотреть файл

@ -12,25 +12,28 @@ import (
)
type Fixture struct {
openshiftClusterDocuments []*api.OpenShiftClusterDocument
subscriptionDocuments []*api.SubscriptionDocument
billingDocuments []*api.BillingDocument
asyncOperationDocuments []*api.AsyncOperationDocument
portalDocuments []*api.PortalDocument
gatewayDocuments []*api.GatewayDocument
openShiftVersionDocuments []*api.OpenShiftVersionDocument
clusterManagerConfigurationDocuments []*api.ClusterManagerConfigurationDocument
openshiftClusterDocuments []*api.OpenShiftClusterDocument
subscriptionDocuments []*api.SubscriptionDocument
billingDocuments []*api.BillingDocument
asyncOperationDocuments []*api.AsyncOperationDocument
portalDocuments []*api.PortalDocument
gatewayDocuments []*api.GatewayDocument
openShiftVersionDocuments []*api.OpenShiftVersionDocument
platformWorkloadIdentityRoleSetDocuments []*api.PlatformWorkloadIdentityRoleSetDocument
clusterManagerConfigurationDocuments []*api.ClusterManagerConfigurationDocument
openShiftClustersDatabase database.OpenShiftClusters
billingDatabase database.Billing
subscriptionsDatabase database.Subscriptions
asyncOperationsDatabase database.AsyncOperations
portalDatabase database.Portal
gatewayDatabase database.Gateway
openShiftVersionsDatabase database.OpenShiftVersions
clusterManagerConfigurationsDatabase database.ClusterManagerConfigurations
openShiftClustersDatabase database.OpenShiftClusters
billingDatabase database.Billing
subscriptionsDatabase database.Subscriptions
asyncOperationsDatabase database.AsyncOperations
portalDatabase database.Portal
gatewayDatabase database.Gateway
openShiftVersionsDatabase database.OpenShiftVersions
platformWorkloadIdentityRoleSetsDatabase database.PlatformWorkloadIdentityRoleSets
clusterManagerConfigurationsDatabase database.ClusterManagerConfigurations
openShiftVersionsUUID uuid.Generator
openShiftVersionsUUID uuid.Generator
platformWorkloadIdentityRoleSetsUUID uuid.Generator
}
func NewFixture() *Fixture {
@ -78,6 +81,12 @@ func (f *Fixture) WithOpenShiftVersions(db database.OpenShiftVersions, uuid uuid
return f
}
func (f *Fixture) WithPlatformWorkloadIdentityRoleSets(db database.PlatformWorkloadIdentityRoleSets, uuid uuid.Generator) *Fixture {
f.platformWorkloadIdentityRoleSetsDatabase = db
f.platformWorkloadIdentityRoleSetsUUID = uuid
return f
}
func (f *Fixture) AddOpenShiftClusterDocuments(docs ...*api.OpenShiftClusterDocument) {
for _, doc := range docs {
docCopy, err := deepCopy(doc)
@ -155,6 +164,17 @@ func (f *Fixture) AddOpenShiftVersionDocuments(docs ...*api.OpenShiftVersionDocu
}
}
func (f *Fixture) AddPlatformWorkloadIdentityRoleSetDocuments(docs ...*api.PlatformWorkloadIdentityRoleSetDocument) {
for _, doc := range docs {
docCopy, err := deepCopy(doc)
if err != nil {
panic(err)
}
f.platformWorkloadIdentityRoleSetDocuments = append(f.platformWorkloadIdentityRoleSetDocuments, docCopy.(*api.PlatformWorkloadIdentityRoleSetDocument))
}
}
func (f *Fixture) AddClusterManagerConfigurationDocuments(docs ...*api.ClusterManagerConfigurationDocument) {
for _, doc := range docs {
docCopy, err := deepCopy(doc)
@ -224,6 +244,16 @@ func (f *Fixture) Create() error {
}
}
for _, i := range f.platformWorkloadIdentityRoleSetDocuments {
if i.ID == "" {
i.ID = f.platformWorkloadIdentityRoleSetsDatabase.NewUUID()
}
_, err := f.platformWorkloadIdentityRoleSetsDatabase.Create(ctx, i)
if err != nil {
return err
}
}
for _, i := range f.clusterManagerConfigurationDocuments {
if i.ID == "" {
i.ID = f.clusterManagerConfigurationsDatabase.NewUUID()

Просмотреть файл

@ -72,6 +72,12 @@ func NewFakeOpenShiftVersions(uuid uuid.Generator) (db database.OpenShiftVersion
return db, client
}
func NewFakePlatformWorkloadIdentityRoleSets(uuid uuid.Generator) (db database.PlatformWorkloadIdentityRoleSets, client *cosmosdb.FakePlatformWorkloadIdentityRoleSetDocumentClient) {
client = cosmosdb.NewFakePlatformWorkloadIdentityRoleSetDocumentClient(jsonHandle)
db = database.NewPlatformWorkloadIdentityRoleSetsWithProvidedClient(client, uuid)
return db, client
}
func NewFakeClusterManager() (db database.ClusterManagerConfigurations, client *cosmosdb.FakeClusterManagerConfigurationDocumentClient) {
uuid := deterministicuuid.NewTestUUIDGenerator(deterministicuuid.CLUSTERMANAGER)
client = cosmosdb.NewFakeClusterManagerConfigurationDocumentClient(jsonHandle)