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 NSX-T Firewall support #381

Merged
merged 8 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from 6 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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
[#368](https://github.com/vmware/go-vcloud-director/pull/368)
* Added `NsxtAppPortProfile` and `types.NsxtAppPortProfile` for NSX-T Application Port Profile management
[#378](https://github.com/vmware/go-vcloud-director/pull/378)
* Added methods `NsxtEdgeGateway.UpdateNsxtFirewall()`, `NsxtEdgeGateway.GetNsxtFirewall()`, `nsxtFirewall.DeleteAll()`,
`nsxtFirewall.DeleteById` [#381](https://github.com/vmware/go-vcloud-director/pull/381)


BREAKING CHANGES:
* Added parameter `description` to method `vdc.ComposeRawVapp` [#372](https://github.com/vmware/go-vcloud-director/pull/372)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Though unlrelated to this PR, I just noticed this line. Do we break the semver aspect of the govcd versioning here?

CC: @dataclouder

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep - this happened as part of #372

* Added methods `vapp.Rename`, `vapp.UpdateDescription`, `vapp.UpdateNameDescription` [#372](https://github.com/vmware/go-vcloud-director/pull/372)
Expand All @@ -44,6 +45,8 @@ IMPROVEMENTS:
[#368](https://github.com/vmware/go-vcloud-director/pull/368)
* Improved test entity cleanup to allow specifying parent VDC for vApp removals
[#368](https://github.com/vmware/go-vcloud-director/pull/368)
* Cleanup a few unnecessary type conversions detected by new staticcheck version
[#381](https://github.com/vmware/go-vcloud-director/pull/381)
* Improved `OpenApiGetAllItems` to still follow pages in VCD endpoints with BUG which don't return 'nextPage' link for
pagination [#378](https://github.com/vmware/go-vcloud-director/pull/378)
* Improved LDAP container related tests to use correct port mapping for latest LDAP container version
Expand Down
2 changes: 1 addition & 1 deletion govcd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func decodeBody(bodyType types.BodyType, resp *http.Response, out interface{}) e
}
}

util.ProcessResponseOutput(util.FuncNameCallStack(), resp, fmt.Sprintf("%s", body))
util.ProcessResponseOutput(util.FuncNameCallStack(), resp, string(body))
if err != nil {
return err
}
Expand Down
21 changes: 21 additions & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,28 @@ func (vcd *TestVCD) removeLeftoverEntities(entity CleanupEntity) {
}

vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
// OpenApiEntityFirewall has different API structure therefore generic `OpenApiEntity` case does not fit cleanup
case "OpenApiEntityFirewall":
apiVersion, err := vcd.client.Client.checkOpenApiEndpointCompatibility(types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtFirewallRules)
if err != nil {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
return
}

urlRef, err := vcd.client.Client.OpenApiBuildEndpoint(entity.Name)
if err != nil {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
return
}

// Attempt to use supplied path in entity.Parent for element deletion
err = vcd.client.Client.OpenApiDeleteItem(apiVersion, urlRef, nil)
if err != nil {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
return
}

vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
case "vapp":
vdc := vcd.vdc
var err error
Expand Down
33 changes: 32 additions & 1 deletion govcd/common_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build api functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user nsxv affinity search ALL
// +build api functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user nsxv nsxt openapi affinity search ALL

/*
* Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
Expand Down Expand Up @@ -836,3 +836,34 @@ func getVdcNetworkPoolHref(vcd *TestVCD, check *C) string {

return networkPoolHref
}

// convertSliceOfStringsToOpenApiReferenceIds converts []string to []types.OpenApiReference by filling
// types.OpenApiReference.ID fields
func convertSliceOfStringsToOpenApiReferenceIds(ids []string) []types.OpenApiReference {
resultReferences := make([]types.OpenApiReference, len(ids))
for i, v := range ids {
resultReferences[i].ID = v
}

return resultReferences
}

// extractIdsFromOpenApiReferences extracts []string with IDs from []types.OpenApiReference which contains ID and Names
func extractIdsFromOpenApiReferences(refs []types.OpenApiReference) []string {
resultStrings := make([]string, len(refs))
for index := range refs {
resultStrings[index] = refs[index].ID
}

return resultStrings
}

// contains checks if a slice contains element
func contains(s []string, element string) bool {
for _, a := range s {
if a == element {
return true
}
}
return false
}
8 changes: 4 additions & 4 deletions govcd/entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
check.Skip(fmt.Sprintf("testFinderGetGenericEntity: %s %s not found.", def.entityType, def.entityName))
return
}
entity1 := ge.(genericEntity)
entity1 := ge

wantedType := fmt.Sprintf("*govcd.%s", def.entityType)
if testVerbose {
Expand All @@ -162,7 +162,7 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
ge, err = def.getById(entityId, false)
check.Assert(err, IsNil)
check.Assert(ge, NotNil)
entity2 := ge.(genericEntity)
entity2 := ge
check.Assert(entity2, NotNil)
check.Assert(entity2.name(), Equals, entityName)
check.Assert(entity2.id(), Equals, entityId)
Expand All @@ -175,7 +175,7 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
ge, err = def.getByNameOrId(entityId, false)
check.Assert(err, IsNil)
check.Assert(ge, NotNil)
entity3 := ge.(genericEntity)
entity3 := ge
check.Assert(entity3, NotNil)
check.Assert(entity3.name(), Equals, entityName)
check.Assert(entity3.id(), Equals, entityId)
Expand All @@ -189,7 +189,7 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
ge, err = def.getByNameOrId(entityName, false)
check.Assert(err, IsNil)
check.Assert(ge, NotNil)
entity4 := ge.(genericEntity)
entity4 := ge
check.Assert(entity4, NotNil)
check.Assert(entity4.name(), Equals, entityName)
check.Assert(entity4.id(), Equals, entityId)
Expand Down
4 changes: 2 additions & 2 deletions govcd/filter_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func searchByFilter(queryByMetadata queryByMetadataFunc, queryWithMetadataFields
util.Logger.Printf("[SearchByFilter] result %v: ", greater)
if greater {
latestDate = candidate.GetDate()
candidateByLatest = candidate.(QueryItem)
candidateByLatest = candidate
}
}
if candidateByLatest != nil {
Expand Down Expand Up @@ -281,7 +281,7 @@ func searchByFilter(queryByMetadata queryByMetadataFunc, queryWithMetadataFields
util.Logger.Printf("[SearchByFilter] result %v: ", greater)
if greater {
earliestDate = candidate.GetDate()
candidateByEarliest = candidate.(QueryItem)
candidateByEarliest = candidate
}
}
if candidateByEarliest != nil {
Expand Down
136 changes: 136 additions & 0 deletions govcd/nsxt_firewall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

// NsxtFirewall contains a types.NsxtFirewallRuleContainer which encloses three types of rules -
// system, default and user defined rules. User defined rules are the only ones that can be modified, others are
// read-only.
type NsxtFirewall struct {
NsxtFirewallRuleContainer *types.NsxtFirewallRuleContainer
client *Client
// edgeGatewayId is stored for usage in NsxtFirewall receiver functions
edgeGatewayId string
}

// UpdateNsxtFirewall allows user to set new firewall rules or update existing ones. The API does not have POST endpoint
// and always uses PUT endpoint for creating and updating.
func (egw *NsxtEdgeGateway) UpdateNsxtFirewall(firewallRules *types.NsxtFirewallRuleContainer) (*NsxtFirewall, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtFirewallRules
minimumApiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path edgeGateways/%s/firewall/rules
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

returnObject := &NsxtFirewall{
NsxtFirewallRuleContainer: &types.NsxtFirewallRuleContainer{},
client: client,
edgeGatewayId: egw.EdgeGateway.ID,
}

err = client.OpenApiPutItem(minimumApiVersion, urlRef, nil, firewallRules, returnObject.NsxtFirewallRuleContainer)
if err != nil {
return nil, fmt.Errorf("error setting NSX-T Firewall: %s", err)
}

return returnObject, nil
}

// GetNsxtFirewall retrieves all firewall rules system, default and user defined rules
func (egw *NsxtEdgeGateway) GetNsxtFirewall() (*NsxtFirewall, error) {
client := egw.client
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtFirewallRules
minimumApiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

// Insert Edge Gateway ID into endpoint path edgeGateways/%s/firewall/rules
urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
if err != nil {
return nil, err
}

returnObject := &NsxtFirewall{
NsxtFirewallRuleContainer: &types.NsxtFirewallRuleContainer{},
client: client,
edgeGatewayId: egw.EdgeGateway.ID,
}

err = client.OpenApiGetItem(minimumApiVersion, urlRef, nil, returnObject.NsxtFirewallRuleContainer)
if err != nil {
return nil, fmt.Errorf("error retrieving NSX-T Firewall rules: %s", err)
}

// Store Edge Gateway ID for later operations
returnObject.edgeGatewayId = egw.EdgeGateway.ID

return returnObject, nil
}

// DeleteAll allows users to delete all NSX-T Firewall rules in a particular Edge Gateway
func (firewall *NsxtFirewall) DeleteAll() error {

if firewall.edgeGatewayId == "" {
return fmt.Errorf("missing Edge Gateway ID")
}

endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtFirewallRules
minimumApiVersion, err := firewall.client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return err
}

urlRef, err := firewall.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, firewall.edgeGatewayId))
if err != nil {
return err
}

err = firewall.client.OpenApiDeleteItem(minimumApiVersion, urlRef, nil)

if err != nil {
return fmt.Errorf("error deleting all NSX-T Firewall Rules: %s", err)
}

return nil
}

// DeleteById allows users to delete NSX-T Firewall Rule By ID
func (firewall *NsxtFirewall) DeleteById(id string) error {
if id == "" {
return fmt.Errorf("empty ID specified")
}

endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNsxtFirewallRules
minimumApiVersion, err := firewall.client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return err
}

urlRef, err := firewall.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, firewall.edgeGatewayId), "/", id)
if err != nil {
return err
}

err = firewall.client.OpenApiDeleteItem(minimumApiVersion, urlRef, nil)

if err != nil {
return fmt.Errorf("error deleting NSX-T Firewall Rule with ID '%s': %s", id, err)
}

return nil
}
Loading