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

VDC supports Flex #285

Merged
merged 34 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
156a05a
POC of versioning
vbauzys Jan 22, 2020
24de7e0
Add another way of handling versions
vbauzys Jan 24, 2020
03019ce
Removed sudo
vbauzys Jan 24, 2020
6ffd88d
Improvements
vbauzys Jan 24, 2020
469bb43
Improvements
vbauzys Jan 24, 2020
008be5e
Add update ability
vbauzys Jan 27, 2020
0bdd938
Update comment
vbauzys Jan 27, 2020
0a4ab92
Update comment
vbauzys Jan 27, 2020
1a1da2c
Update comment
vbauzys Jan 27, 2020
65ccfe8
Improvements
vbauzys Jan 27, 2020
0a21b62
Improvements
vbauzys Jan 27, 2020
853d1ba
Improvements
vbauzys Jan 28, 2020
7ed3661
Improvements
vbauzys Jan 28, 2020
3745d29
Added changelog
vbauzys Jan 29, 2020
c8ba6c6
Improvements
vbauzys Jan 30, 2020
ab5ed1f
Merge branch 'master' into vdc-flex
vbauzys Jan 30, 2020
2dbd012
make unused var to be used
vbauzys Jan 30, 2020
09f4bb6
Improvements
vbauzys Feb 4, 2020
0b58f26
Improvements by review
vbauzys Feb 6, 2020
6309e0d
Improvements
vbauzys Feb 7, 2020
336d66b
Improvements
vbauzys Feb 10, 2020
b67bd01
Improve comment
vbauzys Feb 10, 2020
52c7844
Improve comment
vbauzys Feb 10, 2020
fae4c4b
Improve comment
vbauzys Feb 10, 2020
65965d2
Moved admin VDC functions from adminorg to admindvc
vbauzys Feb 10, 2020
cb07d57
Improvements
vbauzys Feb 11, 2020
94c1684
Renaming
vbauzys Feb 11, 2020
2ffd512
Renaming
vbauzys Feb 11, 2020
c62d23b
Added guideline
vbauzys Feb 11, 2020
feaabcf
Improve guideline
vbauzys Feb 11, 2020
584906f
Rename vdcfuntion
vbauzys Feb 11, 2020
7ceccf9
Improve guideline
vbauzys Feb 12, 2020
c6497a5
Improvements
vbauzys Feb 13, 2020
a4bbb26
Improve comment
vbauzys Feb 13, 2020
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: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ go:
- "1.12.x"

sudo: false
install: false

script:
- env GO111MODULE=on make

after_success:
- echo "Build Successful!"
- echo "Build Successful!"
after_failure:
- echo "Build Failed!"
- echo "Build Failed!"

