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

Implement policy resources for lb monitor profile #1036

Merged
merged 1 commit into from
Jan 11, 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
118 changes: 118 additions & 0 deletions nsxt/lb_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/vmware/go-vmware-nsxt/loadbalancer"
"github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

// Helpers for common LB monitor schema settings
Expand Down Expand Up @@ -267,6 +268,123 @@ func resourceNsxtPolicyLBAppProfileDelete(d *schema.ResourceData, m interface{})
if err != nil {
return handleDeleteError("LBAppProfile", id, err)
}
return nil
}

func resourceNsxtPolicyLBMonitorProfileExistsWrapper(id string, connector client.Connector, isGlobalManager bool) (bool, error) {
client := infra.NewLbMonitorProfilesClient(connector)
_, err := client.Get(id)
if err == nil {
return true, nil
}

if isNotFoundError(err) {
return false, nil
}
msg := fmt.Sprintf("Error retrieving resource LBMonitorProfile")
return false, logAPIError(msg, err)
}

func resourceNsxtPolicyLBMonitorProfileDelete(d *schema.ResourceData, m interface{}) error {
id := d.Id()
if id == "" {
return fmt.Errorf("Error obtaining LBMonitorProfile ID")
}
connector := getPolicyConnector(m)
forceParam := true
client := infra.NewLbMonitorProfilesClient(connector)
err := client.Delete(id, &forceParam)
if err != nil {
return handleDeleteError("LBMonitorProfile", id, err)
}
return nil
}

func getLbServerSslSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"certificate_chain_depth": {
Type: schema.TypeInt,
Optional: true,
Description: "Authentication depth is used to set the verification depth in the server certificates chain. format: int64",
},
"client_certificate_path": getPolicyPathSchema(false, false, "Client certificate path"),
"server_auth": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(lBServerSslProfileBindingServerAuthValues, false),
Description: "Server authentication mode.",
},
"server_auth_ca_paths": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "If server auth type is REQUIRED, server certificate must be signed by one of the trusted Certificate Authorities (CAs), also referred to as root CAs, whose self signed certificates are specified.",
},
"server_auth_crl_paths": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "A Certificate Revocation List (CRL) can be specified in the server-side SSL profile binding to disallow compromised server certificates.",
},
"ssl_profile_path": getPolicyPathSchema(false, false, "SSL profile path"),
},
},
Optional: true,
}
}

func getLbServerSslFromSchema(d *schema.ResourceData) *model.LBServerSslProfileBinding {
serverSslList := d.Get("server_ssl").([]interface{})
var serverSsl *model.LBServerSslProfileBinding
for _, item := range serverSslList {
data := item.(map[string]interface{})
certificateChainDepth := int64(data["certificate_chain_depth"].(int))
clientCertificatePath := data["client_certificate_path"].(string)
serverAuth := data["server_auth"].(string)
serverAuthCaPathsList := data["server_auth_ca_paths"].([]interface{})
serverAuthCrlPathsList := data["server_auth_crl_paths"].([]interface{})
var serverAuthCaPaths []string
for _, path := range serverAuthCaPathsList {
serverAuthCaPaths = append(serverAuthCaPaths, path.(string))
}
var serverAuthCrlPaths []string
for _, path := range serverAuthCrlPathsList {
serverAuthCrlPaths = append(serverAuthCrlPaths, path.(string))
}
sslProfilePath := data["ssl_profile_path"].(string)
obj := model.LBServerSslProfileBinding{
CertificateChainDepth: &certificateChainDepth,
ClientCertificatePath: &clientCertificatePath,
ServerAuth: &serverAuth,
ServerAuthCaPaths: serverAuthCaPaths,
ServerAuthCrlPaths: serverAuthCrlPaths,
SslProfilePath: &sslProfilePath,
}
serverSsl = &obj
}
return serverSsl
}

func setLbServerSslInSchema(d *schema.ResourceData, lBServerSsl model.LBServerSslProfileBinding) {
var serverSslList []map[string]interface{}
elem := make(map[string]interface{})
elem["certificate_chain_depth"] = lBServerSsl.CertificateChainDepth
elem["client_certificate_path"] = lBServerSsl.ClientCertificatePath
elem["server_auth"] = lBServerSsl.ServerAuth
elem["ssl_profile_path"] = lBServerSsl.SslProfilePath
elem["server_auth_ca_paths"] = lBServerSsl.ServerAuthCaPaths
elem["server_auth_crl_paths"] = lBServerSsl.ServerAuthCrlPaths
serverSslList = append(serverSslList, elem)
err := d.Set("server_ssl", serverSslList)
if err != nil {
log.Printf("[WARNING] Failed to set server_ssl in schema: %v", err)
}
}
35 changes: 35 additions & 0 deletions nsxt/policy_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,38 @@ func getElemOrEmptyMapFromMap(d map[string]interface{}, key string) map[string]i
}
return make(map[string]interface{})
}

