Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Aspire] Add support for default.value for parameter.v0 #4371

Merged
merged 3 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions cli/azd/pkg/apphost/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ func init() {
},
"removeDot": scaffold.RemoveDotAndDash,
"envFormat": scaffold.EnvFormat,
"bicepParameterValue": func(value *string) string {
weikanglim marked this conversation as resolved.
Show resolved Hide resolved
if value == nil {
return ""
}
return fmt.Sprintf(" = '%s'", *value)
vhvb1989 marked this conversation as resolved.
Show resolved Hide resolved
},
},
).
ParseFS(resources.AppHostTemplates, "apphost/templates/*")
Expand Down Expand Up @@ -298,6 +304,7 @@ func BicepTemplate(name string, manifest *Manifest, options AppHostOptions) (*me
Name string
Secret bool
Type string
Value *string
}
type autoGenInput struct {
genInput
Expand All @@ -317,14 +324,22 @@ func BicepTemplate(name string, manifest *Manifest, options AppHostOptions) (*me
for _, key := range genParametersKeys {
parameter := generator.bicepContext.InputParameters[key]
parameterMetadata := ""
if parameter.Default != nil && parameter.Default.Generate != nil {
pMetadata, err := inputMetadata(*parameter.Default.Generate)
if err != nil {
return nil, fmt.Errorf("generating input metadata for %s: %w", key, err)
var parameterDefaultValue *string
vhvb1989 marked this conversation as resolved.
Show resolved Hide resolved
if parameter.Default != nil {
// main.bicep template handles *string for default.Value. If the value is nil, it will be ignored.
// if not nil, like empty string or any other string, it is used as `= '<value>'`
parameterDefaultValue = parameter.Default.Value
if parameter.Default.Generate != nil {
pMetadata, err := inputMetadata(*parameter.Default.Generate)
if err != nil {
return nil, fmt.Errorf("generating input metadata for %s: %w", key, err)
}
parameterMetadata = pMetadata
}
parameterMetadata = pMetadata
// Note: azd is not checking or validating that Default.Generate and Default.Value are not both set.
// The AppHost prevents this from happening by not allowing both to be set at the same time.
}
input := genInput{Name: key, Secret: parameter.Secret, Type: parameter.Type}
input := genInput{Name: key, Secret: parameter.Secret, Type: parameter.Type, Value: parameterDefaultValue}
parameters = append(parameters, autoGenInput{
genInput: input,
MetadataConfig: parameterMetadata,
Expand Down Expand Up @@ -1565,6 +1580,15 @@ func (b infraGenerator) evalBindingRef(v string, emitType inputEmitType) (string
case inputEmitTypeBicep:
return fmt.Sprintf("{{%s}}", replaceDash), nil
case inputEmitTypeYaml:
if param.Default != nil && param.Default.Value != nil {
if param.Secret {
return "", fmt.Errorf("default value for secured parameter %s is not supported", resource)
}
inputType = "parameterWithDefault"
// parameter with default value will either use the default value or the value passed in the environment
return fmt.Sprintf(`{{ %s "%s" "%s"}}`, inputType, replaceDash, *param.Default.Value), nil
}
// parameter without default value
return fmt.Sprintf(`{{ %s "%s" }}`, inputType, replaceDash), nil
default:
panic(fmt.Sprintf("unexpected parameter %s", string(emitType)))
Expand Down
1 change: 1 addition & 0 deletions cli/azd/pkg/apphost/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ type InputDefaultGenerate struct {

type InputDefault struct {
Generate *InputDefaultGenerate `json:"generate,omitempty"`
Value *string `json:"value,omitempty"`
}

// ManifestFromAppHost returns the Manifest from the given app host.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ param noVolume_pas_sw_ord string
})
@secure()
param noVolume_password string
param param_with_empty_value string = ''
param param_with_value string = 'default value for param'

var tags = {
'azd-env-name': environmentName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
"noVolume_password": {
"value": "${AZURE_NO_VOLUME_PASSWORD}"
},
"param_with_empty_value": {
"value": "${AZURE_PARAM_WITH_EMPTY_VALUE}"
},
"param_with_value": {
"value": "${AZURE_PARAM_WITH_VALUE}"
},
"environmentName": {
"value": "${AZURE_ENV_NAME}"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ properties:
env:
- name: AZURE_CLIENT_ID
value: {{ .Env.MANAGED_IDENTITY_CLIENT_ID }}
- name: EMPTY_VALUE
value: '{{ parameterWithDefault "param_with_empty_value" ""}}'
- name: WITH_VALUE
value: '{{ parameterWithDefault "param_with_value" "default value for param"}}'
- name: MYSQL_ROOT_PASSWORD
secretRef: mysql-root-password
- name: SpecialChar
Expand Down
30 changes: 29 additions & 1 deletion cli/azd/pkg/apphost/testdata/aspire-container.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,32 @@
}
}
},
"param-with-value": {
"type": "parameter.v0",
"value": "{param-with-value.inputs.value}",
"inputs": {
"value": {
"type": "string",
"secret": false,
"default":{
"value": "default value for param"
}
}
}
},
"param-with-empty-value": {
"type": "parameter.v0",
"value": "{param-with-empty-value.inputs.value}",
"inputs": {
"value": {
"type": "string",
"secret": false,
"default":{
"value": ""
}
}
}
},
"mysqlabstract-pas-sw-ord": {
"type": "parameter.v0",
"value": "{mysqlabstract-pas-sw-ord.inputs.value}",
Expand All @@ -38,7 +64,9 @@
"image": "mysql:latest",
"env": {
"MYSQL_ROOT_PASSWORD": "{mysqlabstract-password.value}",
"SpecialChar": "{mysqlabstract-pas-sw-ord.value}"
"SpecialChar": "{mysqlabstract-pas-sw-ord.value}",
"WITH_VALUE": "{param-with-value.value}",
"EMPTY_VALUE": "{param-with-empty-value.value}"
},
"volumes": [
{
Expand Down
27 changes: 25 additions & 2 deletions cli/azd/pkg/project/service_target_dotnet_containerapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"strings"
"text/template"

"github.com/azure/azure-dev/cli/azd/internal/scaffold"
"github.com/azure/azure-dev/cli/azd/pkg/alpha"
"github.com/azure/azure-dev/cli/azd/pkg/apphost"
"github.com/azure/azure-dev/cli/azd/pkg/async"
Expand Down Expand Up @@ -252,8 +253,9 @@ func (at *dotnetContainerAppTarget) Deploy(
}

funcMap := template.FuncMap{
"urlHost": fns.UrlHost,
"parameter": fns.Parameter,
"urlHost": fns.UrlHost,
"parameter": fns.Parameter,
"parameterWithDefault": fns.ParameterWithDefault,
// securedParameter gets a parameter the same way as parameter, but supporting the securedParameter
// allows to update the logic of pulling secret parameters in the future, if azd changes the way it
// stores the parameter value.
Expand Down Expand Up @@ -503,7 +505,16 @@ func (_ *containerAppTemplateManifestFuncs) UrlHost(s string) (string, error) {

const infraParametersKey = "infra.parameters."

// Parameter resolves the name of a parameter defined in the ACA yaml definition. The parameter can be mapped to a system
// environment variable or persisted in the azd environment configuration.
func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, error) {
envVarMapping := scaffold.EnvFormat(name)
weikanglim marked this conversation as resolved.
Show resolved Hide resolved
// map only to system environment variables. Not adding support for mapping to azd environment by design (b/c
// parameters could be secured)
if val, found := os.LookupEnv(envVarMapping); found {
return val, nil
}

key := infraParametersKey + name
val, found := fns.env.Config.Get(key)
if !found {
Expand All @@ -516,6 +527,18 @@ func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, er
return valString, nil
}

// ParameterWithDefault resolves the name of a parameter defined in the ACA yaml definition.
// The parameter can be mapped to a system environment variable or be default to a value directly.
func (fns *containerAppTemplateManifestFuncs) ParameterWithDefault(name string, defaultValue string) (string, error) {
envVarMapping := scaffold.EnvFormat(name)
// map only to system environment variables. Not adding support for mapping to azd environment by design (b/c
// parameters could be secured)
vhvb1989 marked this conversation as resolved.
Show resolved Hide resolved
if val, found := os.LookupEnv(envVarMapping); found {
return val, nil
}
return defaultValue, nil
}

// kvSecret gets the value of the secret with the given name from the KeyVault with the given host name. If the secret is
// not found, an error is returned.
func (fns *containerAppTemplateManifestFuncs) kvSecret(kvHost, secretName string) (string, error) {
Expand Down
2 changes: 1 addition & 1 deletion cli/azd/resources/apphost/templates/main.bicept
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ param principalId string = ''
{{- if $parameter.Secret }}
@secure()
{{- end}}
param {{bicepParameterName $parameter.Name}} {{$parameter.Type}}
param {{bicepParameterName $parameter.Name}} {{$parameter.Type}}{{bicepParameterValue $parameter.Value}}
{{- end}}

var tags = {
Expand Down
Loading