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

azurerm_logic_app_workflow - add supports for workflow_parameters #12314

Merged
merged 5 commits into from
Jul 30, 2021
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
237 changes: 218 additions & 19 deletions azurerm/internal/services/logic/logic_app_workflow_resource.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package logic

import (
"encoding/json"
"fmt"
"log"
"regexp"
"strconv"
"time"

"github.com/Azure/azure-sdk-for-go/services/logic/mgmt/2019-05-01/logic"
Expand Down Expand Up @@ -91,6 +93,14 @@ func resourceLogicAppWorkflow() *pluginsdk.Resource {
Default: "1.0.0.0",
},

"workflow_parameters": {
Type: pluginsdk.TypeMap,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"access_endpoint": {
Type: pluginsdk.TypeString,
Computed: true,
Expand Down Expand Up @@ -146,10 +156,18 @@ func resourceLogicAppWorkflowCreate(d *pluginsdk.ResourceData, meta interface{})
}

location := azure.NormalizeLocation(d.Get("location").(string))
parameters := expandLogicAppWorkflowParameters(d.Get("parameters").(map[string]interface{}))

workflowSchema := d.Get("workflow_schema").(string)
workflowVersion := d.Get("workflow_version").(string)
workflowParameters, err := expandLogicAppWorkflowWorkflowParameters(d.Get("workflow_parameters").(map[string]interface{}))
if err != nil {
return fmt.Errorf("expanding `workflow_parameters`: %+v", err)
}

parameters, err := expandLogicAppWorkflowParameters(d.Get("parameters").(map[string]interface{}), workflowParameters)
if err != nil {
return err
}
t := d.Get("tags").(map[string]interface{})

properties := logic.Workflow{
Expand All @@ -160,6 +178,7 @@ func resourceLogicAppWorkflowCreate(d *pluginsdk.ResourceData, meta interface{})
"contentVersion": workflowVersion,
"actions": make(map[string]interface{}),
"triggers": make(map[string]interface{}),
"parameters": workflowParameters,
},
Parameters: parameters,
},
Expand Down Expand Up @@ -227,13 +246,24 @@ func resourceLogicAppWorkflowUpdate(d *pluginsdk.ResourceData, meta interface{})
}

location := azure.NormalizeLocation(d.Get("location").(string))
parameters := expandLogicAppWorkflowParameters(d.Get("parameters").(map[string]interface{}))
workflowParameters, err := expandLogicAppWorkflowWorkflowParameters(d.Get("workflow_parameters").(map[string]interface{}))
if err != nil {
return fmt.Errorf("expanding `workflow_parameters`: %+v", err)
}
parameters, err := expandLogicAppWorkflowParameters(d.Get("parameters").(map[string]interface{}), workflowParameters)
if err != nil {
return err
}

t := d.Get("tags").(map[string]interface{})

definition := read.WorkflowProperties.Definition.(map[string]interface{})
definition["parameters"] = workflowParameters

properties := logic.Workflow{
Location: utils.String(location),
WorkflowProperties: &logic.WorkflowProperties{
Definition: read.WorkflowProperties.Definition,
Definition: definition,
Parameters: parameters,
},
Tags: tags.Expand(t),
Expand Down Expand Up @@ -282,11 +312,6 @@ func resourceLogicAppWorkflowRead(d *pluginsdk.ResourceData, meta interface{}) e
}

if props := resp.WorkflowProperties; props != nil {
parameters := flattenLogicAppWorkflowParameters(props.Parameters)
if err := d.Set("parameters", parameters); err != nil {
return fmt.Errorf("Error setting `parameters`: %+v", err)
}

d.Set("access_endpoint", props.AccessEndpoint)

if props.EndpointsConfiguration == nil || props.EndpointsConfiguration.Connector == nil {
Expand All @@ -312,6 +337,25 @@ func resourceLogicAppWorkflowRead(d *pluginsdk.ResourceData, meta interface{}) e
if v["contentVersion"] != nil {
d.Set("workflow_version", v["contentVersion"].(string))
}
if p, ok := v["parameters"]; ok {
workflowParameters, err := flattenLogicAppWorkflowWorkflowParameters(p.(map[string]interface{}))
if err != nil {
return fmt.Errorf("flattening `workflow_parameters`: %+v", err)
}
if err := d.Set("workflow_parameters", workflowParameters); err != nil {
return fmt.Errorf("setting `workflow_parameters`: %+v", err)
}

// The props.Parameters (the value of the param) is accompany with the "parameters" (the definition of the param) inside the props.Definition.
// We will need to make use of the definition of the parameters in order to properly flatten the value of the parameters being set (for kinds of types).
parameters, err := flattenLogicAppWorkflowParameters(d, props.Parameters, p.(map[string]interface{}))
if err != nil {
return fmt.Errorf("flattening `parameters`: %v", err)
}
if err := d.Set("parameters", parameters); err != nil {
return fmt.Errorf("Error setting `parameters`: %+v", err)
}
}
}
}

Expand Down Expand Up @@ -363,35 +407,190 @@ func resourceLogicAppWorkflowDelete(d *pluginsdk.ResourceData, meta interface{})
return nil
}

