Skip to content

Commit

Permalink
Implement policy resources for lb monitor profile
Browse files Browse the repository at this point in the history
Implement LB monitor resources using policy API.

Types of LB monitors include:
- lb_http_monitor
- lb_https_monitor
- lb_icmp_monitor
- lb_passive_monitor
- lb_tcp_monitor
- lb_udp_monitor

Signed-off-by: Shizhao Liu <[email protected]>
  • Loading branch information
Shizhao Liu committed Jan 9, 2024
1 parent 886c9fe commit 88103cc
Show file tree
Hide file tree
Showing 22 changed files with 2,896 additions and 0 deletions.
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) {
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,
}
}
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(),
"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])
}

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 {
return resourceNsxtPolicyLBMonitorProfileDelete(d, m)
}
Loading

0 comments on commit 88103cc

Please sign in to comment.