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

Add nat type to nat rule resource #1480

Merged
merged 1 commit into from
Dec 13, 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
83 changes: 62 additions & 21 deletions nsxt/resource_nsxt_policy_nat_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ var policyNATRulePolicyBasedVpnModeTypeValues = []string{
model.PolicyNatRule_POLICY_BASED_VPN_MODE_MATCH,
}

var policyNATRuleTypeValues = []string{
model.PolicyNat_NAT_TYPE_INTERNAL,
model.PolicyNat_NAT_TYPE_USER,
model.PolicyNat_NAT_TYPE_DEFAULT,
model.PolicyNat_NAT_TYPE_NAT64,
}

func resourceNsxtPolicyNATRule() *schema.Resource {
return &schema.Resource{
Create: resourceNsxtPolicyNATRuleCreate,
Expand Down Expand Up @@ -144,6 +151,14 @@ func resourceNsxtPolicyNATRule() *schema.Resource {
Computed: true,
ValidateFunc: validation.StringInSlice(policyNATRulePolicyBasedVpnModeTypeValues, false),
},
"type": {
Type: schema.TypeString,
Description: "NAT Type",
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(policyNATRuleTypeValues, false),
Computed: true,
},
},
}
}
Expand Down Expand Up @@ -180,7 +195,8 @@ func resourceNsxtPolicyNATRuleDelete(d *schema.ResourceData, m interface{}) erro
}

