generated from hashicorp/packer-plugin-scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 97
feat: datasource for virtual machines #498
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
Open
castorsky
wants to merge
6
commits into
hashicorp:main
Choose a base branch
from
castorsky:feature/datasource-virtual_machine
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
23a6cb4
add: new datasource and documentation
castorsky bd81ebd
review: code fixed
castorsky 598ba81
review: renamed `tags` config field to `tag`
castorsky 33372c2
review: reformat documentation
castorsky d943c0c
refactor: filters using unit functions
castorsky b77f6eb
review: changed error type
castorsky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
.web-docs/components/data-source/virtualmachine/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
Type: `vsphere-virtualmachine` | ||
Artifact BuilderId: `vsphere.virtualmachine` | ||
|
||
This data source retrieves information about existing virtual machines from vSphere | ||
and return name of one virtual machine that matches all specified filters. This virtual | ||
machine can be used in the vSphere Clone builder to select a template. | ||
|
||
## Configuration Reference | ||
|
||
### Filters Configuration | ||
|
||
**Optional:** | ||
|
||
<!-- Code generated from the comments of the Config struct in datasource/virtualmachine/data.go; DO NOT EDIT MANUALLY --> | ||
|
||
- `name` (string) - Basic filter with glob support (e.g. `ubuntu_basic*`). Defaults to `*`. | ||
Using strict globs will not reduce execution time because vSphere API | ||
returns the full inventory. But can be used for better readability over | ||
regular expressions. | ||
|
||
- `name_regex` (string) - Extended name filter with regular expressions support | ||
(e.g. `ubuntu[-_]basic[0-9]*`). Default is empty. The match of the | ||
regular expression is checked by substring. Use `^` and `$` to define a | ||
full string. For example, the `^[^_]+$` filter will search names | ||
without any underscores. The expression must use | ||
[Go Regex Syntax](https://pkg.go.dev/regexp/syntax). | ||
|
||
- `template` (bool) - Filter to return only objects that are virtual machine templates. | ||
Defaults to `false` and returns all virtual machines. | ||
|
||
- `host` (string) - Filter to search virtual machines only on the specified ESX host. | ||
|
||
- `tag` ([]Tag) - Filter to return only that virtual machines that have attached all | ||
specifies tags. Specify one or more `tag` blocks to define list of tags | ||
for the filter. | ||
|
||
HCL Example: | ||
|
||
```hcl | ||
tag { | ||
category = "team" | ||
name = "operations" | ||
} | ||
tag { | ||
category = "sla" | ||
name = "gold" | ||
} | ||
``` | ||
|
||
- `latest` (bool) - This filter determines how to handle multiple machines that were | ||
matched with all previous filters. Machine creation time is being used | ||
to find latest. By default, multiple matching machines results in an | ||
error. | ||
|
||
<!-- End of code generated from the comments of the Config struct in datasource/virtualmachine/data.go; --> | ||
|
||
|
||
### Tags Filter Configuration | ||
|
||
**Required:** | ||
|
||
<!-- Code generated from the comments of the Tag struct in datasource/virtualmachine/data.go; DO NOT EDIT MANUALLY --> | ||
|
||
- `name` (string) - Name of the tag added to virtual machine which must pass the `tag` | ||
filter. | ||
|
||
- `category` (string) - Name of the tag category that contains the tag. | ||
|
||
-> **Note:** Both `name` and `category` must be specified in the `tag` | ||
filter. | ||
|
||
<!-- End of code generated from the comments of the Tag struct in datasource/virtualmachine/data.go; --> | ||
|
||
|
||
### Connection Configuration | ||
|
||
**Optional:** | ||
|
||
<!-- Code generated from the comments of the ConnectConfig struct in builder/vsphere/common/step_connect.go; DO NOT EDIT MANUALLY --> | ||
|
||
- `vcenter_server` (string) - The fully qualified domain name or IP address of the vCenter Server | ||
instance. | ||
|
||
- `username` (string) - The username to authenticate with the vCenter Server instance. | ||
|
||
- `password` (string) - The password to authenticate with the vCenter Server instance. | ||
|
||
- `insecure_connection` (bool) - Do not validate the certificate of the vCenter Server instance. | ||
Defaults to `false`. | ||
|
||
-> **Note:** This option is beneficial in scenarios where the certificate | ||
is self-signed or does not meet standard validation criteria. | ||
|
||
- `datacenter` (string) - The name of the datacenter object in the vSphere inventory. | ||
|
||
-> **Note:** Required if more than one datacenter object exists in the | ||
vSphere inventory. | ||
|
||
<!-- End of code generated from the comments of the ConnectConfig struct in builder/vsphere/common/step_connect.go; --> | ||
|
||
|
||
## Output | ||
|
||
<!-- Code generated from the comments of the DatasourceOutput struct in datasource/virtualmachine/data.go; DO NOT EDIT MANUALLY --> | ||
|
||
- `vm_name` (string) - Name of the found virtual machine. | ||
|
||
<!-- End of code generated from the comments of the DatasourceOutput struct in datasource/virtualmachine/data.go; --> | ||
|
||
|
||
## Example Usage | ||
|
||
This example demonstrates how to connect to vSphere cluster and search for the latest virtual machine | ||
that matches the filters. The name of the machine is then output to the console as an output variable. | ||
```hcl | ||
data "vsphere-virtualmachine" "default" { | ||
vcenter_server = "vcenter.example.com" | ||
insecure_connection = true | ||
username = "[email protected]" | ||
password = "VMware1!" | ||
datacenter = "dc-01" | ||
latest = true | ||
tags { | ||
category = "team" | ||
name = "operations" | ||
} | ||
tags { | ||
category = "sla" | ||
name = "gold" | ||
} | ||
|
||
} | ||
|
||
locals { | ||
vm_name = data.vsphere-virtualmachine.default.vm_name | ||
} | ||
|
||
source "null" "example" { | ||
communicator = "none" | ||
} | ||
|
||
build { | ||
sources = [ | ||
"source.null.example" | ||
] | ||
|
||
provisioner "shell-local" { | ||
inline = [ | ||
"echo vm_name: ${local.vm_name}", | ||
] | ||
} | ||
} | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package driver | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/url" | ||
|
||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common" | ||
"github.com/vmware/govmomi" | ||
"github.com/vmware/govmomi/find" | ||
"github.com/vmware/govmomi/object" | ||
"github.com/vmware/govmomi/vapi/rest" | ||
) | ||
|
||
type VCenterDriver struct { | ||
Ctx context.Context | ||
Client *govmomi.Client | ||
RestClient *rest.Client | ||
Finder *find.Finder | ||
Datacenter *object.Datacenter | ||
} | ||
|
||
func NewDriver(config common.ConnectConfig) (*VCenterDriver, error) { | ||
ctx := context.Background() | ||
|
||
vcenterUrl, err := url.Parse(fmt.Sprintf("https://%v/sdk", config.VCenterServer)) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse URL: %w", err) | ||
} | ||
vcenterUrl.User = url.UserPassword(config.Username, config.Password) | ||
|
||
client, err := govmomi.NewClient(ctx, vcenterUrl, true) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create govmomi Client: %w", err) | ||
} | ||
|
||
restClient := rest.NewClient(client.Client) | ||
err = restClient.Login(ctx, vcenterUrl.User) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to login to REST API endpoint: %w", err) | ||
} | ||
|
||
finder := find.NewFinder(client.Client, true) | ||
datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to find datacenter: %w", err) | ||
} | ||
finder.SetDatacenter(datacenter) | ||
|
||
return &VCenterDriver{ | ||
Ctx: ctx, | ||
Client: client, | ||
RestClient: restClient, | ||
Finder: finder, | ||
Datacenter: datacenter, | ||
}, nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package testing | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/vmware/govmomi/object" | ||
"github.com/vmware/govmomi/vapi/tags" | ||
) | ||
|
||
// MarkSimulatedVmAsTemplate powers off the virtual machine before converting it to a template (because the simulator | ||
// creates all virtual machines in an online state). | ||
func MarkSimulatedVmAsTemplate(ctx context.Context, vm *object.VirtualMachine) error { | ||
task, err := vm.PowerOff(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to issue powering off command to the machine: %w", err) | ||
} | ||
err = task.Wait(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to power off the machine: %w", err) | ||
} | ||
err = vm.MarkAsTemplate(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to mark virtual machine as a template: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
// FindOrCreateCategory tries to find category passed by name, creates category if not found and returns category ID. | ||
// Category will be created with "MULTIPLE" constraint. | ||
func FindOrCreateCategory(ctx context.Context, man *tags.Manager, catName string) (string, error) { | ||
categoryList, err := man.GetCategories(ctx) | ||
if err != nil { | ||
return "", fmt.Errorf("cannot return categories from cluster: %w", err) | ||
} | ||
for _, category := range categoryList { | ||
if category.Name == catName { | ||
return category.ID, nil | ||
} | ||
} | ||
newCategoryID, err := man.CreateCategory(ctx, &tags.Category{Name: catName, Cardinality: "MULTIPLE"}) | ||
if err != nil { | ||
return "", fmt.Errorf("cannot create category: %w", err) | ||
} | ||
return newCategoryID, nil | ||
} | ||
|
||
// FindOrCreateTag tries to find the tagName in category with catID, creates if not found and returns tag ID. | ||
func FindOrCreateTag(ctx context.Context, man *tags.Manager, catID string, tagName string) (string, error) { | ||
tagsInCategory, err := man.GetTagsForCategory(ctx, catID) | ||
if err != nil { | ||
return "", fmt.Errorf("cannot return tags for category: %w", err) | ||
} | ||
for _, tag := range tagsInCategory { | ||
if tag.Name == tagName { | ||
return tag.ID, nil | ||
} | ||
} | ||
newTagID, err := man.CreateTag(ctx, &tags.Tag{Name: tagName, CategoryID: catID}) | ||
if err != nil { | ||
return "", fmt.Errorf("cannot create tag: %w", err) | ||
} | ||
return newTagID, nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see we're introducing a common driver, does that mean that the builder's driver is to be moved to this package? I don't see anything to that effect in the PR, is that a later item?
At first glance, the code seems to be equivalent to the
NewDriver
function from thebuilder/vsphere/driver
package, so I assume this is meant to become one package eventually?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not an experienced developer and do not want to introduce potentially breaking changes to the main branch. So, I implemented a basic driver that exposes some
govmomi
functions required by my data source and its filters to process requests to the vSphere cluster. I have no intention of replacing the main driver from thebuilder
.