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 support for NSX Application Port Profiles #378

Merged
merged 2 commits into from
Jun 11, 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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
[#368](https://github.com/vmware/go-vcloud-director/pull/368)
* Added methods Org.QueryVmList and Org.QueryVmById to find VM by ID in an Org
[#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)


BREAKING CHANGES:
* Added parameter `description` to method `vdc.ComposeRawVapp` [#372](https://github.com/vmware/go-vcloud-director/pull/372)
Expand All @@ -41,6 +44,11 @@ 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)
* 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
[#378](https://github.com/vmware/go-vcloud-director/pull/378)


## 2.11.0 (March 10, 2021)

Expand Down
13 changes: 11 additions & 2 deletions govcd/adminorg_ldap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,22 +161,31 @@ func configureLdapForOrg(vcd *TestVCD, check *C, ldapHostIp string) {
// In essence it creates two groups - "admin_staff" and "ship_crew" and a few users.
// More information about users and groups in: https://github.com/rroemhild/docker-test-openldap
func createLdapServer(vcd *TestVCD, check *C, directNetworkName string) (string, string, string) {
// LDAP configuration is tailored for this testing LDAP container. However it may make sense to host it in custom
// docker registry because docker throttles container downloads and this might cause test failures.
// Config vcd.config.Misc.LdapContainer can be set to pull this container from custom registry.
ldapContainerName := "rroemhild/test-openldap"
if vcd.config.Misc.LdapContainer != "" {
ldapContainerName = vcd.config.Misc.LdapContainer
}
fmt.Printf("# Using docker LDAP image '%s'\n", ldapContainerName)

vAppName := "ldap"
// The customization script waits until IP address is set on the NIC because Guest tools run
// script and network configuration together. If the script runs too quick - there is a risk
// that network card is not yet configured and it will not be able to pull docker image from
// remote. Guest tools could also be interrupted if the script below failed before NICs are
// configured therefore it is run in background.
// It waits until "inet" (not "inet6") is set and then runs docker container
const ldapCustomizationScript = `
ldapCustomizationScript := `
{
until ip a show eth0 | grep "inet "
do
sleep 1
done
systemctl enable docker
systemctl start docker
docker run --name ldap-server --restart=always --privileged -d -p 389:389 rroemhild/test-openldap
docker run --name ldap-server --restart=always -d -p 389:10389 ` + ldapContainerName + `
} &
`
// Get Org, Vdc
Expand Down
2 changes: 1 addition & 1 deletion govcd/adminvdc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (vcd *TestVCD) Test_VdcUpdateStorageProfile(check *C) {
check.Assert(storageProfileId, NotNil)

updatedVdc, err := adminVdc.UpdateStorageProfile(storageProfileId, &types.AdminVdcStorageProfile{
Name: foundStorageProfile.ProviderVdcStorageProfile.Name,
Name: foundStorageProfile.Name,
Default: true,
Limit: 9081,
Enabled: takeBoolPointer(true),
Expand Down
3 changes: 3 additions & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ type TestConfig struct {
Media string `yaml:"mediaName,omitempty"`
PhotonOsOvaPath string `yaml:"photonOsOvaPath,omitempty"`
} `yaml:"media"`
Misc struct {
LdapContainer string `yaml:"ldapContainer,omitempty"`
} `yaml:"misc"`
}

// Test struct for vcloud-director.
Expand Down
6 changes: 5 additions & 1 deletion govcd/disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package govcd

import (
"fmt"
"strings"

. "gopkg.in/check.v1"

Expand Down Expand Up @@ -685,7 +686,10 @@ func (vcd *TestVCD) Test_GetDiskByHref(check *C) {
check.Assert(disk.Disk.Name, Equals, diskName)
check.Assert(disk.Disk.Description, Equals, diskName+"Description")

invalidDiskHREF := diskHREF + "1"
// Creating HREF with fake UUID
uuid, err := GetUuidFromHref(diskHREF, true)
check.Assert(err, IsNil)
invalidDiskHREF := strings.ReplaceAll(diskHREF, uuid, "1abcbdb3-1111-1111-a1c2-85d261e22fcf")
disk, err = vcd.vdc.GetDiskByHref(invalidDiskHREF)
check.Assert(err, NotNil)
check.Assert(IsNotFound(err), Equals, true)
Expand Down
219 changes: 219 additions & 0 deletions govcd/nsxt_application_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* Copyright 2021 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"fmt"
"net/url"

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

// NsxtAppPortProfile uses OpenAPI endpoint to operate NSX-T Application Port Profiles
// It can have 3 types of scopes:
// * SYSTEM - Read-only (The ones that are provided by SYSTEM). Constant `types.ApplicationPortProfileScopeSystem`
// * PROVIDER - Created by Provider on a particular network provider (NSX-T manager). Constant `types.ApplicationPortProfileScopeProvider`
// * TENANT (Created by Tenant at Org VDC level). Constant `types.ApplicationPortProfileScopeTenant`
//
// More details about scope in documentation for types.NsxtAppPortProfile
type NsxtAppPortProfile struct {
NsxtAppPortProfile *types.NsxtAppPortProfile
client *Client
}

// CreateNsxtAppPortProfile allows users to create NSX-T Application Port Profile definition.
// It can have 3 types of scopes:
// * SYSTEM (The ones that are provided by SYSTEM) Read-only
// * PROVIDER (Created by Provider globally)
// * TENANT (Create by tenant at Org level)
// More details about scope in documentation for types.NsxtAppPortProfile
func (org *Org) CreateNsxtAppPortProfile(appPortProfileConfig *types.NsxtAppPortProfile) (*NsxtAppPortProfile, error) {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAppPortProfiles
minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

urlRef, err := org.client.OpenApiBuildEndpoint(endpoint)
if err != nil {
return nil, err
}

returnObject := &NsxtAppPortProfile{
NsxtAppPortProfile: &types.NsxtAppPortProfile{},
client: org.client,
}

err = org.client.OpenApiPostItem(minimumApiVersion, urlRef, nil, appPortProfileConfig, returnObject.NsxtAppPortProfile)
if err != nil {
return nil, fmt.Errorf("error creating NSX-T Application Port Profile: %s", err)
}

return returnObject, nil
}

// GetAllNsxtAppPortProfiles returns all NSX-T Application Port Profiles for specific scope
// More details about scope in documentation for types.NsxtAppPortProfile
func (org *Org) GetAllNsxtAppPortProfiles(queryParameters url.Values, scope string) ([]*NsxtAppPortProfile, error) {
queryParams := copyOrNewUrlValues(queryParameters)
if scope != "" {
queryParams = queryParameterFilterAnd("scope=="+scope, queryParams)
}

return getAllNsxtAppPortProfiles(org.client, queryParams)
}

// GetNsxtAppPortProfileByName allows users to retrieve Application Port Profiles for specific scope.
// More details in documentation for types.NsxtAppPortProfile
//
// Note. Names are enforced to be unique per scope
func (org *Org) GetNsxtAppPortProfileByName(name, scope string) (*NsxtAppPortProfile, error) {
queryParameters := url.Values{}
if scope != "" {
queryParameters = queryParameterFilterAnd("scope=="+scope, queryParameters)
}

return getNsxtAppPortProfileByName(org.client, name, queryParameters)
}

// GetNsxtAppPortProfileById retrieves NSX-T Application Port Profile by ID
func (org *Org) GetNsxtAppPortProfileById(id string) (*NsxtAppPortProfile, error) {
return getNsxtAppPortProfileById(org.client, id)
}

// Update allows users to update NSX-T Application Port Profile
func (appPortProfile *NsxtAppPortProfile) Update(appPortProfileConfig *types.NsxtAppPortProfile) (*NsxtAppPortProfile, error) {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAppPortProfiles
minimumApiVersion, err := appPortProfile.client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

if appPortProfileConfig.ID == "" {
return nil, fmt.Errorf("cannot update NSX-T Application Port Profile without ID")
}

urlRef, err := appPortProfile.client.OpenApiBuildEndpoint(endpoint, appPortProfileConfig.ID)
if err != nil {
return nil, err
}

returnObject := &NsxtAppPortProfile{
NsxtAppPortProfile: &types.NsxtAppPortProfile{},
client: appPortProfile.client,
}

err = appPortProfile.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, appPortProfileConfig, returnObject.NsxtAppPortProfile)
if err != nil {
return nil, fmt.Errorf("error updating NSX-T Application Port Profile : %s", err)
}

return returnObject, nil
}

// Delete allows users to delete NSX-T Application Port Profile
func (appPortProfile *NsxtAppPortProfile) Delete() error {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAppPortProfiles
minimumApiVersion, err := appPortProfile.client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return err
}

if appPortProfile.NsxtAppPortProfile.ID == "" {
return fmt.Errorf("cannot delete NSX-T Application Port Profile without ID")
}

urlRef, err := appPortProfile.client.OpenApiBuildEndpoint(endpoint, appPortProfile.NsxtAppPortProfile.ID)
if err != nil {
return err
}

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

if err != nil {
return fmt.Errorf("error deleting NSX-T Application Port Profile: %s", err)
}

return nil
}

func getNsxtAppPortProfileByName(client *Client, name string, queryParameters url.Values) (*NsxtAppPortProfile, error) {
queryParams := copyOrNewUrlValues(queryParameters)
queryParams = queryParameterFilterAnd("name=="+name, queryParams)

allAppPortProfiles, err := getAllNsxtAppPortProfiles(client, queryParams)
if err != nil {
return nil, fmt.Errorf("could not find NSX-T Application Port Profile with name '%s': %s", name, err)
}

if len(allAppPortProfiles) == 0 {
return nil, fmt.Errorf("%s: expected exactly one NSX-T Application Port Profile with name '%s'. Got %d", ErrorEntityNotFound, name, len(allAppPortProfiles))
}

if len(allAppPortProfiles) > 1 {
return nil, fmt.Errorf("expected exactly one NSX-T Application Port Profile with name '%s'. Got %d", name, len(allAppPortProfiles))
}

return getNsxtAppPortProfileById(client, allAppPortProfiles[0].NsxtAppPortProfile.ID)
}

func getNsxtAppPortProfileById(client *Client, id string) (*NsxtAppPortProfile, error) {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAppPortProfiles
minimumApiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

if id == "" {
return nil, fmt.Errorf("empty NSX-T Application Port Profile ID specified")
}

urlRef, err := client.OpenApiBuildEndpoint(endpoint, id)
if err != nil {
return nil, err
}

appPortProfile := &NsxtAppPortProfile{
NsxtAppPortProfile: &types.NsxtAppPortProfile{},
client: client,
}

err = client.OpenApiGetItem(minimumApiVersion, urlRef, nil, appPortProfile.NsxtAppPortProfile)
if err != nil {
return nil, err
}

return appPortProfile, nil
}

func getAllNsxtAppPortProfiles(client *Client, queryParameters url.Values) ([]*NsxtAppPortProfile, error) {
endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAppPortProfiles
minimumApiVersion, err := client.checkOpenApiEndpointCompatibility(endpoint)
if err != nil {
return nil, err
}

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

typeResponses := []*types.NsxtAppPortProfile{{}}
err = client.OpenApiGetAllItems(minimumApiVersion, urlRef, queryParameters, &typeResponses)
if err != nil {
return nil, err
}

// Wrap all typeResponses into NsxtAppPortProfile types with client
wrappedResponses := make([]*NsxtAppPortProfile, len(typeResponses))
for sliceIndex := range typeResponses {
wrappedResponses[sliceIndex] = &NsxtAppPortProfile{
NsxtAppPortProfile: typeResponses[sliceIndex],
client: client,
}
}

return wrappedResponses, nil
}
Loading