func ParseAndValidateConfig()

in component/azstorage/config.go [303:543]


func ParseAndValidateConfig(az *AzStorage, opt AzStorageOptions) error {
	log.Trace("ParseAndValidateConfig : Parsing config")

	// Validate account name is present or not
	if opt.AccountName == "" {
		return errors.New("account name not provided")
	}
	az.stConfig.authConfig.AccountName = opt.AccountName

	// Validate account type property
	if opt.AccountType == "" {
		opt.AccountType = "block"
	}

	if config.IsSet(compName + ".use-adls") {
		if opt.UseAdls {
			az.stConfig.authConfig.AccountType = az.stConfig.authConfig.AccountType.ADLS()
		} else {
			az.stConfig.authConfig.AccountType = az.stConfig.authConfig.AccountType.BLOCK()
		}
	} else {
		var accountType AccountType
		err := accountType.Parse(opt.AccountType)
		if err != nil {
			log.Err("ParseAndValidateConfig : Failed to parse account type %s", opt.AccountType)
			return errors.New("invalid account type")
		}

		if accountType == EAccountType.INVALID_ACC() {
			log.Err("ParseAndValidateConfig : Invalid account type %s", opt.AccountType)
			return errors.New("invalid account type")
		}

		az.stConfig.authConfig.AccountType = accountType
	}

	if opt.BlockSize != 0 {
		if opt.BlockSize > blockblob.MaxStageBlockBytes {
			log.Err("ParseAndValidateConfig : Block size is too large. Block size has to be smaller than %s Bytes", blockblob.MaxStageBlockBytes)
			return errors.New("block size is too large")
		}
		az.stConfig.blockSize = opt.BlockSize * 1024 * 1024
	}

	// Validate container name is present or not
	err := config.UnmarshalKey("mount-all-containers", &az.stConfig.mountAllContainers)
	if err != nil {
		log.Err("ParseAndValidateConfig : Failed to detect mount-all-container")
	}

	if !az.stConfig.mountAllContainers && opt.Container == "" {
		return errors.New("container name not provided")
	}

	az.stConfig.container = opt.Container

	if config.IsSet(compName + ".use-https") {
		opt.UseHTTP = !opt.UseHTTPS
	}

	if opt.CPKEnabled {
		if opt.CPKEncryptionKey == "" || opt.CPKEncryptionKeySha256 == "" {
			log.Err("ParseAndValidateConfig : CPK key or CPK key sha256 not provided")
			return errors.New("CPK key or key sha256 not provided")
		}
		az.stConfig.cpkEnabled = opt.CPKEnabled
		az.stConfig.cpkEncryptionKey = opt.CPKEncryptionKey
		az.stConfig.cpkEncryptionKeySha256 = opt.CPKEncryptionKeySha256
	}

	// Validate endpoint
	if opt.Endpoint == "" {
		log.Warn("ParseAndValidateConfig : account endpoint not provided, assuming the default .core.windows.net style endpoint")
		if az.stConfig.authConfig.AccountType == EAccountType.BLOCK() {
			opt.Endpoint = fmt.Sprintf("%s.blob.core.windows.net", opt.AccountName)
		} else if az.stConfig.authConfig.AccountType == EAccountType.ADLS() {
			opt.Endpoint = fmt.Sprintf("%s.dfs.core.windows.net", opt.AccountName)
		}
	}
	az.stConfig.authConfig.Endpoint = opt.Endpoint
	az.stConfig.authConfig.Endpoint = formatEndpointProtocol(az.stConfig.authConfig.Endpoint, opt.UseHTTP)
	az.stConfig.authConfig.Endpoint = formatEndpointAccountType(az.stConfig.authConfig.Endpoint, az.stConfig.authConfig.AccountType)

	az.stConfig.authConfig.ActiveDirectoryEndpoint = opt.ActiveDirectoryEndpoint
	az.stConfig.authConfig.ActiveDirectoryEndpoint = formatEndpointProtocol(az.stConfig.authConfig.ActiveDirectoryEndpoint, false)

	// If subdirectory is mounted, take the prefix path
	az.stConfig.prefixPath = removeLeadingSlashes(opt.PrefixPath)

	// Block list call on mount for given amount of time
	az.stConfig.cancelListForSeconds = opt.CancelListForSeconds

	az.stConfig.telemetry = opt.Telemetry

	httpProxyProvided := opt.HttpProxyAddress != ""
	httpsProxyProvided := opt.HttpsProxyAddress != ""

	// Set whether to use http or https and proxy
	if opt.UseHTTP {
		az.stConfig.authConfig.UseHTTP = true
		if httpProxyProvided {
			az.stConfig.proxyAddress = opt.HttpProxyAddress
		} else if httpsProxyProvided {
			az.stConfig.proxyAddress = opt.HttpsProxyAddress
		}
	} else {
		if httpsProxyProvided {
			az.stConfig.proxyAddress = opt.HttpsProxyAddress
		} else {
			if httpProxyProvided {
				log.Err("ParseAndValidateConfig : `http-proxy` Invalid : must set `use-http: true` in your config file")
				return errors.New("`http-proxy` Invalid : must set `use-http: true` in your config file")
			}
		}
	}
	az.stConfig.proxyAddress = formatEndpointProtocol(az.stConfig.proxyAddress, opt.UseHTTP)
	log.Info("ParseAndValidateConfig : using the following proxy address from the config file: %s", az.stConfig.proxyAddress)

	err = ParseAndReadDynamicConfig(az, opt, false)
	if err != nil {
		return err
	}

	log.Debug("ParseAndValidateConfig : Getting auth type")
	if opt.AuthMode == "" {
		// Based on other config decide the auth mode
		// for e.g. if sas token is set then mode shall be set to sas and if key is set then authmode shall be key
		opt.AuthMode = autoDetectAuthMode(opt)
		log.Debug("ParseAndValidateConfig : Auth type %s", opt.AuthMode)
	}

	var authType AuthType
	err = authType.Parse(opt.AuthMode)
	if err != nil {
		log.Err("ParseAndValidateConfig : Invalid auth type %s", opt.AccountType)
		return errors.New("invalid auth type")
	}

	az.stConfig.authConfig.ObjectID = opt.ObjectID

	switch authType {
	case EAuthType.KEY():
		az.stConfig.authConfig.AuthMode = EAuthType.KEY()
		if opt.AccountKey == "" {
			return errors.New("storage key not provided")
		}
		az.stConfig.authConfig.AccountKey = opt.AccountKey
	case EAuthType.SAS():
		az.stConfig.authConfig.AuthMode = EAuthType.SAS()
		if opt.SaSKey == "" {
			return errors.New("SAS key not provided")
		}
		az.stConfig.authConfig.SASKey = sanitizeSASKey(opt.SaSKey)
	case EAuthType.MSI():
		az.stConfig.authConfig.AuthMode = EAuthType.MSI()
		err := validateMsiConfig(opt)
		if err != nil {
			return err
		}
		az.stConfig.authConfig.ApplicationID = opt.ApplicationID
		az.stConfig.authConfig.ResourceID = opt.ResourceID
	case EAuthType.SPN():
		az.stConfig.authConfig.AuthMode = EAuthType.SPN()
		if opt.ClientID == "" || (opt.ClientSecret == "" && opt.OAuthTokenFilePath == "" && opt.WorkloadIdentityToken == "") || opt.TenantID == "" {
			//lint:ignore ST1005 ignore
			return errors.New("Client ID, Tenant ID or Client Secret, OAuthTokenFilePath, WorkloadIdentityToken not provided")
		}
		az.stConfig.authConfig.ClientID = opt.ClientID
		az.stConfig.authConfig.ClientSecret = opt.ClientSecret
		az.stConfig.authConfig.TenantID = opt.TenantID
		az.stConfig.authConfig.OAuthTokenFilePath = opt.OAuthTokenFilePath
		az.stConfig.authConfig.WorkloadIdentityToken = opt.WorkloadIdentityToken
	case EAuthType.AZCLI():
		az.stConfig.authConfig.AuthMode = EAuthType.AZCLI()
	case EAuthType.WORKLOADIDENTITY():
		az.stConfig.authConfig.AuthMode = EAuthType.WORKLOADIDENTITY()
		if opt.ClientID == "" || opt.TenantID == "" || opt.ApplicationID == "" {
			return errors.New("Client ID, Tenant ID or Application ID not provided")
		}

		az.stConfig.authConfig.ClientID = opt.ClientID
		az.stConfig.authConfig.TenantID = opt.TenantID
		az.stConfig.authConfig.ApplicationID = opt.ApplicationID
		az.stConfig.authConfig.UserAssertion = opt.UserAssertion

	default:
		log.Err("ParseAndValidateConfig : Invalid auth mode %s", opt.AuthMode)
		return errors.New("invalid auth mode")
	}
	az.stConfig.authConfig.AuthResource = opt.AuthResourceString

	// Retry policy configuration
	// A user provided value of 0 doesn't make sense for MaxRetries, MaxTimeout, BackoffTime, or MaxRetryDelay.

	az.stConfig.maxRetries = 5     // Max number of retry to be done  (default 4) (v1 : 0)
	az.stConfig.maxTimeout = 900   // Max timeout for any single retry (default 1 min) (v1 : 60)
	az.stConfig.backoffTime = 4    // Delay before any retry (exponential increase) (default 4 sec)
	az.stConfig.maxRetryDelay = 60 // Maximum allowed delay before retry (default 120 sec) (v1 : 1.2)

	if opt.MaxRetries != 0 {
		az.stConfig.maxRetries = opt.MaxRetries
	}
	if opt.MaxTimeout != 0 {
		az.stConfig.maxTimeout = opt.MaxTimeout
	}
	if opt.BackoffTime != 0 {
		az.stConfig.backoffTime = opt.BackoffTime
	}
	if opt.MaxRetryDelay != 0 {
		az.stConfig.maxRetryDelay = opt.MaxRetryDelay
	}

	if config.IsSet(compName + ".set-content-type") {
		log.Warn("unsupported v1 CLI parameter: set-content-type is always true in blobfuse2.")
	}
	if config.IsSet(compName + ".ca-cert-file") {
		log.Warn("unsupported v1 CLI parameter: ca-cert-file is not supported in blobfuse2. Use the default ca cert path for your environment.")
	}
	if config.IsSet(compName + ".debug-libcurl") {
		log.Warn("unsupported v1 CLI parameter: debug-libcurl is not applicable in blobfuse2.")
	}

	az.stConfig.preserveACL = opt.PreserveACL
	if opt.Filter != "" {
		err = configureBlobFilter(az, opt)
		if err != nil {
			return err
		}
	}

	log.Crit("ParseAndValidateConfig : account %s, container %s, account-type %s, auth %s, prefix %s, endpoint %s, MD5 %v %v, virtual-directory %v, disable-compression %v, CPK %v",
		az.stConfig.authConfig.AccountName, az.stConfig.container, az.stConfig.authConfig.AccountType, az.stConfig.authConfig.AuthMode,
		az.stConfig.prefixPath, az.stConfig.authConfig.Endpoint, az.stConfig.validateMD5, az.stConfig.updateMD5, az.stConfig.virtualDirectory, az.stConfig.disableCompression, az.stConfig.cpkEnabled)
	log.Crit("ParseAndValidateConfig : use-HTTP %t, block-size %d, max-concurrency %d, default-tier %s, fail-unsupported-op %t, mount-all-containers %t", az.stConfig.authConfig.UseHTTP, az.stConfig.blockSize, az.stConfig.maxConcurrency, az.stConfig.defaultTier, az.stConfig.ignoreAccessModifiers, az.stConfig.mountAllContainers)
	log.Crit("ParseAndValidateConfig : Retry Config: retry-count %d, max-timeout %d, backoff-time %d, max-delay %d, preserve-acl: %v",
		az.stConfig.maxRetries, az.stConfig.maxTimeout, az.stConfig.backoffTime, az.stConfig.maxRetryDelay, az.stConfig.preserveACL)

	log.Crit("ParseAndValidateConfig : Telemetry : %s, honour-ACL %v", az.stConfig.telemetry, az.stConfig.honourACL)

	return nil
}