mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-30 02:31:10 +00:00
feat(node): add support for node config API (#1482)
* feat(node): implement CRUD API for proxmox node config Signed-off-by: Björn Brauer <zaubernerd@zaubernerd.de> * fix: add unit tests, fix UnmarshalJSON Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --------- Signed-off-by: Björn Brauer <zaubernerd@zaubernerd.de> Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
dd50873e2a
commit
3e025fd6c8
41
proxmox/nodes/config.go
Normal file
41
proxmox/nodes/config.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetConfig retrieves the config for a node.
|
||||||
|
func (c *Client) GetConfig(ctx context.Context) (*[]ConfigGetResponseData, error) {
|
||||||
|
resBody := &ConfigGetResponseBody{}
|
||||||
|
|
||||||
|
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("config"), nil, resBody)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error retrieving node config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resBody.Data == nil {
|
||||||
|
return nil, api.ErrNoDataObjectInResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
return resBody.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfig updates the config for a node.
|
||||||
|
func (c *Client) UpdateConfig(ctx context.Context, d *ConfigUpdateRequestBody) error {
|
||||||
|
err := c.DoRequest(ctx, http.MethodPost, c.ExpandPath("config"), d, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating node config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
240
proxmox/nodes/config_types.go
Normal file
240
proxmox/nodes/config_types.go
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConfigGetResponseBody contains the body from a config get response.
|
||||||
|
type ConfigGetResponseBody struct {
|
||||||
|
Data *[]ConfigGetResponseData `json:"data,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigGetResponseData contains the data from a config get response.
|
||||||
|
type ConfigGetResponseData struct {
|
||||||
|
// Node specific ACME settings.
|
||||||
|
ACME *ACMEConfig `json:"acme,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain0 *ACMEDomainConfig `json:"acmedomain0,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain1 *ACMEDomainConfig `json:"acmedomain1,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain2 *ACMEDomainConfig `json:"acmedomain2,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain3 *ACMEDomainConfig `json:"acmedomain3,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain4 *ACMEDomainConfig `json:"acmedomain4,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain5 *ACMEDomainConfig `json:"acmedomain5,omitempty"`
|
||||||
|
// Description for the Node. Shown in the web-interface node notes panel. This is saved as comment inside the configuration file.
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.
|
||||||
|
Digest *string `json:"digest,omitempty"`
|
||||||
|
// Initial delay in seconds, before starting all the Virtual Guests with on-boot enabled.
|
||||||
|
StartAllOnbootDelay *int `json:"startall-onboot-delay,omitempty"`
|
||||||
|
// Node specific wake on LAN settings.
|
||||||
|
WakeOnLan *WakeOnLandConfig `json:"wakeonlan,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigUpdateRequestBody contains the body for a config update request.
|
||||||
|
type ConfigUpdateRequestBody struct {
|
||||||
|
// Node specific ACME settings.
|
||||||
|
ACME *ACMEConfig `json:"acme,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain0 *ACMEDomainConfig `json:"acmedomain0,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain1 *ACMEDomainConfig `json:"acmedomain1,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain2 *ACMEDomainConfig `json:"acmedomain2,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain3 *ACMEDomainConfig `json:"acmedomain3,omitempty"`
|
||||||
|
// ACME domain and validation plugin
|
||||||
|
ACMEDomain4 *ACMEDomainConfig `json:"acmedomain4,omitempty"`
|
||||||
|
Delete *string `json:"delete,omitempty"`
|
||||||
|
// Description for the Node. Shown in the web-interface node notes panel. This is saved as comment inside the configuration file.
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.
|
||||||
|
Digest *string `json:"digest,omitempty"`
|
||||||
|
// Initial delay in seconds, before starting all the Virtual Guests with on-boot enabled.
|
||||||
|
StartAllOnbootDelay *int `json:"startall-onboot-delay,omitempty"`
|
||||||
|
// Node specific wake on LAN settings.
|
||||||
|
WakeOnLan *WakeOnLandConfig `json:"wakeonlan,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACMEConfig contains the ACME account / domains configuration that use the "standalone" plugin (http challenge).
|
||||||
|
type ACMEConfig struct {
|
||||||
|
// account name
|
||||||
|
Account *string
|
||||||
|
// domains
|
||||||
|
Domains []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals a ACMEConfig struct from JSON.
|
||||||
|
func (a *ACMEConfig) UnmarshalJSON(b []byte) error {
|
||||||
|
config := ACMEConfig{}
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(s, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
kv := strings.Split(part, "=")
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("invalid key-value pair: %s", part)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kv[0] {
|
||||||
|
case "account":
|
||||||
|
config.Account = &kv[1]
|
||||||
|
case "domains":
|
||||||
|
config.Domains = strings.Split(kv[1], ";")
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown key: %s", kv[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*a = config
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeValues encodes a ACMEConfig struct into a string.
|
||||||
|
func (a *ACMEConfig) EncodeValues(key string, v *url.Values) error {
|
||||||
|
value := ""
|
||||||
|
if a.Account != nil {
|
||||||
|
value = fmt.Sprintf("account=%s", *a.Account)
|
||||||
|
}
|
||||||
|
|
||||||
|
value = fmt.Sprintf("%s,%s", value, strings.Join(a.Domains, ";"))
|
||||||
|
v.Add(key, value)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACMEDomainConfig contains the ACME domain configuration for domains using the dns challenge plugin.
|
||||||
|
type ACMEDomainConfig struct {
|
||||||
|
// domain name
|
||||||
|
Domain string
|
||||||
|
// alias for the domain
|
||||||
|
Alias *string
|
||||||
|
// name of the plugin configuration
|
||||||
|
Plugin *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals a ACMEDomainConfig struct from JSON.
|
||||||
|
func (a *ACMEDomainConfig) UnmarshalJSON(b []byte) error {
|
||||||
|
config := ACMEDomainConfig{}
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(s, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
kv := strings.Split(part, "=")
|
||||||
|
if len(kv) == 1 {
|
||||||
|
config.Domain = kv[0]
|
||||||
|
} else {
|
||||||
|
switch kv[0] {
|
||||||
|
case "domain":
|
||||||
|
config.Domain = kv[1]
|
||||||
|
case "alias":
|
||||||
|
config.Alias = &kv[1]
|
||||||
|
case "plugin":
|
||||||
|
config.Plugin = &kv[1]
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown key: %s", kv[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*a = config
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeValues encodes a ACMEDomainConfig struct into a string.
|
||||||
|
func (a *ACMEDomainConfig) EncodeValues(key string, v *url.Values) error {
|
||||||
|
value := a.Domain
|
||||||
|
if a.Alias != nil {
|
||||||
|
value = fmt.Sprintf("%s,alias=%s", value, *a.Alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Plugin != nil {
|
||||||
|
value = fmt.Sprintf("%s,plugin=%s", value, *a.Plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Add(key, value)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WakeOnLandConfig contains the wake on LAN configuration.
|
||||||
|
type WakeOnLandConfig struct {
|
||||||
|
// MAC address
|
||||||
|
MACAddress string
|
||||||
|
// bind interface
|
||||||
|
BindInterface *string
|
||||||
|
// IPv4 broadcast address
|
||||||
|
BroadcastAddress *string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals a WakeOnLandConfig struct from JSON.
|
||||||
|
func (a *WakeOnLandConfig) UnmarshalJSON(b []byte) error {
|
||||||
|
config := WakeOnLandConfig{}
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling json: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(s, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
kv := strings.Split(part, "=")
|
||||||
|
if len(kv) == 1 {
|
||||||
|
config.MACAddress = kv[0]
|
||||||
|
} else {
|
||||||
|
switch kv[0] {
|
||||||
|
case "mac":
|
||||||
|
config.MACAddress = kv[1]
|
||||||
|
case "bind-interface":
|
||||||
|
config.BindInterface = &kv[1]
|
||||||
|
case "broadcast-address":
|
||||||
|
config.BroadcastAddress = &kv[1]
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown key: %s", kv[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*a = config
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeValues encodes a WakeOnLandConfig struct into a string.
|
||||||
|
func (a *WakeOnLandConfig) EncodeValues(key string, v *url.Values) error {
|
||||||
|
value := a.MACAddress
|
||||||
|
if a.BindInterface != nil {
|
||||||
|
value = fmt.Sprintf("%s,bind-interface=%s", value, *a.BindInterface)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.BroadcastAddress != nil {
|
||||||
|
value = fmt.Sprintf("%s,broadcast-address=%s", value, *a.BroadcastAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Add(key, value)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
409
proxmox/nodes/config_types_test.go
Normal file
409
proxmox/nodes/config_types_test.go
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nodes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmox/helpers/ptr"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestACMEConfig_UnmarshalJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config ACMEConfig
|
||||||
|
str string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "account only",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: ptr.Ptr("foo"),
|
||||||
|
Domains: nil,
|
||||||
|
},
|
||||||
|
str: `"account=foo"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account and domains",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: ptr.Ptr("foo"),
|
||||||
|
Domains: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
str: `"account=foo,domains=bar;baz"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domains only",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: nil,
|
||||||
|
Domains: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
str: `"domains=bar;baz"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.UnmarshalJSON([]byte(tt.str)); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACMEConfig_EncodeValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
v *url.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config ACMEConfig
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "account only",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: ptr.Ptr("foo"),
|
||||||
|
Domains: nil,
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"account": {"foo"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "account and domains",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: ptr.Ptr("foo"),
|
||||||
|
Domains: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"account": {"foo"},
|
||||||
|
"domains": {"bar;baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domains only",
|
||||||
|
config: ACMEConfig{
|
||||||
|
Account: nil,
|
||||||
|
Domains: []string{"bar", "baz"},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"domains": {"bar;baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.EncodeValues(tt.args.key, tt.args.v); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("EncodeValues() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACMEDomainConfig_UnmarshalJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config ACMEDomainConfig
|
||||||
|
str string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "domain only",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
},
|
||||||
|
str: `"foo"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain only with key",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
},
|
||||||
|
str: `"domain=foo"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain and alias",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Alias: ptr.Ptr("bar"),
|
||||||
|
},
|
||||||
|
str: `"domain=foo,alias=bar"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain and plugin",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Plugin: ptr.Ptr("bar"),
|
||||||
|
},
|
||||||
|
str: `"domain=foo,plugin=bar"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain, alias, and plugin",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Alias: ptr.Ptr("bar"),
|
||||||
|
Plugin: ptr.Ptr("baz"),
|
||||||
|
},
|
||||||
|
str: `"domain=foo,alias=bar,plugin=baz"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.UnmarshalJSON([]byte(tt.str)); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACMEDomainConfig_EncodeValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
v *url.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config ACMEDomainConfig
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "domain only",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"domain": {"foo"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain and alias",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Alias: ptr.Ptr("bar"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"domain": {"foo"},
|
||||||
|
"alias": {"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain and plugin",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Plugin: ptr.Ptr("bar"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"domain": {"foo"},
|
||||||
|
"plugin": {"bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "domain, alias, and plugin",
|
||||||
|
config: ACMEDomainConfig{
|
||||||
|
Domain: "foo",
|
||||||
|
Alias: ptr.Ptr("bar"),
|
||||||
|
Plugin: ptr.Ptr("baz"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"acme",
|
||||||
|
&url.Values{
|
||||||
|
"domain": {"foo"},
|
||||||
|
"alias": {"bar"},
|
||||||
|
"plugin": {"baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.EncodeValues(tt.args.key, tt.args.v); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("EncodeValues() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWakeOnLandConfig_UnmarshalJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config WakeOnLandConfig
|
||||||
|
str string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "mac only",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
},
|
||||||
|
str: `"00:11:22:33:44:55"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac only with key",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
},
|
||||||
|
str: `"mac=00:11:22:33:44:55"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac and bind interface",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BindInterface: ptr.Ptr("eth0"),
|
||||||
|
},
|
||||||
|
str: `"mac=00:11:22:33:44:55,bind-interface=eth0"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac and broadcast address",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BroadcastAddress: ptr.Ptr("192.168.0.155"),
|
||||||
|
},
|
||||||
|
str: `"mac=00:11:22:33:44:55,broadcast-address=192.168.0.255"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac, bind interface, and broadcast address",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BindInterface: ptr.Ptr("eth0"),
|
||||||
|
BroadcastAddress: ptr.Ptr("192.168.0.255"),
|
||||||
|
},
|
||||||
|
str: `"mac=00:11:22:33:44:55,bind-interface=eth0,broadcast-address=192.168.0.255"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.UnmarshalJSON([]byte(tt.str)); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWakeOnLandConfig_EncodeValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
v *url.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config WakeOnLandConfig
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "mac only",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"wakeonlan",
|
||||||
|
&url.Values{
|
||||||
|
"mac": {"00:11:22:33:44:55"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac and bind interface",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BindInterface: ptr.Ptr("eth0"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"wakeonlan",
|
||||||
|
&url.Values{
|
||||||
|
"mac": {"00:11:22:33:44:55"},
|
||||||
|
"bind-interface": {"eth0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac and broadcast address",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BroadcastAddress: ptr.Ptr("192.168.0.255"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"wakeonlan",
|
||||||
|
&url.Values{
|
||||||
|
"mac": {"00:11:22:33:44:55"},
|
||||||
|
"broadcast-address": {"192.168.0.255"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mac, bind interface, and broadcast address",
|
||||||
|
config: WakeOnLandConfig{
|
||||||
|
MACAddress: "00:11:22:33:44:55",
|
||||||
|
BindInterface: ptr.Ptr("eth0"),
|
||||||
|
BroadcastAddress: ptr.Ptr("10.255.255.255"),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
"wakeonlan",
|
||||||
|
&url.Values{
|
||||||
|
"mac": {"00:11:22:33:44:55"},
|
||||||
|
"bind-interface": {"eth0"},
|
||||||
|
"broadcast-address": {"10.255.255.255"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if err := tt.config.EncodeValues(tt.args.key, tt.args.v); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("EncodeValues() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user