ARO-RP/pkg/deploy/config.go

151 строка
7.7 KiB
Go

package deploy
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"fmt"
"io/ioutil"
"reflect"
"strings"
"github.com/ghodss/yaml"
)
// NOTICE: when modifying the config definition here, don't forget to update
// DevConfig().
// Config represents configuration object for deployer tooling
type Config struct {
RPs []RPConfig `json:"rps,omitempty"`
Configuration *Configuration `json:"configuration,omitempty"`
}
// RPConfig represents individual RP configuration
type RPConfig struct {
Location string `json:"location,omitempty"`
SubscriptionID string `json:"subscriptionId,omitempty"`
RPResourceGroupName string `json:"rpResourceGroupName,omitempty"`
Configuration *Configuration `json:"configuration,omitempty"`
}
// Configuration represents configuration structure
type Configuration struct {
ACRLocationOverride *string `json:"acrLocationOverride,omitempty"`
ACRResourceID *string `json:"acrResourceId,omitempty" value:"required"`
AzureCloudName *string `json:"azureCloudName,omitempty" value:"required"`
RPVersionStorageAccountName *string `json:"rpVersionStorageAccountName,omitempty" value:"required"`
ACRReplicaDisabled *bool `json:"acrReplicaDisabled,omitempty"`
AdminAPICABundle *string `json:"adminApiCaBundle,omitempty" value:"required"`
AdminAPIClientCertCommonName *string `json:"adminApiClientCertCommonName,omitempty" value:"required"`
ARMAPICABundle *string `json:"armApiCaBundle,omitempty"`
ARMAPIClientCertCommonName *string `json:"armApiClientCertCommonName,omitempty"`
ARMClientID *string `json:"armClientId,omitempty"`
BillingE2EStorageAccountID *string `json:"billingE2EStorageAccountId,omitempty"`
BillingServicePrincipalID *string `json:"billingServicePrincipalId,omitempty"`
ClusterMDMAccount *string `json:"clusterMdmAccount,omitempty" value:"required"`
ClusterMDSDAccount *string `json:"clusterMdsdAccount,omitempty" value:"required"`
ClusterMDSDConfigVersion *string `json:"clusterMdsdConfigVersion,omitempty" value:"required"`
ClusterMDSDNamespace *string `json:"clusterMdsdNamespace,omitempty" value:"required"`
ClusterParentDomainName *string `json:"clusterParentDomainName,omitempty" value:"required"`
DatabaseAccountName *string `json:"databaseAccountName,omitempty" value:"required"`
DisableCosmosDBFirewall *bool `json:"disableCosmosDBFirewall,omitempty"`
ExtraClusterKeyvaultAccessPolicies []interface{} `json:"extraClusterKeyvaultAccessPolicies,omitempty" value:"required"`
ExtraDBTokenKeyvaultAccessPolicies []interface{} `json:"extraDBTokenKeyvaultAccessPolicies,omitempty" value:"required"`
ExtraCosmosDBIPs []string `json:"extraCosmosDBIPs,omitempty"`
ExtraPortalKeyvaultAccessPolicies []interface{} `json:"extraPortalKeyvaultAccessPolicies,omitempty" value:"required"`
ExtraServiceKeyvaultAccessPolicies []interface{} `json:"extraServiceKeyvaultAccessPolicies,omitempty" value:"required"`
FPClientID *string `json:"fpClientId,omitempty" value:"required"`
FPServerCertCommonName *string `json:"fpServerCertCommonName,omitempty"`
FPServicePrincipalID *string `json:"fpServicePrincipalId,omitempty" value:"required"`
GlobalResourceGroupName *string `json:"globalResourceGroupName,omitempty" value:"required"`
GlobalResourceGroupLocation *string `json:"globalResourceGroupLocation,omitempty" value:"required"`
GlobalSubscriptionID *string `json:"globalSubscriptionId,omitempty" value:"required"`
KeyvaultDNSSuffix *string `json:"keyvaultDNSSuffix,omitempty" value:"required"`
KeyvaultPrefix *string `json:"keyvaultPrefix,omitempty" value:"required"`
MDMFrontendURL *string `json:"mdmFrontendUrl,omitempty" value:"required"`
MDSDEnvironment *string `json:"mdsdEnvironment,omitempty" value:"required"`
PortalAccessGroupIDs []string `json:"portalAccessGroupIds,omitempty" value:"required"`
PortalClientID *string `json:"portalClientId,omitempty" value:"required"`
PortalElevatedGroupIDs []string `json:"portalElevatedGroupIds,omitempty" value:"required"`
RPFeatures []string `json:"rpFeatures,omitempty"`
RPImagePrefix *string `json:"rpImagePrefix,omitempty" value:"required"`
RPMDMAccount *string `json:"rpMdmAccount,omitempty" value:"required"`
RPMDSDAccount *string `json:"rpMdsdAccount,omitempty" value:"required"`
RPMDSDConfigVersion *string `json:"rpMdsdConfigVersion,omitempty" value:"required"`
RPMDSDNamespace *string `json:"rpMdsdNamespace,omitempty" value:"required"`
RPNSGSourceAddressPrefixes []string `json:"rpNsgSourceAddressPrefixes,omitempty" value:"required"`
RPParentDomainName *string `json:"rpParentDomainName,omitempty" value:"required"`
SubscriptionResourceGroupName *string `json:"subscriptionResourceGroupName,omitempty" value:"required"`
SubscriptionResourceGroupLocation *string `json:"subscriptionResourceGroupLocation,omitempty" value:"required"`
RPVMSSCapacity *int `json:"rpVmssCapacity,omitempty"`
SSHPublicKey *string `json:"sshPublicKey,omitempty" value:"required"`
StorageAccountDomain *string `json:"storageAccountDomain,omitempty" value:"required"`
VMSize *string `json:"vmSize,omitempty" value:"required"`
}
// GetConfig return RP configuration from the file
func GetConfig(path, location string) (*RPConfig, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var config *Config
err = yaml.Unmarshal(data, &config)
if err != nil {
return nil, err
}
for _, c := range config.RPs {
if c.Location == location {
configuration, err := mergeConfig(c.Configuration, config.Configuration)
if err != nil {
return nil, err
}
c.Configuration = configuration
return &c, nil
}
}
return nil, fmt.Errorf("location %s not found in %s", location, path)
}
// mergeConfig merges two Configuration structs, replacing each zero field in
// primary with the contents of the corresponding field in secondary
func mergeConfig(primary, secondary *Configuration) (*Configuration, error) {
sValues := reflect.ValueOf(secondary).Elem()
pValues := reflect.ValueOf(primary).Elem()
for i := 0; i < pValues.NumField(); i++ {
if pValues.Field(i).IsZero() {
pValues.Field(i).Set(sValues.Field(i))
}
}
return primary, nil
}
// CheckRequiredFields validates configuration whether it provides required fields.
// Config is invalid if required fields are not provided.
func (conf *RPConfig) validate() error {
configuration := conf.Configuration
v := reflect.ValueOf(*configuration)
missingFields := []string{}
for i := 0; i < v.NumField(); i++ {
required := v.Type().Field(i).Tag.Get("value") == "required"
if required && v.Field(i).IsZero() {
missingFields = append(missingFields, v.Type().Field(i).Name)
}
}
if len(missingFields) == 0 {
return nil
}
return fmt.Errorf("configuration has missing fields: %s", strings.Join(missingFields, ","))
}