diff --git a/bare_metal_server.go b/bare_metal_server.go index 8ae73b8..91247f7 100644 --- a/bare_metal_server.go +++ b/bare_metal_server.go @@ -92,13 +92,14 @@ type BareMetalCreate struct { ActivationEmail *bool `json:"activation_email,omitempty"` Hostname string `json:"hostname,omitempty"` // Deprecated: Tag should no longer be used. Instead, use Tags. - Tag string `json:"tag,omitempty"` - ReservedIPv4 string `json:"reserved_ipv4,omitempty"` - PersistentPxe *bool `json:"persistent_pxe,omitempty"` - Tags []string `json:"tags"` - AttachVPC2 []string `json:"attach_vpc2,omitempty"` - DetachVPC2 []string `json:"detach_vpc2,omitempty"` - EnableVPC2 *bool `json:"enable_vpc2,omitempty"` + Tag string `json:"tag,omitempty"` + ReservedIPv4 string `json:"reserved_ipv4,omitempty"` + PersistentPxe *bool `json:"persistent_pxe,omitempty"` + Tags []string `json:"tags"` + AttachVPC2 []string `json:"attach_vpc2,omitempty"` + DetachVPC2 []string `json:"detach_vpc2,omitempty"` + EnableVPC2 *bool `json:"enable_vpc2,omitempty"` + AppVariables map[string]string `json:"app_variables,omitempty"` } // BareMetalUpdate represents the optional parameters that can be set when updating a Bare Metal server diff --git a/govultr.go b/govultr.go index 02eae48..f38943b 100644 --- a/govultr.go +++ b/govultr.go @@ -57,6 +57,7 @@ type Client struct { ISO ISOService Kubernetes KubernetesService LoadBalancer LoadBalancerService + Marketplace MarketplaceService // Deprecated: Network should no longer be used. Instead, use VPC. Network NetworkService ObjectStorage ObjectStorageService @@ -129,6 +130,7 @@ func NewClient(httpClient *http.Client) *Client { client.ISO = &ISOServiceHandler{client} client.Kubernetes = &KubernetesHandler{client} client.LoadBalancer = &LoadBalancerHandler{client} + client.Marketplace = &MarketplaceServiceHandler{client} client.Network = &NetworkServiceHandler{client} client.ObjectStorage = &ObjectStorageServiceHandler{client} client.OS = &OSServiceHandler{client} diff --git a/instance.go b/instance.go index 7b24f43..524d31b 100644 --- a/instance.go +++ b/instance.go @@ -273,17 +273,18 @@ type InstanceCreateReq struct { // Deprecated: EnablePrivateNetwork should no longer be used. Instead, use EnableVPC. EnablePrivateNetwork *bool `json:"enable_private_network,omitempty"` // Deprecated: AttachPrivateNetwork should no longer be used. Instead, use AttachVPC. - AttachPrivateNetwork []string `json:"attach_private_network,omitempty"` - EnableVPC *bool `json:"enable_vpc,omitempty"` - AttachVPC []string `json:"attach_vpc,omitempty"` - EnableVPC2 *bool `json:"enable_vpc2,omitempty"` - AttachVPC2 []string `json:"attach_vpc2,omitempty"` - SSHKeys []string `json:"sshkey_id,omitempty"` - Backups string `json:"backups,omitempty"` - DDOSProtection *bool `json:"ddos_protection,omitempty"` - UserData string `json:"user_data,omitempty"` - ReservedIPv4 string `json:"reserved_ipv4,omitempty"` - ActivationEmail *bool `json:"activation_email,omitempty"` + AttachPrivateNetwork []string `json:"attach_private_network,omitempty"` + EnableVPC *bool `json:"enable_vpc,omitempty"` + AttachVPC []string `json:"attach_vpc,omitempty"` + EnableVPC2 *bool `json:"enable_vpc2,omitempty"` + AttachVPC2 []string `json:"attach_vpc2,omitempty"` + SSHKeys []string `json:"sshkey_id,omitempty"` + Backups string `json:"backups,omitempty"` + DDOSProtection *bool `json:"ddos_protection,omitempty"` + UserData string `json:"user_data,omitempty"` + ReservedIPv4 string `json:"reserved_ipv4,omitempty"` + ActivationEmail *bool `json:"activation_email,omitempty"` + AppVariables map[string]string `json:"app_variables,omitempty"` } // InstanceUpdateReq struct used to update an instance. diff --git a/marketplace.go b/marketplace.go new file mode 100644 index 0000000..0d7b619 --- /dev/null +++ b/marketplace.go @@ -0,0 +1,50 @@ +package govultr + +import ( + "context" + "fmt" + "net/http" +) + +const marketplacePath = "/v2/marketplace" + +// MarketplaceService is the interface to interact with the Marketplace endpoints on the Vultr API +// Link: https://www.vultr.com/api/#tag/marketplace +type MarketplaceService interface { + ListAppVariables(ctx context.Context, imageID string) ([]MarketplaceAppVariable, *http.Response, error) +} + +// MarketplaceServiceHandler handles interaction with the server methods for the Vultr API +type MarketplaceServiceHandler struct { + client *Client +} + +// MarketplaceAppVariable represents a user-supplied variable for a Marketplace app +type MarketplaceAppVariable struct { + Name string `json:"name"` + Description string `json:"description"` + Required *bool `json:"required"` +} + +// marketplaceAppVariablesBase holds the API response for retrieving a list of user-supplied variables for a Marketplace app +type marketplaceAppVariablesBase struct { + MarketplaceAppVariables []MarketplaceAppVariable `json:"variables"` +} + +// ListAppVariables retrieves all user-supplied variables for a Marketplace app +func (d *MarketplaceServiceHandler) ListAppVariables(ctx context.Context, imageID string) ([]MarketplaceAppVariable, *http.Response, error) { //nolint:lll + uri := fmt.Sprintf("%s/apps/%s/variables", marketplacePath, imageID) + + req, err := d.client.NewRequest(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, nil, err + } + + marketplaceAppVariables := new(marketplaceAppVariablesBase) + resp, err := d.client.DoWithContext(ctx, req, marketplaceAppVariables) + if err != nil { + return nil, nil, err + } + + return marketplaceAppVariables.MarketplaceAppVariables, resp, nil +} diff --git a/marketplace_test.go b/marketplace_test.go new file mode 100644 index 0000000..87b9319 --- /dev/null +++ b/marketplace_test.go @@ -0,0 +1,53 @@ +package govultr + +import ( + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestMarketplaceServiceHandler_ListAppVariables(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc(fmt.Sprintf("/v2/marketplace/apps/%s/variables", "testimage"), func(writer http.ResponseWriter, request *http.Request) { + response := `{ + "variables": [ + { + "name": "some_required_variable", + "description": "This is an example of a required user-supplied variable for this Marketplace app.", + "required": true + }, + { + "name": "some_optional_variable", + "description": "This is an example of an optional user-supplied variable for this Marketplace app.", + "required": false + } + ] + }` + fmt.Fprint(writer, response) + }) + + variables, _, err := client.Marketplace.ListAppVariables(ctx, "testimage") + if err != nil { + t.Errorf("Marketplace.ListAppVariables returned %+v", err) + } + + expected := []MarketplaceAppVariable{ + { + Name: "some_required_variable", + Description: "This is an example of a required user-supplied variable for this Marketplace app.", + Required: BoolToBoolPtr(true), + }, + { + Name: "some_optional_variable", + Description: "This is an example of an optional user-supplied variable for this Marketplace app.", + Required: BoolToBoolPtr(false), + }, + } + + if !reflect.DeepEqual(variables, expected) { + t.Errorf("Marketplace.ListAppVariables returned %+v, expected %+v", variables, expected) + } +}