* add workerProfilesStatus field to hold the enriched worker profile data

* update swagger

* swagger examples

* update clients

* resolve golint

* update defaults

* validate worker Profile status is nil in input request

* make client changes after rebase

* rebase

* update workerProfiles references and UTs

* fix golint errors

* remove duplicate logic of verifing workerProfilesStatus not nil

---------

Co-authored-by: gniranjan <gniranjan@microsoft.com>
This commit is contained in:
Goutham Muguluvalli Niranjan 2023-09-05 13:56:27 -05:00 коммит произвёл GitHub
Родитель 91a03574d6
Коммит dba48c1f0c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
58 изменённых файлов: 629 добавлений и 91 удалений

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

@ -4,4 +4,4 @@
1d167031baf0209fe8c46df9654585c64e8cc9a0c89555d7479c4ed6dc150251 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2022-09-04/redhatopenshift.json
622404e8311c62f27fba778e30e760bb1901e5bd221b23de72f449cafbdf0c45 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-04-01/redhatopenshift.json
3aede70b183bad612c23cb776fe5a932c5709334e1fe1ad7ff8772b58be3661f swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/preview/2023-07-01-preview/redhatopenshift.json
0c2bfc4b4308ff10d3cdd1c66c1356ba4153342ce536d478bcbb515fa1fe5958 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-09-04/redhatopenshift.json
3127f0a6acebf9ce09623df69dbd88824384b58967fe36c19acf2e2cf34c46b2 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-09-04/redhatopenshift.json

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

@ -28,33 +28,36 @@ type OpenShiftCluster struct {
// OpenShiftClusterProperties represents an OpenShift cluster's properties.
type OpenShiftClusterProperties struct {
ArchitectureVersion ArchitectureVersion `json:"architectureVersion"` // ArchitectureVersion is int so 0 is valid value to be returned
ProvisioningState ProvisioningState `json:"provisioningState,omitempty"`
LastProvisioningState ProvisioningState `json:"lastProvisioningState,omitempty"`
FailedProvisioningState ProvisioningState `json:"failedProvisioningState,omitempty"`
LastAdminUpdateError string `json:"lastAdminUpdateError,omitempty"`
MaintenanceTask MaintenanceTask `json:"maintenanceTask,omitempty" mutable:"true"`
OperatorFlags OperatorFlags `json:"operatorFlags,omitempty" mutable:"true"`
OperatorVersion string `json:"operatorVersion,omitempty" mutable:"true"`
CreatedAt time.Time `json:"createdAt,omitempty"`
CreatedBy string `json:"createdBy,omitempty"`
ProvisionedBy string `json:"provisionedBy,omitempty"`
ClusterProfile ClusterProfile `json:"clusterProfile,omitempty"`
FeatureProfile FeatureProfile `json:"featureProfile,omitempty"`
ConsoleProfile ConsoleProfile `json:"consoleProfile,omitempty"`
ServicePrincipalProfile ServicePrincipalProfile `json:"servicePrincipalProfile,omitempty"`
NetworkProfile NetworkProfile `json:"networkProfile,omitempty"`
MasterProfile MasterProfile `json:"masterProfile,omitempty"`
WorkerProfiles []WorkerProfile `json:"workerProfiles,omitempty"`
APIServerProfile APIServerProfile `json:"apiserverProfile,omitempty"`
IngressProfiles []IngressProfile `json:"ingressProfiles,omitempty"`
Install *Install `json:"install,omitempty"`
StorageSuffix string `json:"storageSuffix,omitempty"`
RegistryProfiles []RegistryProfile `json:"registryProfiles,omitempty"`
ImageRegistryStorageAccountName string `json:"imageRegistryStorageAccountName,omitempty"`
InfraID string `json:"infraId,omitempty"`
HiveProfile HiveProfile `json:"hiveProfile,omitempty"`
PucmPending bool `json:"pucmPending,omitempty"`
ArchitectureVersion ArchitectureVersion `json:"architectureVersion"` // ArchitectureVersion is int so 0 is valid value to be returned
ProvisioningState ProvisioningState `json:"provisioningState,omitempty"`
LastProvisioningState ProvisioningState `json:"lastProvisioningState,omitempty"`
FailedProvisioningState ProvisioningState `json:"failedProvisioningState,omitempty"`
LastAdminUpdateError string `json:"lastAdminUpdateError,omitempty"`
MaintenanceTask MaintenanceTask `json:"maintenanceTask,omitempty" mutable:"true"`
OperatorFlags OperatorFlags `json:"operatorFlags,omitempty" mutable:"true"`
OperatorVersion string `json:"operatorVersion,omitempty" mutable:"true"`
CreatedAt time.Time `json:"createdAt,omitempty"`
CreatedBy string `json:"createdBy,omitempty"`
ProvisionedBy string `json:"provisionedBy,omitempty"`
ClusterProfile ClusterProfile `json:"clusterProfile,omitempty"`
FeatureProfile FeatureProfile `json:"featureProfile,omitempty"`
ConsoleProfile ConsoleProfile `json:"consoleProfile,omitempty"`
ServicePrincipalProfile ServicePrincipalProfile `json:"servicePrincipalProfile,omitempty"`
NetworkProfile NetworkProfile `json:"networkProfile,omitempty"`
MasterProfile MasterProfile `json:"masterProfile,omitempty"`
// WorkerProfiles is used to store the worker profile data that was sent in the api request
WorkerProfiles []WorkerProfile `json:"workerProfiles,omitempty"`
// WorkerProfilesStatus is used to store the enriched worker profile data
WorkerProfilesStatus []WorkerProfile `json:"workerProfilesStatus,omitempty"`
APIServerProfile APIServerProfile `json:"apiserverProfile,omitempty"`
IngressProfiles []IngressProfile `json:"ingressProfiles,omitempty"`
Install *Install `json:"install,omitempty"`
StorageSuffix string `json:"storageSuffix,omitempty"`
RegistryProfiles []RegistryProfile `json:"registryProfiles,omitempty"`
ImageRegistryStorageAccountName string `json:"imageRegistryStorageAccountName,omitempty"`
InfraID string `json:"infraId,omitempty"`
HiveProfile HiveProfile `json:"hiveProfile,omitempty"`
PucmPending bool `json:"pucmPending,omitempty"`
}
// ProvisioningState represents a provisioning state.

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

@ -131,6 +131,21 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
}
if oc.Properties.WorkerProfilesStatus != nil {
out.Properties.WorkerProfilesStatus = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfilesStatus))
for _, p := range oc.Properties.WorkerProfilesStatus {
out.Properties.WorkerProfilesStatus = append(out.Properties.WorkerProfilesStatus, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),
DiskSizeGB: p.DiskSizeGB,
SubnetID: p.SubnetID,
Count: p.Count,
EncryptionAtHost: EncryptionAtHost(p.EncryptionAtHost),
DiskEncryptionSetID: p.DiskEncryptionSetID,
})
}
}
if oc.Properties.IngressProfiles != nil {
out.Properties.IngressProfiles = make([]IngressProfile, 0, len(oc.Properties.IngressProfiles))
for _, p := range oc.Properties.IngressProfiles {
@ -285,6 +300,20 @@ func (c openShiftClusterConverter) ToInternal(_oc interface{}, out *api.OpenShif
out.Properties.WorkerProfiles[i].DiskEncryptionSetID = oc.Properties.WorkerProfiles[i].DiskEncryptionSetID
}
}
if oc.Properties.WorkerProfilesStatus != nil {
out.Properties.WorkerProfilesStatus = make([]api.WorkerProfile, len(oc.Properties.WorkerProfilesStatus))
for _, p := range oc.Properties.WorkerProfilesStatus {
out.Properties.WorkerProfilesStatus = append(out.Properties.WorkerProfilesStatus, api.WorkerProfile{
Name: p.Name,
VMSize: api.VMSize(p.VMSize),
DiskSizeGB: p.DiskSizeGB,
SubnetID: p.SubnetID,
Count: p.Count,
EncryptionAtHost: api.EncryptionAtHost(p.EncryptionAtHost),
DiskEncryptionSetID: p.DiskEncryptionSetID,
})
}
}
out.Properties.APIServerProfile.Visibility = api.Visibility(oc.Properties.APIServerProfile.Visibility)
out.Properties.APIServerProfile.URL = oc.Properties.APIServerProfile.URL
out.Properties.APIServerProfile.IP = oc.Properties.APIServerProfile.IP

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

@ -21,6 +21,12 @@ func SetDefaults(doc *OpenShiftClusterDocument) {
}
}
for i, wp := range doc.OpenShiftCluster.Properties.WorkerProfilesStatus {
if wp.EncryptionAtHost == "" {
doc.OpenShiftCluster.Properties.WorkerProfilesStatus[i].EncryptionAtHost = EncryptionAtHostDisabled
}
}
if doc.OpenShiftCluster.Properties.ClusterProfile.FipsValidatedModules == "" {
doc.OpenShiftCluster.Properties.ClusterProfile.FipsValidatedModules = FipsValidatedModulesDisabled
}

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