action := d.Get("action").(string)
natType := getNatTypeByAction(action)
natType := d.Get("type").(string)
natType = getNatTypeByAction(natType, action)
err := deleteNsxtPolicyNATRule(context, getPolicyConnector(m), gwID, isT0, natType, id)
if err != nil {
return handleDeleteError("NAT Rule", id, err)
Expand All @@ -204,8 +220,7 @@ func getNsxtPolicyNATRuleByID(sessionContext utl.SessionContext, connector clien
return client.Get(gwID, natType, ruleID)
}

func patchNsxtPolicyNATRule(sessionContext utl.SessionContext, connector client.Connector, gwID string, rule model.PolicyNatRule, isT0 bool) error {
natType := getNatTypeByAction(*rule.Action)
func patchNsxtPolicyNATRule(sessionContext utl.SessionContext, connector client.Connector, gwID string, rule model.PolicyNatRule, isT0 bool, natType string) error {
_, err := getTranslatedNetworks(rule)
if err != nil {
return err
Expand All @@ -231,12 +246,15 @@ func patchNsxtPolicyNATRule(sessionContext utl.SessionContext, connector client.
return client.Patch(gwID, natType, *rule.Id, rule)
}

func getNatTypeByAction(action string) string {
func getNatTypeByAction(natType string, action string) string {
if action == model.PolicyNatRule_ACTION_NAT64 {
return model.PolicyNat_NAT_TYPE_NAT64
}
salv-orlando marked this conversation as resolved.
Show resolved Hide resolved
if natType == "" {
return model.PolicyNat_NAT_TYPE_USER
}

return model.PolicyNat_NAT_TYPE_USER
return natType
}

func translatedNetworksNeeded(action string) bool {
Expand Down Expand Up @@ -284,8 +302,14 @@ func resourceNsxtPolicyNATRuleRead(d *schema.ResourceData, m interface{}) error
return handleMultitenancyTier0Error()
}

action := d.Get("action").(string)
natType := getNatTypeByAction(action)
natType := d.Get("type").(string)
if natType == "" {
// This can happen when provider was upgraded and we're refreshing an existing resource
// This is not an import case, so action should be set
action := d.Get("action").(string)
natType = getNatTypeByAction(natType, action)
d.Set("type", natType)
salv-orlando marked this conversation as resolved.
Show resolved Hide resolved
}
obj, err := getNsxtPolicyNATRuleByID(context, connector, gwID, isT0, natType, id)
if err != nil {
return handleReadError(d, "NAT Rule", id, err)
Expand Down Expand Up @@ -322,12 +346,30 @@ func resourceNsxtPolicyNATRuleRead(d *schema.ResourceData, m interface{}) error
return nil
}

func validateNatTypeAction(action string, natType string) error {
if action == model.PolicyNatRule_ACTION_NAT64 && (natType != "" && natType != model.PolicyNat_NAT_TYPE_NAT64) {
return fmt.Errorf("Rules with NAT64 action must have NAT64 nat type")
}

if natType == model.PolicyNat_NAT_TYPE_NAT64 && action != model.PolicyNatRule_ACTION_NAT64 {
return fmt.Errorf("Rules with type NAT64 action must have NAT64 action")
}
return nil
}

func resourceNsxtPolicyNATRuleCreate(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)

gwPolicyPath := d.Get("gateway_path").(string)
action := d.Get("action").(string)
natType := getNatTypeByAction(action)
natType := d.Get("type").(string)
if err := validateNatTypeAction(action, natType); err != nil {
return err
}
// nat type attribute was introduced as explicit attribute when existing deployments
// were calculating it based on action
// for backward compatibility, we allow the type to be overridden by NAT64 action
natType = getNatTypeByAction(natType, action)
isT0, gwID := parseGatewayPolicyPath(gwPolicyPath)
if gwID == "" {
return fmt.Errorf("gateway_path is not valid")
Expand Down Expand Up @@ -394,13 +436,15 @@ func resourceNsxtPolicyNATRuleCreate(d *schema.ResourceData, m interface{}) erro

log.Printf("[INFO] Creating NAT Rule with ID %s", id)

err := patchNsxtPolicyNATRule(getSessionContext(d, m), connector, gwID, ruleStruct, isT0)
err := patchNsxtPolicyNATRule(getSessionContext(d, m), connector, gwID, ruleStruct, isT0, natType)
if err != nil {
return handleCreateError("NAT Rule", id, err)
}

d.SetId(id)
d.Set("nsx_id", id)
// In case nat type was not specified or got overridden by action
d.Set("type", natType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to restore any change that might have been done in line 311?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is create flow - if nat type was left blank by the user, we need to set the Computed nat type that was determined in line 372


return resourceNsxtPolicyNATRuleRead(d, m)
}
Expand All @@ -426,6 +470,11 @@ func resourceNsxtPolicyNATRuleUpdate(d *schema.ResourceData, m interface{}) erro
displayName := d.Get("display_name").(string)
description := d.Get("description").(string)
action := d.Get("action").(string)
natType := d.Get("type").(string)
if err := validateNatTypeAction(action, natType); err != nil {
return err
}
natType = getNatTypeByAction(natType, action)
enabled := d.Get("enabled").(bool)
logging := d.Get("logging").(bool)
priority := int64(d.Get("rule_priority").(int))
Expand Down Expand Up @@ -467,7 +516,7 @@ func resourceNsxtPolicyNATRuleUpdate(d *schema.ResourceData, m interface{}) erro
}

log.Printf("[INFO] Updating NAT Rule with ID %s", id)
err := patchNsxtPolicyNATRule(context, connector, gwID, ruleStruct, isT0)
err := patchNsxtPolicyNATRule(context, connector, gwID, ruleStruct, isT0, natType)
if err != nil {
return handleUpdateError("NAT Rule", id, err)
}
Expand All @@ -492,24 +541,16 @@ func resourceNsxtPolicyNATRuleImport(d *schema.ResourceData, m interface{}) ([]*
if err != nil {
return nil, err
}
if natType == model.PolicyNat_NAT_TYPE_USER {
// Value will be overwritten by resourceNsxtPolicyNATRuleRead()
d.Set("action", model.PolicyNatRule_ACTION_DNAT)
} else {
d.Set("action", model.PolicyNatRule_ACTION_NAT64)
}
d.Set("type", natType)
return rd, nil
} else if !errors.Is(err, ErrNotAPolicyPath) {
return rd, err
}
if len(s) < 2 || len(s) > 3 {
return nil, fmt.Errorf("Please provide <gateway-id>/<nat-rule-id>/[nat-type] as an input")
}
if len(s) == 3 {
// take care of NAT64 nat-type via action
if s[2] == model.PolicyNat_NAT_TYPE_NAT64 {
d.Set("action", model.PolicyNatRule_ACTION_NAT64)
}
if len(s) < 3 {
d.Set("type", model.PolicyNat_NAT_TYPE_USER)
}

gwID := s[0]
Expand Down
Loading
Loading