func expandLogicAppWorkflowParameters(input map[string]interface{}) map[string]*logic.WorkflowParameter {
func expandLogicAppWorkflowParameters(input map[string]interface{}, paramDefs map[string]interface{}) (map[string]*logic.WorkflowParameter, error) {
output := make(map[string]*logic.WorkflowParameter)

for k, v := range input {
defRaw, ok := paramDefs[k]
if !ok {
return nil, fmt.Errorf("no parameter definition for %s", k)
}
def := defRaw.(map[string]interface{})
t := logic.ParameterType(def["type"].(string))

v := v.(string)

var value interface{}
switch t {
case logic.ParameterTypeBool:
var uv bool
if err := json.Unmarshal([]byte(v), &uv); err != nil {
return nil, fmt.Errorf("unmarshalling %s to bool: %v", k, err)
}
value = uv
case logic.ParameterTypeFloat:
var uv float64
if err := json.Unmarshal([]byte(v), &uv); err != nil {
return nil, fmt.Errorf("unmarshalling %s to float64: %v", k, err)
}
value = uv
case logic.ParameterTypeInt:
var uv int
if err := json.Unmarshal([]byte(v), &uv); err != nil {
return nil, fmt.Errorf("unmarshalling %s to int: %v", k, err)
}
value = uv
case logic.ParameterTypeArray:
var uv []interface{}
if err := json.Unmarshal([]byte(v), &uv); err != nil {
return nil, fmt.Errorf("unmarshalling %s to []interface{}: %v", k, err)
}
value = uv
case logic.ParameterTypeObject,
logic.ParameterTypeSecureObject:
var uv map[string]interface{}
if err := json.Unmarshal([]byte(v), &uv); err != nil {
return nil, fmt.Errorf("unmarshalling %s to map[string]interface{}: %v", k, err)
}
value = uv
case logic.ParameterTypeString,
logic.ParameterTypeSecureString:
value = v
}

output[k] = &logic.WorkflowParameter{
Type: logic.ParameterTypeString,
Value: v.(string),
Type: t,
Value: value,
}
}

return output
return output, nil
}

func flattenLogicAppWorkflowParameters(input map[string]*logic.WorkflowParameter) map[string]interface{} {
func flattenLogicAppWorkflowParameters(d *pluginsdk.ResourceData, input map[string]*logic.WorkflowParameter, paramDefs map[string]interface{}) (map[string]interface{}, error) {
output := make(map[string]interface{})

// Read the "parameters" from state, which is used to fill in the "sensitive" properties.
paramInState := make(map[string]interface{})
paramsRaw := d.Get("parameters")
if params, ok := paramsRaw.(map[string]interface{}); ok {
paramInState = params
}

for k, v := range input {
if v != nil {
// we only support string parameters at this time
val, ok := v.Value.(string)
defRaw, ok := paramDefs[k]
if !ok {
// This should never happen.
log.Printf("[WARN] The parameter %s is not defined in the Logic App Workflow", k)
continue
}

if v == nil {
log.Printf("[WARN] The value of parameter %s is nil", k)
continue
}

def := defRaw.(map[string]interface{})
t := logic.ParameterType(def["type"].(string))

var value string
switch t {
case logic.ParameterTypeBool:
tv, ok := v.Value.(bool)
if !ok {
return nil, fmt.Errorf("the value of parameter %s is expected to be bool, but got %T", k, v.Value)
}
value = "true"
if !tv {
value = "false"
}
case logic.ParameterTypeFloat:
// Note that the json unmarshalled response doesn't differ between float and int, as json has only type number.
tv, ok := v.Value.(float64)
if !ok {
return nil, fmt.Errorf("the value of parameter %s is expected to be float64, but got %T", k, v.Value)
}
value = strconv.FormatFloat(tv, 'f', -1, 64)
case logic.ParameterTypeInt:
// Note that the json unmarshalled response doesn't differ between float and int, as json has only type number.
tv, ok := v.Value.(float64)
if !ok {
return nil, fmt.Errorf("the value of parameter %s is expected to be float64, but got %T", k, v.Value)
}
value = strconv.Itoa(int(tv))

case logic.ParameterTypeArray:
tv, ok := v.Value.([]interface{})
if !ok {
log.Printf("[DEBUG] Skipping parameter %q since it's not a string", k)
return nil, fmt.Errorf("the value of parameter %s is expected to be []interface{}, but got %T", k, v.Value)
}
obj, err := json.Marshal(tv)
if err != nil {
return nil, fmt.Errorf("converting %+v from json: %v", tv, err)
}
value = string(obj)

case logic.ParameterTypeObject:
tv, ok := v.Value.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("the value of parameter %s is expected to be map[string]interface{}, but got %T", k, v.Value)
}
obj, err := json.Marshal(tv)
if err != nil {
return nil, fmt.Errorf("converting %+v from json: %v", tv, err)
}
value = string(obj)

case logic.ParameterTypeString:
tv, ok := v.Value.(string)
if !ok {
return nil, fmt.Errorf("the value of parameter %s is expected to be string, but got %T", k, v.Value)
}
value = tv

case logic.ParameterTypeSecureString,
logic.ParameterTypeSecureObject:
// This is not returned from API, we will try to read them from the state instead.
if v, ok := paramInState[k]; ok {
value = v.(string) // The value in state here is guaranteed to be a string, so directly cast the type.
}
}

output[k] = value
}

return output, nil
}

func expandLogicAppWorkflowWorkflowParameters(input map[string]interface{}) (map[string]interface{}, error) {
if len(input) == 0 {
return nil, nil
}

output[k] = val
output := make(map[string]interface{})
for k, v := range input {
obj, err := pluginsdk.ExpandJsonFromString(v.(string))
if err != nil {
return nil, err
}
output[k] = obj
}
return output, nil
}

return output
func flattenLogicAppWorkflowWorkflowParameters(input map[string]interface{}) (map[string]interface{}, error) {
if input == nil {
return nil, nil
}
output := make(map[string]interface{})
for k, v := range input {
objstr, err := pluginsdk.FlattenJsonToString(v.(map[string]interface{}))
if err != nil {
return nil, err
}
output[k] = objstr
}
return output, nil
}

func flattenIPAddresses(input *[]logic.IPAddress) []interface{} {
Expand Down
Loading