2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Improved functions to not expect XML namespaces provided in argument structure [#284](https://github.com/vmware/go-vcloud-director/pull/284)
* Change `int` and `bool` fields from types.VAppTemplateLeaseSettings and VAppLeaseSettings into pointers
* Added method `catalog.GetVappTemplateByHref`, and expose methods `vdc.GetEdgeGatewayByHref` and `vdc.GetEdgeGatewayRecordsType`
* Added methods `adminOrg.CreateOrgVdc`, `adminOrg.CreateOrgVdcAsync` and improved existing to support Flex VDC model. These new methods are dynamic as they change invocation behind the scenes based on vCD version [#285](https://github.com/vmware/go-vcloud-director/pull/285)
* Deprecated functions `adminOrg.CreateVdc` and `adminOrg.CreateVdcWait` [#285](https://github.com/vmware/go-vcloud-director/pull/285)

## 2.5.1 (December 12, 2019)

Expand Down
60 changes: 60 additions & 0 deletions CODING_GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,66 @@ prior to attempting a search.
Note: We are in the process of replacing methods that don't adhere to the above principles (for example, return a
structure instead of a pointer, return a nil error on not-found, etc).

## Implementing functions to support different vCD API versions

Functions dealing with different versions should use a matrix structure to identify which calls to run according to the
highest API version supported by vCD. An example can be found in adminvdc.go.

Note: use this pattern for adding new vCD functionality, which is not available in the earliest API version supported
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: please add a new line above this note.

by the code base (as indicated by `Client.APIVersion`).

```
type vdcVersionedFunc struct {
SupportedVersion string
CreateVdc func(adminOrg *AdminOrg, vdcConfiguration *types.VdcConfiguration) (*Vdc, error)
CreateVdcAsync func(adminOrg *AdminOrg, vdcConfiguration *types.VdcConfiguration) (Task, error)
UpdateVdc func(adminVdc *AdminVdc) (*AdminVdc, error)
UpdateVdcAsync func(adminVdc *AdminVdc) (Task, error)
}

var vdcVersionedFuncsV90 = vdcVersionedFuncs{
SupportedVersion: "29.0",
CreateVdc: createVdc,
CreateVdcAsync: createVdcAsync,
UpdateVdc: updateVdc,
UpdateVdcAsync: updateVdcAsync,
}

var vdcVersionedFuncsV97 = vdcVersionedFuncs{
SupportedVersion: "32.0",
CreateVdc: createVdcV97,
CreateVdcAsync: createVdcAsyncV97,
UpdateVdc: updateVdcV97,
UpdateVdcAsync: updateVdcAsyncV97,
}

var vdcVersionedFuncsByVcdVersion = map[string]vdcVersionedFuncs{
"vdc9.0": vdcCrudV90,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please note that vcdCrudV90 is not defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

"vdc9.1": vdcCrudV90,
"vdc9.5": vdcCrudV90,
"vdc9.7": vdcCrudV97,
"vdc10.0": vdcCrudV97,
}

func (adminOrg *AdminOrg) CreateOrgVdc(vdcConfiguration *types.VdcConfiguration) (*Vdc, error) {
apiVersion, err := adminOrg.client.maxSupportedVersion()
if err != nil {
return nil, err
}
vdcFunctions, ok := vdcVersionedFuncsByVcdVersion["vdc"+apiVersionToVcdVersion[apiVersion]]
if !ok {
return nil, fmt.Errorf("no entity type found %s", "vdc"+apiVersion)
}
if vdcFunctions.CreateVdc == nil {
return nil, fmt.Errorf("function CreateVdc is not defined for %s", "vdc"+apiVersion)
}
util.Logger.Printf("[DEBUG] CreateOrgVdc call function for version %s", vdcFunctions.SupportedVersion)
return vdcFunctions.CreateVdc(adminOrg, vdcConfiguration)
}
```



## Testing

Every feature in the library must include testing. See [TESTING.md](https://github.com/vmware/go-vcloud-director/blob/master/TESTING.md) for more info.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/vmware/go-vcloud-director v2.0.0+incompatible h1:3B121XZVdEOxRhv5ARswKVxXt4KznAbun8GoXNbbZWs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
172 changes: 24 additions & 148 deletions govcd/adminorg.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,6 @@ func NewAdminOrg(cli *Client) *AdminOrg {
}
}

// GetAdminVdcByName function uses a valid VDC name and returns a admin VDC object.
// If no VDC is found, then it returns an empty VDC and no error.
// Otherwise it returns an empty VDC and an error.
// Deprecated: Use adminOrg.GetAdminVDCByName
func (adminOrg *AdminOrg) GetAdminVdcByName(vdcname string) (AdminVdc, error) {
for _, vdcs := range adminOrg.AdminOrg.Vdcs.Vdcs {
if vdcs.Name == vdcname {
adminVdc := NewAdminVdc(adminOrg.client)
_, err := adminOrg.client.ExecuteRequest(vdcs.HREF, http.MethodGet,
"", "error getting vdc: %s", nil, adminVdc.AdminVdc)
return *adminVdc, err
}
}
return AdminVdc{}, nil
}

// CreateCatalog creates a catalog with given name and description under the
// the given organization. Returns an AdminCatalog that contains a creation
// task.
Expand All @@ -58,79 +42,6 @@ func (adminOrg *AdminOrg) CreateCatalog(name, description string) (AdminCatalog,
return CreateCatalog(adminOrg.client, adminOrg.AdminOrg.Link, name, description)
}

// If user specifies valid vdc name then this returns a vdc object.
// If no vdc is found, then it returns an empty vdc and no error.
// Otherwise it returns an empty vdc and an error. This function
// allows users to use an AdminOrg to fetch a vdc as well.
// Deprecated: Use adminOrg.GetVDCByName instead
func (adminOrg *AdminOrg) GetVdcByName(vdcname string) (Vdc, error) {
for _, vdcs := range adminOrg.AdminOrg.Vdcs.Vdcs {
if vdcs.Name == vdcname {
splitByAdminHREF := strings.Split(vdcs.HREF, "/api/admin")

// admin user and normal user will have different urls
var vdcHREF string
if len(splitByAdminHREF) == 1 {
vdcHREF = vdcs.HREF
} else {
vdcHREF = splitByAdminHREF[0] + "/api" + splitByAdminHREF[1]
}

vdc := NewVdc(adminOrg.client)

_, err := adminOrg.client.ExecuteRequest(vdcHREF, http.MethodGet,
"", "error getting vdc: %s", nil, vdc.Vdc)

return *vdc, err
}
}
return Vdc{}, nil
}

// CreateVdc creates a VDC with the given params under the given organization.
// Returns an AdminVdc.
// API Documentation: https://code.vmware.com/apis/220/vcloud#/doc/doc/operations/POST-VdcConfiguration.html
func (adminOrg *AdminOrg) CreateVdc(vdcConfiguration *types.VdcConfiguration) (Task, error) {
err := validateVdcConfiguration(vdcConfiguration)
if err != nil {
return Task{}, err
}

vdcConfiguration.Xmlns = types.XMLNamespaceVCloud

vdcCreateHREF, err := url.ParseRequestURI(adminOrg.AdminOrg.HREF)
if err != nil {
return Task{}, fmt.Errorf("error parsing admin org url: %s", err)
}
vdcCreateHREF.Path += "/vdcsparams"

adminVdc := NewAdminVdc(adminOrg.client)

_, err = adminOrg.client.ExecuteRequest(vdcCreateHREF.String(), http.MethodPost,
"application/vnd.vmware.admin.createVdcParams+xml", "error retrieving vdc: %s", vdcConfiguration, adminVdc.AdminVdc)
if err != nil {
return Task{}, err
}

// Return the task
task := NewTask(adminOrg.client)
task.Task = adminVdc.AdminVdc.Tasks.Task[0]
return *task, nil
}

// Creates the vdc and waits for the asynchronous task to complete.
func (adminOrg *AdminOrg) CreateVdcWait(vdcDefinition *types.VdcConfiguration) error {
task, err := adminOrg.CreateVdc(vdcDefinition)
if err != nil {
return err
}
err = task.WaitTaskCompletion()
if err != nil {
return fmt.Errorf("couldn't finish creating vdc %s", err)
}
return nil
}

// Deletes the org, returning an error if the vCD call fails.
// API Documentation: https://code.vmware.com/apis/220/vcloud#/doc/doc/operations/DELETE-Organization.html
func (adminOrg *AdminOrg) Delete(force bool, recursive bool) error {
Expand Down Expand Up @@ -662,8 +573,9 @@ func (adminOrg *AdminOrg) GetVDCByHref(vdcHref string) (*Vdc, error) {

vdc := NewVdc(adminOrg.client)

_, err := adminOrg.client.ExecuteRequest(vdcHREF, http.MethodGet,
"", "error getting vdc: %s", nil, vdc.Vdc)
_, err := adminOrg.client.ExecuteRequestWithApiVersion(vdcHREF, http.MethodGet,
"", "error getting vdc: %s", nil, vdc.Vdc,
adminOrg.client.GetSpecificApiVersionOnCondition(">= 32.0", "32.0"))

if err != nil {
return nil, err
Expand Down Expand Up @@ -721,67 +633,31 @@ func (adminOrg *AdminOrg) GetVDCByNameOrId(identifier string, refresh bool) (*Vd
return entity.(*Vdc), err
}

// GetVDCByHref retrieves a VDC using a direct call with the HREF
func (adminOrg *AdminOrg) GetAdminVDCByHref(vdcHref string) (*AdminVdc, error) {

adminVdc := NewAdminVdc(adminOrg.client)
// If user specifies valid vdc name then this returns a vdc object.
// If no vdc is found, then it returns an empty vdc and no error.
// Otherwise it returns an empty vdc and an error. This function
// allows users to use an AdminOrg to fetch a vdc as well.
// Deprecated: Use adminOrg.GetVDCByName instead
func (adminOrg *AdminOrg) GetVdcByName(vdcname string) (Vdc, error) {
for _, vdcs := range adminOrg.AdminOrg.Vdcs.Vdcs {
if vdcs.Name == vdcname {
splitByAdminHREF := strings.Split(vdcs.HREF, "/api/admin")

_, err := adminOrg.client.ExecuteRequest(vdcHref, http.MethodGet,
"", "error getting vdc: %s", nil, adminVdc.AdminVdc)
// admin user and normal user will have different urls
var vdcHREF string
if len(splitByAdminHREF) == 1 {
vdcHREF = vdcs.HREF
} else {
vdcHREF = splitByAdminHREF[0] + "/api" + splitByAdminHREF[1]
}

if err != nil {
return nil, err
}
return adminVdc, nil
}
vdc := NewVdc(adminOrg.client)

// GetAdminVDCByName finds an Admin VDC by Name
// On success, returns a pointer to the AdminVdc structure and a nil error
// On failure, returns a nil pointer and an error
func (adminOrg *AdminOrg) GetAdminVDCByName(vdcName string, refresh bool) (*AdminVdc, error) {
if refresh {
err := adminOrg.Refresh()
if err != nil {
return nil, err
}
}
for _, vdc := range adminOrg.AdminOrg.Vdcs.Vdcs {
if vdc.Name == vdcName {
return adminOrg.GetAdminVDCByHref(vdc.HREF)
}
}
return nil, ErrorEntityNotFound
}
_, err := adminOrg.client.ExecuteRequest(vdcHREF, http.MethodGet,
"", "error getting vdc: %s", nil, vdc.Vdc)

// GetAdminVDCById finds an Admin VDC by ID
// On success, returns a pointer to the AdminVdc structure and a nil error
// On failure, returns a nil pointer and an error
func (adminOrg *AdminOrg) GetAdminVDCById(vdcId string, refresh bool) (*AdminVdc, error) {
if refresh {
err := adminOrg.Refresh()
if err != nil {
return nil, err
}
}
for _, vdc := range adminOrg.AdminOrg.Vdcs.Vdcs {
if equalIds(vdcId, vdc.ID, vdc.HREF) {
return adminOrg.GetAdminVDCByHref(vdc.HREF)
return *vdc, err
}
}
return nil, ErrorEntityNotFound
}

// GetAdminVDCByNameOrId finds an Admin VDC by Name Or ID
// On success, returns a pointer to the AdminVdc structure and a nil error
// On failure, returns a nil pointer and an error
func (adminOrg *AdminOrg) GetAdminVDCByNameOrId(identifier string, refresh bool) (*AdminVdc, error) {
getByName := func(name string, refresh bool) (interface{}, error) {
return adminOrg.GetAdminVDCByName(name, refresh)
}
getById := func(id string, refresh bool) (interface{}, error) { return adminOrg.GetAdminVDCById(id, refresh) }
entity, err := getEntityByNameOrId(getByName, getById, identifier, refresh)
if entity == nil {
return nil, err
}
return entity.(*AdminVdc), err
return Vdc{}, nil
}
Loading