func setPolicyLbHTTPHeaderInSchema(d *schema.ResourceData, attrName string, headers []model.LbHttpRequestHeader) {
Copy link
Member

Choose a reason for hiding this comment

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

I would not mind instead creating a generic function that sets an attribute which is a list of key/value pairs. This can be used for tags, headers, and likely more.

I do not have however a strong preference.

var headerList []map[string]string
for _, header := range headers {
elem := make(map[string]string)
elem["name"] = *header.HeaderName
elem["value"] = *header.HeaderValue
headerList = append(headerList, elem)
}
d.Set(attrName, headerList)
}

func getPolicyLbHTTPHeaderFromSchema(d *schema.ResourceData, attrName string) []model.LbHttpRequestHeader {
headers := d.Get(attrName).(*schema.Set).List()
var headerList []model.LbHttpRequestHeader
for _, header := range headers {
data := header.(map[string]interface{})
name := data["name"].(string)
value := data["value"].(string)
elem := model.LbHttpRequestHeader{
HeaderName: &name,
HeaderValue: &value}

headerList = append(headerList, elem)
}
return headerList
}

func getPolicyLbMonitorPortSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeInt,
Description: "If the monitor port is specified, it would override pool member port setting for healthcheck. A port range is not supported",
Optional: true,
2ez4szliu marked this conversation as resolved.
Show resolved Hide resolved
}
}
6 changes: 6 additions & 0 deletions nsxt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,12 @@ func Provider() *schema.Provider {
"nsxt_policy_security_policy_rule": resourceNsxtPolicySecurityPolicyRule(),
"nsxt_policy_parent_security_policy": resourceNsxtPolicyParentSecurityPolicy(),
"nsxt_policy_firewall_exclude_list_member": resourceNsxtPolicyFirewallExcludeListMember(),
"nsxt_policy_lb_http_monitor_profile": resourceNsxtPolicyLBHttpMonitorProfile(),
"nsxt_policy_lb_https_monitor_profile": resourceNsxtPolicyLBHttpsMonitorProfile(),
"nsxt_policy_lb_icmp_monitor_profile": resourceNsxtPolicyLBIcmpMonitorProfile(),
"nsxt_policy_lb_passive_monitor_profile": resourceNsxtPolicyLBPassiveMonitorProfile(),
"nsxt_policy_lb_tcp_monitor_profile": resourceNsxtPolicyLBTcpMonitorProfile(),
"nsxt_policy_lb_udp_monitor_profile": resourceNsxtPolicyLBUdpMonitorProfile(),
},