@ -31,6 +31,11 @@ func validOpenShiftClusterDocument() *OpenShiftClusterDocument {
EncryptionAtHost: EncryptionAtHostDisabled,
},
},
WorkerProfilesStatus: []WorkerProfile{
{
EncryptionAtHost: EncryptionAtHostDisabled,
},
},
ClusterProfile: ClusterProfile{
FipsValidatedModules: FipsValidatedModulesDisabled,
},

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

@ -126,8 +126,12 @@ type OpenShiftClusterProperties struct {
MasterProfile MasterProfile `json:"masterProfile,omitempty"`
// WorkerProfiles is used to store the worker profile data that was sent in the api request
WorkerProfiles []WorkerProfile `json:"workerProfiles,omitempty"`
// WorkerProfilesStatus is used to store the enriched worker profile data
WorkerProfilesStatus []WorkerProfile `json:"workerProfilesStatus,omitempty"`
APIServerProfile APIServerProfile `json:"apiserverProfile,omitempty"`
IngressProfiles []IngressProfile `json:"ingressProfiles,omitempty"`
@ -632,6 +636,15 @@ type WorkerProfile struct {
DiskEncryptionSetID string `json:"diskEncryptionSetId,omitempty"`
}
// GetEnrichedWorkerProfiles returns WorkerProfilesStatus if not nil, otherwise WorkerProfiles
// with their respective json property name
func GetEnrichedWorkerProfiles(ocp OpenShiftClusterProperties) ([]WorkerProfile, string) {
if ocp.WorkerProfilesStatus != nil {
return ocp.WorkerProfilesStatus, "workerProfilesStatus"
}
return ocp.WorkerProfiles, "workerProfiles"
}
// APIServerProfile represents an API server profile
type APIServerProfile struct {
MissingFields

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

@ -67,6 +67,29 @@ func ExampleOpenShiftClusterDocument() *OpenShiftClusterDocument {
Count: 3,
},
},
WorkerProfilesStatus: []WorkerProfile{
{
Name: "worker1",
VMSize: VMSizeStandardD2sV3,
DiskSizeGB: 128,
SubnetID: "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
Count: 1,
},
{
Name: "worker2",
VMSize: VMSizeStandardD2sV3,
DiskSizeGB: 128,
SubnetID: "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
Count: 1,
},
{
Name: "worker3",
VMSize: VMSizeStandardD2sV3,
DiskSizeGB: 128,
SubnetID: "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
Count: 1,
},
},
APIServerProfile: APIServerProfile{
Visibility: VisibilityPublic,
URL: "https://api.cluster.location.aroapp.io:6443/",

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

@ -33,7 +33,9 @@ func NetworkSecurityGroupID(oc *api.OpenShiftCluster, subnetID string) (string,
infraID = "aro"
}
isWorkerSubnet := false
for _, s := range oc.Properties.WorkerProfiles {
workerProfiles, _ := api.GetEnrichedWorkerProfiles(oc.Properties)
for _, s := range workerProfiles {
if strings.EqualFold(subnetID, s.SubnetID) {
isWorkerSubnet = true
break

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

@ -32,6 +32,7 @@ func TestNetworkSecurityGroupID(t *testing.T) {
infraID string
archVersion api.ArchitectureVersion
subnetID string
wpStatus bool
wantNSGID string
wantErr string
}{
@ -64,11 +65,27 @@ func TestNetworkSecurityGroupID(t *testing.T) {
archVersion: api.ArchitectureVersion(42),
wantErr: `unknown architecture version 42`,
},
{
name: "worker arch v2 to use enriched worker Profile",
infraID: "test-1234",
archVersion: api.ArchitectureVersionV2,
wpStatus: true,
subnetID: "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/Enrichedworker",
wantNSGID: "/subscriptions/subscriptionId/resourceGroups/clusterResourceGroup/providers/Microsoft.Network/networkSecurityGroups/test-1234-nsg",
},
} {
t.Run(tt.name, func(t *testing.T) {
oc.Properties.InfraID = tt.infraID
oc.Properties.ArchitectureVersion = tt.archVersion
if tt.wpStatus {
oc.Properties.WorkerProfilesStatus = []api.WorkerProfile{
{
SubnetID: "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/Enrichedworker",
},
}
}
nsgID, err := NetworkSecurityGroupID(oc, tt.subnetID)
utilerror.AssertErrorMessage(t, err, tt.wantErr)

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

@ -51,8 +51,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -51,8 +51,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -54,8 +54,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -54,8 +54,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -54,8 +54,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -55,8 +55,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -96,8 +96,15 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
// Use enriched worker profile data when available
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles = oc.Properties.WorkerProfilesStatus
}
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),

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

@ -9,6 +9,7 @@ import (
func exampleOpenShiftCluster() *OpenShiftCluster {
doc := api.ExampleOpenShiftClusterDocument()
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
return (&openShiftClusterConverter{}).ToExternal(doc.OpenShiftCluster).(*OpenShiftCluster)
}

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

@ -64,6 +64,9 @@ type OpenShiftClusterProperties struct {
// The cluster worker profiles.
WorkerProfiles []WorkerProfile `json:"workerProfiles,omitempty"`
// The cluster worker profiles status.
WorkerProfilesStatus []WorkerProfile `json:"workerProfilesStatus,omitempty"`
// The cluster API server profile.
APIServerProfile APIServerProfile `json:"apiserverProfile,omitempty"`

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

@ -56,8 +56,9 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
if oc.Properties.WorkerProfiles != nil {
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(oc.Properties.WorkerProfiles))
for _, p := range oc.Properties.WorkerProfiles {
workerProfiles := oc.Properties.WorkerProfiles
out.Properties.WorkerProfiles = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfiles = append(out.Properties.WorkerProfiles, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),
@ -70,6 +71,22 @@ func (c openShiftClusterConverter) ToExternal(oc *api.OpenShiftCluster) interfac
}
}
if oc.Properties.WorkerProfilesStatus != nil {
workerProfiles := oc.Properties.WorkerProfilesStatus
out.Properties.WorkerProfilesStatus = make([]WorkerProfile, 0, len(workerProfiles))
for _, p := range workerProfiles {
out.Properties.WorkerProfilesStatus = append(out.Properties.WorkerProfilesStatus, WorkerProfile{
Name: p.Name,
VMSize: VMSize(p.VMSize),
DiskSizeGB: p.DiskSizeGB,
SubnetID: p.SubnetID,
Count: p.Count,
EncryptionAtHost: EncryptionAtHost(p.EncryptionAtHost),
DiskEncryptionSetID: p.DiskEncryptionSetID,
})
}
}
if oc.Properties.IngressProfiles != nil {
out.Properties.IngressProfiles = make([]IngressProfile, 0, len(oc.Properties.IngressProfiles))
for _, p := range oc.Properties.IngressProfiles {
@ -162,6 +179,20 @@ func (c openShiftClusterConverter) ToInternal(_oc interface{}, out *api.OpenShif
out.Properties.WorkerProfiles[i].DiskEncryptionSetID = oc.Properties.WorkerProfiles[i].DiskEncryptionSetID
}
}
if oc.Properties.WorkerProfilesStatus != nil {
out.Properties.WorkerProfilesStatus = make([]api.WorkerProfile, len(oc.Properties.WorkerProfilesStatus))
for _, p := range oc.Properties.WorkerProfilesStatus {
out.Properties.WorkerProfilesStatus = append(out.Properties.WorkerProfilesStatus, api.WorkerProfile{
Name: p.Name,
VMSize: api.VMSize(p.VMSize),
DiskSizeGB: p.DiskSizeGB,
SubnetID: p.SubnetID,
Count: p.Count,
EncryptionAtHost: api.EncryptionAtHost(p.EncryptionAtHost),
DiskEncryptionSetID: p.DiskEncryptionSetID,
})
}
}
out.Properties.APIServerProfile.Visibility = api.Visibility(oc.Properties.APIServerProfile.Visibility)
out.Properties.APIServerProfile.URL = oc.Properties.APIServerProfile.URL
out.Properties.APIServerProfile.IP = oc.Properties.APIServerProfile.IP

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

@ -18,7 +18,7 @@ func ExampleOpenShiftClusterPatchParameter() interface{} {
oc := ExampleOpenShiftClusterPutParameter().(*OpenShiftCluster)
oc.Location = ""
oc.SystemData = nil
oc.Properties.WorkerProfilesStatus = nil
return oc
}
@ -37,14 +37,15 @@ func ExampleOpenShiftClusterPutParameter() interface{} {
oc.Properties.APIServerProfile.IP = ""
oc.Properties.IngressProfiles[0].IP = ""
oc.Properties.MasterProfile.EncryptionAtHost = EncryptionAtHostEnabled
oc.Properties.WorkerProfilesStatus = nil
oc.SystemData = nil
return oc
}
// ExampleOpenShiftClusterResponse returns an example OpenShiftCluster object
// that the RP might return to an end-user
func ExampleOpenShiftClusterResponse() interface{} {
// that the RP might return to an end-user in a GET response
func ExampleOpenShiftClusterGetResponse() interface{} {
oc := exampleOpenShiftCluster()
oc.Properties.ClusterProfile.PullSecret = ""
oc.Properties.ServicePrincipalProfile.ClientSecret = ""
@ -52,12 +53,23 @@ func ExampleOpenShiftClusterResponse() interface{} {
return oc
}
// ExampleOpenShiftClusterResponse returns an example OpenShiftCluster object
// that the RP might return to an end-user in a PUT/PATCH response
func ExampleOpenShiftClusterPutOrPatchResponse() interface{} {
oc := exampleOpenShiftCluster()
oc.Properties.ClusterProfile.PullSecret = ""
oc.Properties.ServicePrincipalProfile.ClientSecret = ""
oc.Properties.WorkerProfilesStatus = nil
return oc
}
// ExampleOpenShiftClusterListResponse returns an example OpenShiftClusterList
// object that the RP might return to an end-user
func ExampleOpenShiftClusterListResponse() interface{} {
return &OpenShiftClusterList{
OpenShiftClusters: []*OpenShiftCluster{
ExampleOpenShiftClusterResponse().(*OpenShiftCluster),
ExampleOpenShiftClusterGetResponse().(*OpenShiftCluster),
},
}
}

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

@ -104,6 +104,9 @@ func (sv openShiftClusterStaticValidator) validateProperties(path string, p *Ope
if err := sv.validateAPIServerProfile(path+".apiserverProfile", &p.APIServerProfile); err != nil {
return err
}
if len(p.WorkerProfilesStatus) != 0 {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, path+".workerProfilesStatus", "Worker Profile Status must be set to nil.")
}
if isCreate {
if len(p.WorkerProfiles) != 1 {

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

@ -243,6 +243,22 @@ func TestOpenShiftClusterStaticValidateProperties(t *testing.T) {
},
wantErr: "400: InvalidParameter: properties.provisioningState: The provided provisioning state 'invalid' is invalid.",
},
{
name: "workerProfileStatus nonNil",
modify: func(oc *OpenShiftCluster) {
oc.Properties.WorkerProfilesStatus = []WorkerProfile{
{
Name: "worker",
VMSize: "Standard_D4s_v3",
EncryptionAtHost: EncryptionAtHostDisabled,
DiskSizeGB: 128,
SubnetID: fmt.Sprintf("/subscriptions/%s/resourceGroups/vnet/providers/Microsoft.Network/virtualNetworks/test-vnet/subnets/worker", subscriptionID),
Count: 3,
},
}
},
wantErr: "400: InvalidParameter: properties.workerProfilesStatus: Worker Profile Status must be set to nil.",
},
}
createTests := []*validateTest{
{

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

@ -748,12 +748,47 @@ type OpenShiftClusterProperties struct {
MasterProfile *MasterProfile `json:"masterProfile,omitempty"`
// WorkerProfiles - The cluster worker profiles.
WorkerProfiles *[]WorkerProfile `json:"workerProfiles,omitempty"`
// WorkerProfilesStatus - READ-ONLY; The cluster worker profiles status.
WorkerProfilesStatus *[]WorkerProfile `json:"workerProfilesStatus,omitempty"`
// ApiserverProfile - The cluster API server profile.
ApiserverProfile *APIServerProfile `json:"apiserverProfile,omitempty"`
// IngressProfiles - The cluster ingress profiles.
IngressProfiles *[]IngressProfile `json:"ingressProfiles,omitempty"`
}
// MarshalJSON is the custom marshaler for OpenShiftClusterProperties.
func (oscp OpenShiftClusterProperties) MarshalJSON() ([]byte, error) {
objectMap := make(map[string]interface{})
if oscp.ProvisioningState != "" {
objectMap["provisioningState"] = oscp.ProvisioningState
}
if oscp.ClusterProfile != nil {
objectMap["clusterProfile"] = oscp.ClusterProfile
}
if oscp.ConsoleProfile != nil {
objectMap["consoleProfile"] = oscp.ConsoleProfile
}
if oscp.ServicePrincipalProfile != nil {
objectMap["servicePrincipalProfile"] = oscp.ServicePrincipalProfile
}
if oscp.NetworkProfile != nil {
objectMap["networkProfile"] = oscp.NetworkProfile
}
if oscp.MasterProfile != nil {
objectMap["masterProfile"] = oscp.MasterProfile
}
if oscp.WorkerProfiles != nil {
objectMap["workerProfiles"] = oscp.WorkerProfiles
}
if oscp.ApiserverProfile != nil {
objectMap["apiserverProfile"] = oscp.ApiserverProfile
}
if oscp.IngressProfiles != nil {
objectMap["ingressProfiles"] = oscp.IngressProfiles
}
return json.Marshal(objectMap)
}
// OpenShiftClustersCreateOrUpdateFuture an abstraction for monitoring and retrieving the results of a
// long-running operation.
type OpenShiftClustersCreateOrUpdateFuture struct {

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

@ -182,10 +182,12 @@ func (m *manager) attachNSGs(ctx context.Context) error {
if m.doc.OpenShiftCluster.Properties.NetworkProfile.PreconfiguredNSG == api.PreconfiguredNSGEnabled {
return nil
}
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
workerSubnetId := workerProfiles[0].SubnetID
for _, subnetID := range []string{
m.doc.OpenShiftCluster.Properties.MasterProfile.SubnetID,
m.doc.OpenShiftCluster.Properties.WorkerProfiles[0].SubnetID,
workerSubnetId,
} {
m.log.Printf("attaching network security group to subnet %s", subnetID)

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

@ -92,13 +92,15 @@ func (m *manager) storageAccount(name, region string, encrypted bool) *arm.Resou
// Virtual network rules to allow the cluster subnets to directly reach the storage accounts
// are only needed when egress lockdown is not enabled.
if !m.doc.OpenShiftCluster.Properties.FeatureProfile.GatewayEnabled {
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
workerSubnetId := workerProfiles[0].SubnetID
virtualNetworkRules = append(virtualNetworkRules, []mgmtstorage.VirtualNetworkRule{
{
VirtualNetworkResourceID: &m.doc.OpenShiftCluster.Properties.MasterProfile.SubnetID,
Action: mgmtstorage.Allow,
},
{
VirtualNetworkResourceID: &m.doc.OpenShiftCluster.Properties.WorkerProfiles[0].SubnetID,
VirtualNetworkResourceID: &workerSubnetId,
Action: mgmtstorage.Allow,
},
}...)

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

@ -6,6 +6,8 @@ package cluster
import (
"context"
"fmt"
"github.com/Azure/ARO-RP/pkg/api"
)
// ensureServiceEndpoints should enable service endpoints on
@ -24,8 +26,9 @@ func (m *manager) getSubnetIds() ([]string, error) {
subnets := []string{
m.doc.OpenShiftCluster.Properties.MasterProfile.SubnetID,
}
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
for _, wp := range m.doc.OpenShiftCluster.Properties.WorkerProfiles {
for _, wp := range workerProfiles {
if len(wp.SubnetID) == 0 {
return nil, fmt.Errorf("WorkerProfile '%s' has no SubnetID; check that the corresponding MachineSet is valid", wp.Name)
}

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

@ -107,7 +107,10 @@ func (m *manager) createOrUpdateRouterIPEarly(ctx context.Context) error {
// with this.
// https://docs.microsoft.com/en-us/azure/virtual-network/private-ip-addresses#allocation-method
var err error
ipAddress, err = m.subnet.GetHighestFreeIP(ctx, m.doc.OpenShiftCluster.Properties.WorkerProfiles[0].SubnetID)
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
workerSubnetId := workerProfiles[0].SubnetID
ipAddress, err = m.subnet.GetHighestFreeIP(ctx, workerSubnetId)
if err != nil {
return err
}

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

@ -274,6 +274,52 @@ func TestCreateOrUpdateRouterIPEarly(t *testing.T) {
Return(nil)
},
},
{
name: "private - use enriched worker profile",
fixtureChecker: func(fixture *testdatabase.Fixture, checker *testdatabase.Checker, dbClient *cosmosdb.FakeOpenShiftClusterDocumentClient) {
doc := &api.OpenShiftClusterDocument{
Key: strings.ToLower(key),
OpenShiftCluster: &api.OpenShiftCluster{
ID: key,
Properties: api.OpenShiftClusterProperties{
ClusterProfile: api.ClusterProfile{
ResourceGroupID: resourceGroupID,
},
WorkerProfiles: []api.WorkerProfile{
{
SubnetID: "subnetid",
},
},
WorkerProfilesStatus: []api.WorkerProfile{
{
SubnetID: "enricheWPsubnetid",
},
},
IngressProfiles: []api.IngressProfile{
{
Visibility: api.VisibilityPrivate,
},
},
ProvisioningState: api.ProvisioningStateCreating,
InfraID: "infra",
},
},
}
fixture.AddOpenShiftClusterDocuments(doc)
doc.Dequeues = 1
doc.OpenShiftCluster.Properties.IngressProfiles[0].IP = "1.2.3.4"
checker.AddOpenShiftClusterDocuments(doc)
},
mocks: func(publicIPAddresses *mock_network.MockPublicIPAddressesClient, dns *mock_dns.MockManager, subnet *mock_subnet.MockManager) {
subnet.EXPECT().
GetHighestFreeIP(gomock.Any(), "enricheWPsubnetid").
Return("1.2.3.4", nil)
dns.EXPECT().
CreateOrUpdateRouter(gomock.Any(), gomock.Any(), gomock.Any()).
Return(nil)
},
},
} {
t.Run(tt.name, func(t *testing.T) {
controller := gomock.NewController(t)

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

@ -18,7 +18,9 @@ import (
// The encryption flag is set to false/disabled for legacy storage accounts.
func (m *manager) migrateStorageAccounts(ctx context.Context) error {
resourceGroup := stringutils.LastTokenByte(m.doc.OpenShiftCluster.Properties.ClusterProfile.ResourceGroupID, '/')
if len(m.doc.OpenShiftCluster.Properties.WorkerProfiles) == 0 {
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
if len(workerProfiles) == 0 {
m.log.Error("skipping migrateStorageAccounts due to missing WorkerProfiles.")
return nil
}

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

@ -13,6 +13,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry"
"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/util/version"
)
@ -28,7 +29,10 @@ const (
// configureDefaultStorageClass replaces default storage class provided by OCP with
// a new one which uses disk encryption set (if one supplied by a customer).
func (m *manager) configureDefaultStorageClass(ctx context.Context) error {
if m.doc.OpenShiftCluster.Properties.WorkerProfiles[0].DiskEncryptionSetID == "" {
workerProfiles, _ := api.GetEnrichedWorkerProfiles(m.doc.OpenShiftCluster.Properties)
workerDiskEncryptionSetID := workerProfiles[0].DiskEncryptionSetID
if workerDiskEncryptionSetID == "" {
return nil
}
@ -63,7 +67,7 @@ func (m *manager) configureDefaultStorageClass(ctx context.Context) error {
return err
}
encryptedSC := newEncryptedStorageClass(m.doc.OpenShiftCluster.Properties.WorkerProfiles[0].DiskEncryptionSetID, encryptedStorageClassName, provisioner)
encryptedSC := newEncryptedStorageClass(workerDiskEncryptionSetID, encryptedStorageClassName, provisioner)
_, err = m.kubernetescli.StorageV1().StorageClasses().Create(ctx, encryptedSC, metav1.CreateOptions{})
if err != nil && !kerrors.IsAlreadyExists(err) {
return err

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

@ -25,6 +25,7 @@ func TestConfigureStorageClass(t *testing.T) {
name string
mocks func(kubernetescli *fake.Clientset)
desID string
wpStatus bool
ocpVersion string
wantErr string
wantNewSC bool
@ -39,6 +40,13 @@ func TestConfigureStorageClass(t *testing.T) {
ocpVersion: "4.10.40",
wantNewSC: true,
},
{
name: "Use disk encryption set provided in enriched worker profile",
desID: "fake-des-id",
wpStatus: true,
ocpVersion: "4.10.40",
wantNewSC: true,
},
{
name: "error getting old default StorageClass",
desID: "fake-des-id",
@ -148,6 +156,15 @@ func TestConfigureStorageClass(t *testing.T) {
},
}
if tt.wpStatus {
m.doc.OpenShiftCluster.Properties.WorkerProfiles = nil
m.doc.OpenShiftCluster.Properties.WorkerProfilesStatus = []api.WorkerProfile{
{
DiskEncryptionSetID: tt.desID,
},
}
}
err = m.configureDefaultStorageClass(ctx)
utilerror.AssertErrorMessage(t, err, tt.wantErr)

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

@ -11,6 +11,7 @@ import (
mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/ARO-RP/pkg/api"
apisubnet "github.com/Azure/ARO-RP/pkg/api/util/subnet"
"github.com/Azure/ARO-RP/pkg/util/arm"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
@ -134,7 +135,9 @@ func (a *azureActions) appendAzureNetworkResources(ctx context.Context, armResou
for _, snet := range *vnet.Subnets {
//we already have the VNet resource, filtering subnets instead of fetching them individually with a SubnetClient
interestingSubnet := (*snet.ID == a.oc.Properties.MasterProfile.SubnetID)
for _, wProfile := range a.oc.Properties.WorkerProfiles {
workerProfiles, _ := api.GetEnrichedWorkerProfiles(a.oc.Properties)
for _, wProfile := range workerProfiles {
interestingSubnet = interestingSubnet || (*snet.ID == wProfile.SubnetID)
}
if !interestingSubnet {

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

@ -245,6 +245,9 @@ func (f *frontend) _putOrPatchOpenShiftCluster(ctx context.Context, log *logrus.
doc.OpenShiftCluster.Properties.ClusterProfile.PullSecret = ""
doc.OpenShiftCluster.Properties.ServicePrincipalProfile.ClientSecret = ""
// We don't return enriched worker profile data on PUT/PATCH operations
doc.OpenShiftCluster.Properties.WorkerProfilesStatus = nil
b, err := json.MarshalIndent(converter.ToExternal(doc.OpenShiftCluster), "", " ")
if err != nil {
return nil, err

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

@ -58,8 +58,10 @@ func validateQuota(ctx context.Context, oc *api.OpenShiftCluster, spNetworkUsage
if err != nil {
return err
}
workerProfiles, _ := api.GetEnrichedWorkerProfiles(oc.Properties)
//worker node resource calculation
for _, w := range oc.Properties.WorkerProfiles {
for _, w := range workerProfiles {
err := addRequiredResources(requiredResources, w.VMSize, w.Count)
if err != nil {
return err

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

@ -31,6 +31,7 @@ func TestValidateVMSku(t *testing.T) {
availableSku2 string
restrictedSku string
resourceSkusClientErr error
wpStatus bool
wantErr string
}{
{
@ -40,6 +41,14 @@ func TestValidateVMSku(t *testing.T) {
masterProfileSku: "Standard_D4s_v2",
availableSku: "Standard_D4s_v2",
},
{
name: "worker profile is enriched and skus are valid",
workerProfile1Sku: "Standard_D4s_v2",
workerProfile2Sku: "Standard_D4s_v2",
masterProfileSku: "Standard_D4s_v2",
availableSku: "Standard_D4s_v2",
wpStatus: true,
},
{
name: "worker and master skus are distinct, both valid",
workerProfile1Sku: "Standard_E104i_v5",
@ -203,6 +212,18 @@ func TestValidateVMSku(t *testing.T) {
},
}
if tt.wpStatus {
oc.Properties.WorkerProfiles = nil
oc.Properties.WorkerProfilesStatus = []api.WorkerProfile{
{
VMSize: api.VMSize(tt.workerProfile1Sku),
},
{
VMSize: api.VMSize(tt.workerProfile2Sku),
},
}
}
resourceSkusClient := mock_compute.NewMockResourceSkusClient(controller)
resourceSkusClient.EXPECT().
List(gomock.Any(), fmt.Sprintf("location eq %v", "eastus")).

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

@ -52,9 +52,11 @@ func validateVMSku(ctx context.Context, oc *api.OpenShiftCluster, resourceSkusCl
return err
}
workerProfiles, _ := api.GetEnrichedWorkerProfiles(oc.Properties)
// In case there are multiple WorkerProfiles listed in the cluster document (such as post-install),
// compare VMSize in each WorkerProfile to the resourceSkusClient call above to ensure that the sku is available in region.
for i, workerprofile := range oc.Properties.WorkerProfiles {
for i, workerprofile := range workerProfiles {
workerProfileSku := string(workerprofile.VMSize)
err = checkSKUAvailability(filteredSkus, location, fmt.Sprintf("properties.workerProfiles[%d].VMSize", i), workerProfileSku)

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

@ -154,7 +154,16 @@ func (g *generator) generateExamples(outputDir string, s *Swagger) error {
case "#/definitions/SecretList":
body = g.exampleSecretListResponse()
case "#/definitions/OpenShiftCluster":
body = g.exampleOpenShiftClusterResponse()
if g.workerProfilesStatus {
switch op {
case pi.Get:
body = g.exampleOpenShiftClusterGetResponse()
case pi.Put, pi.Patch:
body = g.exampleOpenShiftClusterPutOrPatchResponse()
}
} else {
body = g.exampleOpenShiftClusterResponse()
}
case "#/definitions/OpenShiftClusterCredentials":
body = g.exampleOpenShiftClusterCredentialsResponse()
case "#/definitions/OpenShiftClusterAdminKubeconfig":

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

@ -44,20 +44,23 @@ type generator struct {
exampleOpenShiftClusterPutParameter func() interface{}
exampleOpenShiftClusterPatchParameter func() interface{}
exampleOpenShiftClusterResponse func() interface{}
exampleOpenShiftClusterGetResponse func() interface{}
exampleOpenShiftClusterPutOrPatchResponse func() interface{}
exampleOpenShiftClusterCredentialsResponse func() interface{}
exampleOpenShiftClusterAdminKubeconfigResponse func() interface{}
exampleOpenShiftClusterListResponse func() interface{}
exampleOpenShiftVersionListResponse func() interface{}
exampleOperationListResponse func() interface{}
systemData bool
kubeConfig bool
installVersionList bool
clusterManager bool
xmsEnum []string
xmsSecretList []string
xmsIdentifiers []string
commonTypesVersion string
systemData bool
kubeConfig bool
installVersionList bool
clusterManager bool
workerProfilesStatus bool
xmsEnum []string
xmsSecretList []string
xmsIdentifiers []string
commonTypesVersion string
}
var apis = map[string]*generator{
@ -227,21 +230,23 @@ var apis = map[string]*generator{
exampleSecretListResponse: v20230904.ExampleSecretListResponse,
exampleOpenShiftClusterPutParameter: v20230904.ExampleOpenShiftClusterPutParameter,
exampleOpenShiftClusterPatchParameter: v20230904.ExampleOpenShiftClusterPatchParameter,
exampleOpenShiftClusterResponse: v20230904.ExampleOpenShiftClusterResponse,
exampleOpenShiftClusterGetResponse: v20230904.ExampleOpenShiftClusterGetResponse,
exampleOpenShiftClusterPutOrPatchResponse: v20230904.ExampleOpenShiftClusterPutOrPatchResponse,
exampleOpenShiftClusterCredentialsResponse: v20230904.ExampleOpenShiftClusterCredentialsResponse,
exampleOpenShiftClusterListResponse: v20230904.ExampleOpenShiftClusterListResponse,
exampleOpenShiftClusterAdminKubeconfigResponse: v20230904.ExampleOpenShiftClusterAdminKubeconfigResponse,
exampleOpenShiftVersionListResponse: v20230904.ExampleOpenShiftVersionListResponse,
exampleOperationListResponse: api.ExampleOperationListResponse,
xmsEnum: []string{"EncryptionAtHost", "FipsValidatedModules", "SoftwareDefinedNetwork", "Visibility", "OutboundType", "PreconfiguredNSG"},
xmsSecretList: []string{"kubeconfig", "kubeadminPassword", "secretResources"},
xmsIdentifiers: []string{},
commonTypesVersion: "v3",
systemData: true,
clusterManager: true,
installVersionList: true,
kubeConfig: true,
xmsEnum: []string{"EncryptionAtHost", "FipsValidatedModules", "SoftwareDefinedNetwork", "Visibility", "OutboundType"},
xmsSecretList: []string{"kubeconfig", "kubeadminPassword", "secretResources"},
xmsIdentifiers: []string{},
commonTypesVersion: "v3",
systemData: true,
clusterManager: true,
installVersionList: true,
kubeConfig: true,
workerProfilesStatus: true,
},
}

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

@ -141,6 +141,9 @@ func (tw *typeWalker) schemaFromType(t types.Type, deps map[*types.Named]struct{
properties := tw.schemaFromType(field.Type(), deps)
properties.Description = strings.Trim(node.Doc.Text(), "\n")
if field.Name() == "WorkerProfilesStatus" {
properties.ReadOnly = true
}
if field.Name() == "EffectiveOutboundIPs" {
properties.ReadOnly = true

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

@ -102,10 +102,10 @@ func (ce machineClientEnricher) Enrich(
oc.Lock.Lock()
defer oc.Lock.Unlock()
oc.Properties.WorkerProfiles = workerProfiles
oc.Properties.WorkerProfilesStatus = workerProfiles
return nil
}
func (ce machineClientEnricher) SetDefaults(oc *api.OpenShiftCluster) {
oc.Properties.WorkerProfiles = nil
oc.Properties.WorkerProfilesStatus = nil
}

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

@ -192,7 +192,7 @@ func getWantOc(clusID string, workerprofile []api.WorkerProfile) *api.OpenShiftC
return &api.OpenShiftCluster{
ID: clusID,
Properties: api.OpenShiftClusterProperties{
WorkerProfiles: workerprofile,
WorkerProfilesStatus: workerprofile,
},
}
}

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

@ -31,7 +31,9 @@ func (dv *dynamic) ValidateDiskEncryptionSets(ctx context.Context, oc *api.OpenS
ids = append(ids, oc.Properties.MasterProfile.DiskEncryptionSetID)
paths = append(paths, "properties.masterProfile.diskEncryptionSetId")
}
for i, wp := range oc.Properties.WorkerProfiles {
workerProfiles, propertyName := api.GetEnrichedWorkerProfiles(oc.Properties)
for i, wp := range workerProfiles {
if wp.DiskEncryptionSetID != "" {
lowercasedId := strings.ToLower(wp.DiskEncryptionSetID)
if _, ok := uniqueIds[lowercasedId]; ok {
@ -40,7 +42,7 @@ func (dv *dynamic) ValidateDiskEncryptionSets(ctx context.Context, oc *api.OpenS
uniqueIds[lowercasedId] = struct{}{}
ids = append(ids, wp.DiskEncryptionSetID)
paths = append(paths, fmt.Sprintf("properties.workerProfiles[%d].diskEncryptionSetId", i))
paths = append(paths, fmt.Sprintf("properties.%s[%d].diskEncryptionSetId", propertyName, i))
}
}

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

@ -78,6 +78,31 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
},
},
{
name: "valid disk encryption set by enriched worker profile",
oc: &api.OpenShiftCluster{
Location: "eastus",
Properties: api.OpenShiftClusterProperties{
MasterProfile: api.MasterProfile{
DiskEncryptionSetID: fakeDesID1,
},
WorkerProfilesStatus: []api.WorkerProfile{{
DiskEncryptionSetID: fakeDesID1,
}},
},
},
mocks: func(permissions *mock_authorization.MockPermissionsClient, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, cancel context.CancelFunc) {
permissions.EXPECT().
ListForResource(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.Provider, "", fakeDesR1.ResourceType, fakeDesR1.ResourceName).
Return([]mgmtauthorization.Permission{{
Actions: &[]string{"Microsoft.Compute/diskEncryptionSets/read"},
NotActions: &[]string{},
}}, nil)
diskEncryptionSets.EXPECT().
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
Return(mgmtcompute.DiskEncryptionSet{Location: to.StringPtr("eastus")}, nil)
},
},
{
name: "valid permissions multiple disk encryption sets",
oc: &api.OpenShiftCluster{

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

@ -22,9 +22,10 @@ func (dv *dynamic) ValidateEncryptionAtHost(ctx context.Context, oc *api.OpenShi
}
}
for i, wp := range oc.Properties.WorkerProfiles {
workerProfiles, propertyName := api.GetEnrichedWorkerProfiles(oc.Properties)
for i, wp := range workerProfiles {
if wp.EncryptionAtHost == api.EncryptionAtHostEnabled {
err := dv.validateEncryptionAtHostSupport(wp.VMSize, fmt.Sprintf("properties.workerProfiles[%d].encryptionAtHost", i))
err := dv.validateEncryptionAtHostSupport(wp.VMSize, fmt.Sprintf("properties.%s[%d].encryptionAtHost", propertyName, i))
if err != nil {
return err
}

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

@ -58,6 +58,35 @@ func TestValidateEncryptionAtHost(t *testing.T) {
}, nil)
},
},
{
name: "encryption at host enabled with valid VM SKU and enriched worker profile available",
oc: &api.OpenShiftCluster{
Properties: api.OpenShiftClusterProperties{
MasterProfile: api.MasterProfile{
EncryptionAtHost: api.EncryptionAtHostEnabled,
VMSize: api.VMSizeStandardD8sV3,
},
WorkerProfilesStatus: []api.WorkerProfile{{
EncryptionAtHost: api.EncryptionAtHostEnabled,
VMSize: api.VMSizeStandardD4asV4,
}},
},
},
mocks: func(env *mock_env.MockInterface) {
env.EXPECT().VMSku(string(api.VMSizeStandardD8sV3)).
Return(&mgmtcompute.ResourceSku{
Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{
{Name: to.StringPtr("EncryptionAtHostSupported"), Value: to.StringPtr("True")},
}),
}, nil)
env.EXPECT().VMSku(string(api.VMSizeStandardD4asV4)).
Return(&mgmtcompute.ResourceSku{
Capabilities: &([]mgmtcompute.ResourceSkuCapabilities{
{Name: to.StringPtr("EncryptionAtHostSupported"), Value: to.StringPtr("True")},
}),
}, nil)
},
},
{
name: "encryption at host enabled with unsupported master VM SKU",
oc: &api.OpenShiftCluster{

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

@ -122,10 +122,12 @@ func (dv *openShiftClusterDynamicValidator) Dynamic(ctx context.Context) error {
ID: dv.oc.Properties.MasterProfile.SubnetID,
Path: "properties.masterProfile.subnetId",
}}
for i, wp := range dv.oc.Properties.WorkerProfiles {
workerProfiles, propertyName := api.GetEnrichedWorkerProfiles(dv.oc.Properties)
for i, wp := range workerProfiles {
subnets = append(subnets, dynamic.Subnet{
ID: wp.SubnetID,
Path: fmt.Sprintf("properties.workerProfiles[%d].subnetId", i),
Path: fmt.Sprintf("properties.%s[%d].subnetId", propertyName, i),
})
}

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

@ -633,6 +633,9 @@ class OpenShiftCluster(TrackedResource):
:vartype master_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.MasterProfile
:ivar worker_profiles: The cluster worker profiles.
:vartype worker_profiles: list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar worker_profiles_status: The cluster worker profiles status.
:vartype worker_profiles_status:
list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar apiserver_profile: The cluster API server profile.
:vartype apiserver_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.APIServerProfile
:ivar ingress_profiles: The cluster ingress profiles.
@ -645,6 +648,7 @@ class OpenShiftCluster(TrackedResource):
'type': {'readonly': True},
'system_data': {'readonly': True},
'location': {'required': True},
'worker_profiles_status': {'readonly': True},
}
_attribute_map = {
@ -661,6 +665,7 @@ class OpenShiftCluster(TrackedResource):
'network_profile': {'key': 'properties.networkProfile', 'type': 'NetworkProfile'},
'master_profile': {'key': 'properties.masterProfile', 'type': 'MasterProfile'},
'worker_profiles': {'key': 'properties.workerProfiles', 'type': '[WorkerProfile]'},
'worker_profiles_status': {'key': 'properties.workerProfilesStatus', 'type': '[WorkerProfile]'},
'apiserver_profile': {'key': 'properties.apiserverProfile', 'type': 'APIServerProfile'},
'ingress_profiles': {'key': 'properties.ingressProfiles', 'type': '[IngressProfile]'},
}
@ -705,6 +710,7 @@ class OpenShiftCluster(TrackedResource):
self.network_profile = kwargs.get('network_profile', None)
self.master_profile = kwargs.get('master_profile', None)
self.worker_profiles = kwargs.get('worker_profiles', None)
self.worker_profiles_status = None
self.apiserver_profile = kwargs.get('apiserver_profile', None)
self.ingress_profiles = kwargs.get('ingress_profiles', None)
@ -816,6 +822,9 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
:vartype master_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.MasterProfile
:ivar worker_profiles: The cluster worker profiles.
:vartype worker_profiles: list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar worker_profiles_status: The cluster worker profiles status.
:vartype worker_profiles_status:
list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar apiserver_profile: The cluster API server profile.
:vartype apiserver_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.APIServerProfile
:ivar ingress_profiles: The cluster ingress profiles.
@ -824,6 +833,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
_validation = {
'system_data': {'readonly': True},
'worker_profiles_status': {'readonly': True},
}
_attribute_map = {
@ -836,6 +846,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
'network_profile': {'key': 'properties.networkProfile', 'type': 'NetworkProfile'},
'master_profile': {'key': 'properties.masterProfile', 'type': 'MasterProfile'},
'worker_profiles': {'key': 'properties.workerProfiles', 'type': '[WorkerProfile]'},
'worker_profiles_status': {'key': 'properties.workerProfilesStatus', 'type': '[WorkerProfile]'},
'apiserver_profile': {'key': 'properties.apiserverProfile', 'type': 'APIServerProfile'},
'ingress_profiles': {'key': 'properties.ingressProfiles', 'type': '[IngressProfile]'},
}
@ -880,6 +891,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
self.network_profile = kwargs.get('network_profile', None)
self.master_profile = kwargs.get('master_profile', None)
self.worker_profiles = kwargs.get('worker_profiles', None)
self.worker_profiles_status = None
self.apiserver_profile = kwargs.get('apiserver_profile', None)
self.ingress_profiles = kwargs.get('ingress_profiles', None)

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

@ -684,6 +684,9 @@ class OpenShiftCluster(TrackedResource):
:vartype master_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.MasterProfile
:ivar worker_profiles: The cluster worker profiles.
:vartype worker_profiles: list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar worker_profiles_status: The cluster worker profiles status.
:vartype worker_profiles_status:
list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar apiserver_profile: The cluster API server profile.
:vartype apiserver_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.APIServerProfile
:ivar ingress_profiles: The cluster ingress profiles.
@ -696,6 +699,7 @@ class OpenShiftCluster(TrackedResource):
'type': {'readonly': True},
'system_data': {'readonly': True},
'location': {'required': True},
'worker_profiles_status': {'readonly': True},
}
_attribute_map = {
@ -712,6 +716,7 @@ class OpenShiftCluster(TrackedResource):
'network_profile': {'key': 'properties.networkProfile', 'type': 'NetworkProfile'},
'master_profile': {'key': 'properties.masterProfile', 'type': 'MasterProfile'},
'worker_profiles': {'key': 'properties.workerProfiles', 'type': '[WorkerProfile]'},
'worker_profiles_status': {'key': 'properties.workerProfilesStatus', 'type': '[WorkerProfile]'},
'apiserver_profile': {'key': 'properties.apiserverProfile', 'type': 'APIServerProfile'},
'ingress_profiles': {'key': 'properties.ingressProfiles', 'type': '[IngressProfile]'},
}
@ -768,6 +773,7 @@ class OpenShiftCluster(TrackedResource):
self.network_profile = network_profile
self.master_profile = master_profile
self.worker_profiles = worker_profiles
self.worker_profiles_status = None
self.apiserver_profile = apiserver_profile
self.ingress_profiles = ingress_profiles
@ -887,6 +893,9 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
:vartype master_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.MasterProfile
:ivar worker_profiles: The cluster worker profiles.
:vartype worker_profiles: list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar worker_profiles_status: The cluster worker profiles status.
:vartype worker_profiles_status:
list[~azure.mgmt.redhatopenshift.v2023_09_04.models.WorkerProfile]
:ivar apiserver_profile: The cluster API server profile.
:vartype apiserver_profile: ~azure.mgmt.redhatopenshift.v2023_09_04.models.APIServerProfile
:ivar ingress_profiles: The cluster ingress profiles.
@ -895,6 +904,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
_validation = {
'system_data': {'readonly': True},
'worker_profiles_status': {'readonly': True},
}
_attribute_map = {
@ -907,6 +917,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
'network_profile': {'key': 'properties.networkProfile', 'type': 'NetworkProfile'},
'master_profile': {'key': 'properties.masterProfile', 'type': 'MasterProfile'},
'worker_profiles': {'key': 'properties.workerProfiles', 'type': '[WorkerProfile]'},
'worker_profiles_status': {'key': 'properties.workerProfilesStatus', 'type': '[WorkerProfile]'},
'apiserver_profile': {'key': 'properties.apiserverProfile', 'type': 'APIServerProfile'},
'ingress_profiles': {'key': 'properties.ingressProfiles', 'type': '[IngressProfile]'},
}
@ -962,6 +973,7 @@ class OpenShiftClusterUpdate(msrest.serialization.Model):
self.network_profile = network_profile
self.master_profile = master_profile
self.worker_profiles = worker_profiles
self.worker_profiles_status = None
self.apiserver_profile = apiserver_profile
self.ingress_profiles = ingress_profiles

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

@ -54,6 +54,29 @@
"count": 3
}
],
"workerProfilesStatus": [
{
"name": "worker1",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker2",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker3",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
}
],
"apiserverProfile": {
"visibility": "Public",
"url": "https://api.cluster.location.aroapp.io:6443/",

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

@ -54,6 +54,29 @@
"count": 3
}
],
"workerProfilesStatus": [
{
"name": "worker1",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker2",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker3",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
}
],
"apiserverProfile": {
"visibility": "Public",
"url": "https://api.cluster.location.aroapp.io:6443/",

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

@ -55,6 +55,29 @@
"count": 3
}
],
"workerProfilesStatus": [
{
"name": "worker1",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker2",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
},
{
"name": "worker3",
"vmSize": "Standard_D2s_v3",
"diskSizeGB": 128,
"subnetId": "/subscriptions/subscriptionId/resourceGroups/vnetResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/worker",
"count": 1
}
],
"apiserverProfile": {
"visibility": "Public",
"url": "https://api.cluster.location.aroapp.io:6443/",

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

@ -2097,6 +2097,15 @@
},
"x-ms-identifiers": []
},
"workerProfilesStatus": {
"description": "The cluster worker profiles status.",
"type": "array",
"items": {
"$ref": "#/definitions/WorkerProfile"
},
"readOnly": true,
"x-ms-identifiers": []
},
"apiserverProfile": {
"$ref": "#/definitions/APIServerProfile",
"description": "The cluster API server profile."
@ -2234,11 +2243,7 @@
"Disabled",
"Enabled"
],
"type": "string",
"x-ms-enum": {
"name": "PreconfiguredNSG",
"modelAsString": true
}
"type": "string"
},
"ProvisioningState": {
"description": "ProvisioningState represents a provisioning state.",