ConfigureFunc: providerConfigure,
Expand Down
181 changes: 181 additions & 0 deletions nsxt/resource_nsxt_policy_lb_http_monitor_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/* Copyright © 2023 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/vsphere-automation-sdk-go/runtime/bindings"
"github.com/vmware/vsphere-automation-sdk-go/runtime/data"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

func resourceNsxtPolicyLBHttpMonitorProfile() *schema.Resource {
return &schema.Resource{
Create: resourceNsxtPolicyLBHttpMonitorProfileCreate,
Read: resourceNsxtPolicyLBHttpMonitorProfileRead,
Update: resourceNsxtPolicyLBHttpMonitorProfileUpdate,
Delete: resourceNsxtPolicyLBHttpMonitorProfileDelete,
Importer: &schema.ResourceImporter{
State: nsxtPolicyPathResourceImporter,
},

Schema: map[string]*schema.Schema{
"nsx_id": getNsxIDSchema(),
"path": getPathSchema(),
"display_name": getDisplayNameSchema(),
"description": getDescriptionSchema(),
"revision": getRevisionSchema(),
"tag": getTagsSchema(),
"request_body": getLbMonitorRequestBodySchema(),
2ez4szliu marked this conversation as resolved.
Show resolved Hide resolved
"request_header": getLbHTTPHeaderSchema("Array of HTTP request headers"),
"request_method": getLbMonitorRequestMethodSchema(),
"request_url": getLbMonitorRequestURLSchema(),
"request_version": getLbMonitorRequestVersionSchema(),
"response_body": getLbMonitorResponseBodySchema(),
"response_status_codes": getLbMonitorResponseStatusCodesSchema(),
"fall_count": getLbMonitorFallCountSchema(),
"interval": getLbMonitorIntervalSchema(),
"rise_count": getLbMonitorRiseCountSchema(),
"timeout": getLbMonitorTimeoutSchema(),
"monitor_port": getPolicyLbMonitorPortSchema(),
},
}
}

func resourceNsxtPolicyLBHttpMonitorProfilePatch(d *schema.ResourceData, m interface{}, id string) error {
connector := getPolicyConnector(m)
converter := bindings.NewTypeConverter()

displayName := d.Get("display_name").(string)
description := d.Get("description").(string)
tags := getPolicyTagsFromSchema(d)
requestBody := d.Get("request_body").(string)
requestHeaders := getPolicyLbHTTPHeaderFromSchema(d, "request_header")
requestMethod := d.Get("request_method").(string)
requestURL := d.Get("request_url").(string)
requestVersion := d.Get("request_version").(string)
responseBody := d.Get("response_body").(string)
responseStatusCodes := interface2Int64List(d.Get("response_status_codes").([]interface{}))
fallCount := int64(d.Get("fall_count").(int))
interval := int64(d.Get("interval").(int))
riseCount := int64(d.Get("rise_count").(int))
timeout := int64(d.Get("timeout").(int))
monitorPort := int64(d.Get("monitor_port").(int))

resourceType := model.LBMonitorProfile_RESOURCE_TYPE_LBHTTPMONITORPROFILE

obj := model.LBHttpMonitorProfile{
DisplayName: &displayName,
Description: &description,
Tags: tags,
RequestBody: &requestBody,
RequestHeaders: requestHeaders,
RequestMethod: &requestMethod,
RequestUrl: &requestURL,
RequestVersion: &requestVersion,
ResponseBody: &responseBody,
ResponseStatusCodes: responseStatusCodes,
FallCount: &fallCount,
Interval: &interval,
MonitorPort: &monitorPort,
RiseCount: &riseCount,
Timeout: &timeout,
ResourceType: resourceType,
}

log.Printf("[INFO] Patching LBHttpMonitorProfile with ID %s", id)
dataValue, errs := converter.ConvertToVapi(obj, model.LBHttpMonitorProfileBindingType())
if errs != nil {
return fmt.Errorf("LBMonitorProfile %s is not of type LBHttpMonitorProfile %s", id, errs[0])
}

client := infra.NewLbMonitorProfilesClient(connector)
return client.Patch(id, dataValue.(*data.StructValue))
}

func resourceNsxtPolicyLBHttpMonitorProfileCreate(d *schema.ResourceData, m interface{}) error {

// Initialize resource Id and verify this ID is not yet used
id, err := getOrGenerateID(d, m, resourceNsxtPolicyLBMonitorProfileExistsWrapper)
if err != nil {
return err
}

err = resourceNsxtPolicyLBHttpMonitorProfilePatch(d, m, id)
if err != nil {
return handleCreateError("LBHttpMonitorProfile", id, err)
}

d.SetId(id)
d.Set("nsx_id", id)

return resourceNsxtPolicyLBHttpMonitorProfileRead(d, m)
}

func resourceNsxtPolicyLBHttpMonitorProfileRead(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)
converter := bindings.NewTypeConverter()

id := d.Id()
if id == "" {
return fmt.Errorf("Error obtaining LBHttpMonitorProfile ID")
}

client := infra.NewLbMonitorProfilesClient(connector)
obj, err := client.Get(id)
if err != nil {
return handleReadError(d, "LBHttpMonitorProfile", id, err)
}

baseObj, errs := converter.ConvertToGolang(obj, model.LBHttpMonitorProfileBindingType())
if len(errs) > 0 {
return fmt.Errorf("Error converting LBHttpMonitorProfile %s", errs[0])
2ez4szliu marked this conversation as resolved.
Show resolved Hide resolved
}

lbHTTPMonitor := baseObj.(model.LBHttpMonitorProfile)

d.Set("revision", lbHTTPMonitor.Revision)
d.Set("description", lbHTTPMonitor.Description)
d.Set("display_name", lbHTTPMonitor.DisplayName)
setPolicyTagsInSchema(d, lbHTTPMonitor.Tags)
d.Set("fall_count", lbHTTPMonitor.FallCount)
d.Set("interval", lbHTTPMonitor.Interval)
d.Set("monitor_port", lbHTTPMonitor.MonitorPort)
d.Set("rise_count", lbHTTPMonitor.RiseCount)
d.Set("timeout", lbHTTPMonitor.Timeout)
d.Set("request_body", lbHTTPMonitor.RequestBody)
d.Set("path", lbHTTPMonitor.Path)
d.Set("nsx_id", id)
setPolicyLbHTTPHeaderInSchema(d, "request_header", lbHTTPMonitor.RequestHeaders)
d.Set("request_method", lbHTTPMonitor.RequestMethod)
d.Set("request_url", lbHTTPMonitor.RequestUrl)
d.Set("request_version", lbHTTPMonitor.RequestVersion)
d.Set("response_body", lbHTTPMonitor.ResponseBody)
d.Set("response_status_codes", int64List2Interface(lbHTTPMonitor.ResponseStatusCodes))

return nil
}

func resourceNsxtPolicyLBHttpMonitorProfileUpdate(d *schema.ResourceData, m interface{}) error {

id := d.Id()
if id == "" {
return fmt.Errorf("Error obtaining LBHttpMonitorProfile ID")
}

err := resourceNsxtPolicyLBHttpMonitorProfilePatch(d, m, id)
if err != nil {
return handleUpdateError("LBHttpMonitorProfile", id, err)
}

return resourceNsxtPolicyLBHttpMonitorProfileRead(d, m)
}

func resourceNsxtPolicyLBHttpMonitorProfileDelete(d *schema.ResourceData, m interface{}) error {
2ez4szliu marked this conversation as resolved.
Show resolved Hide resolved
return resourceNsxtPolicyLBMonitorProfileDelete(d, m)
}
Loading