config: fix failing v1alpha2 -> v1alpha3 migration (#799)

- add validation as extra step after migration
- add missing json struct tags to new v1alpha3 config fields
- add unit tests
- add missing `omitempty` tags to configs to avoid (un-)marshalling issues
- drop `string` type for `time.Duration` type field in JSON Schema (doesn't work properly sometimes due to broken handling of time.Duration as per https://github.com/golang/go/issues/10275)
pull/808/head
Thorsten Klein 3 years ago committed by GitHub
parent 12180ffdd5
commit 594e3ced3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      pkg/config/jsonschema.go
  2. 16
      pkg/config/migrate.go
  3. 76
      pkg/config/migrate_test.go
  4. 51
      pkg/config/test_assets/config_test_simple_migration_v1alpha2.yaml
  5. 55
      pkg/config/test_assets/config_test_simple_migration_v1alpha3.yaml
  6. 74
      pkg/config/v1alpha2/types.go
  7. 1
      pkg/config/v1alpha3/schema.json
  8. 110
      pkg/config/v1alpha3/types.go
  9. 1
      tests/assets/config_test_simple.yaml
  10. 1
      tests/assets/config_test_simple_migration_v1alpha3.yaml

@ -53,7 +53,7 @@ func ValidateSchemaFile(filepath string, schema []byte) error {
} }
// ValidateSchema validates a YAML construct (non-struct representation) against a JSON Schema // ValidateSchema validates a YAML construct (non-struct representation) against a JSON Schema
func ValidateSchema(content map[string]interface{}, schemaJSON []byte) error { func ValidateSchema(content interface{}, schemaJSON []byte) error {
contentYaml, err := yaml.Marshal(content) contentYaml, err := yaml.Marshal(content)
if err != nil { if err != nil {
@ -64,6 +64,11 @@ func ValidateSchema(content map[string]interface{}, schemaJSON []byte) error {
return err return err
} }
return ValidateSchemaJSON(contentJSON, schemaJSON)
}
func ValidateSchemaJSON(contentJSON []byte, schemaJSON []byte) error {
if bytes.Equal(contentJSON, []byte("null")) { if bytes.Equal(contentJSON, []byte("null")) {
contentJSON = []byte("{}") // non-json yaml struct contentJSON = []byte("{}") // non-json yaml struct
} }

@ -35,6 +35,20 @@ func Migrate(config types.Config, targetVersion string) (types.Config, error) {
return nil, fmt.Errorf("no migration possible from '%s' to '%s'", config.GetAPIVersion(), targetVersion) return nil, fmt.Errorf("no migration possible from '%s' to '%s'", config.GetAPIVersion(), targetVersion)
} }
return migration(config) cfg, err := migration(config)
if err != nil {
return nil, fmt.Errorf("error migrating config: %w", err)
}
schema, err := GetSchemaByVersion(cfg.GetAPIVersion())
if err != nil {
return nil, fmt.Errorf("error getting schema for config apiVersion %s: %w", cfg.GetAPIVersion(), err)
}
if err := ValidateSchema(cfg, schema); err != nil {
return config, fmt.Errorf("post-migrate schema validation failed: %w", err)
}
return cfg, err
} }

@ -0,0 +1,76 @@
/*
Copyright © 2020-2021 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package config
import (
"testing"
"github.com/go-test/deep"
l "github.com/rancher/k3d/v5/pkg/logger"
"github.com/spf13/viper"
)
func TestMigrateV1Alpha2ToV1Alpha3(t *testing.T) {
actualPath := "test_assets/config_test_simple_migration_v1alpha2.yaml"
expectedPath := "test_assets/config_test_simple_migration_v1alpha3.yaml"
actualViper := viper.New()
expectedViper := viper.New()
actualViper.SetConfigType("yaml")
expectedViper.SetConfigType("yaml")
actualViper.SetConfigFile(actualPath)
expectedViper.SetConfigFile(expectedPath)
if err := actualViper.ReadInConfig(); err != nil {
t.Fatal(err)
}
if err := expectedViper.ReadInConfig(); err != nil {
t.Fatal(err)
}
actualCfg, err := FromViper(actualViper)
if err != nil {
t.Fatal(err)
}
if actualCfg.GetAPIVersion() != DefaultConfigApiVersion {
actualCfg, err = Migrate(actualCfg, DefaultConfigApiVersion)
if err != nil {
l.Log().Fatalln(err)
}
}
expectedCfg, err := FromViper(expectedViper)
if err != nil {
t.Fatal(err)
}
if diff := deep.Equal(actualCfg, expectedCfg); diff != nil {
t.Fatalf("Actual\n%#v\ndoes not match expected\n%+v\nDiff:\n%#v", actualCfg, expectedCfg, diff)
}
}

@ -0,0 +1,51 @@
apiVersion: k3d.io/v1alpha2
kind: Simple
name: test
servers: 3
agents: 2
kubeAPI:
hostIP: "0.0.0.0"
hostPort: "6446"
#image: rancher/k3s:latest
volumes:
- volume: /my/path:/some/path
nodeFilters:
- all
ports:
- port: 80:80
nodeFilters:
- loadbalancer
- port: 0.0.0.0:443:443
nodeFilters:
- loadbalancer
env:
- envVar: bar=baz,bob
nodeFilters:
- all
labels:
- label: foo=bar
nodeFilters:
- server[0]
- loadbalancer
registries:
create: true
use: []
config: |
mirrors:
"my.company.registry":
endpoint:
- http://my.company.registry:5000
options:
k3d:
wait: true
timeout: "360s" # should be pretty high for multi-server clusters to allow for a proper startup routine
disableLoadbalancer: false
disableImageVolume: false
k3s:
extraServerArgs:
- --tls-san=127.0.0.1
extraAgentArgs: []
kubeconfig:
updateDefaultKubeconfig: true
switchCurrentContext: true

@ -0,0 +1,55 @@
apiVersion: k3d.io/v1alpha3
kind: Simple
name: test
servers: 3
agents: 2
kubeAPI:
hostIP: "0.0.0.0"
hostPort: "6446"
#image: rancher/k3s:latest
volumes:
- volume: /my/path:/some/path
nodeFilters:
- all
ports:
- port: 80:80
nodeFilters:
- loadbalancer
- port: 0.0.0.0:443:443
nodeFilters:
- loadbalancer
env:
- envVar: bar=baz,bob
nodeFilters:
- all
registries:
create:
name: k3d-test-registry
host: "0.0.0.0"
hostPort: random
config: |
mirrors:
"my.company.registry":
endpoint:
- http://my.company.registry:5000
options:
k3d:
wait: true
timeout: "360s" # should be pretty high for multi-server clusters to allow for a proper startup routine
disableLoadbalancer: false
disableImageVolume: false
k3s:
extraArgs:
- arg: --tls-san=127.0.0.1
nodeFilters:
- server:*
kubeconfig:
updateDefaultKubeconfig: true
switchCurrentContext: true
runtime:
labels:
- label: foo=bar
nodeFilters:
- server:0
- loadbalancer

@ -57,23 +57,23 @@ var DefaultConfig = fmt.Sprintf(
) )
type VolumeWithNodeFilters struct { type VolumeWithNodeFilters struct {
Volume string `mapstructure:"volume" yaml:"volume" json:"volume,omitempty"` Volume string `mapstructure:"volume" yaml:"volume,omitempty" json:"volume,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type PortWithNodeFilters struct { type PortWithNodeFilters struct {
Port string `mapstructure:"port" yaml:"port" json:"port,omitempty"` Port string `mapstructure:"port" yaml:"port,omitempty" json:"port,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type LabelWithNodeFilters struct { type LabelWithNodeFilters struct {
Label string `mapstructure:"label" yaml:"label" json:"label,omitempty"` Label string `mapstructure:"label" yaml:"label,omitempty" json:"label,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type EnvVarWithNodeFilters struct { type EnvVarWithNodeFilters struct {
EnvVar string `mapstructure:"envVar" yaml:"envVar" json:"envVar,omitempty"` EnvVar string `mapstructure:"envVar" yaml:"envVar,omitempty" json:"envVar,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
// SimpleConfigOptionsKubeconfig describes the set of options referring to the kubeconfig during cluster creation. // SimpleConfigOptionsKubeconfig describes the set of options referring to the kubeconfig during cluster creation.
@ -83,49 +83,49 @@ type SimpleConfigOptionsKubeconfig struct {
} }
type SimpleConfigOptions struct { type SimpleConfigOptions struct {
K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d"` K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d" json:"k3d"`
K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s"` K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s" json:"k3s"`
KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig"` KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig" json:"kubeconfig"`
Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime"` Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime" json:"runtime"`
} }
type SimpleConfigOptionsRuntime struct { type SimpleConfigOptionsRuntime struct {
GPURequest string `mapstructure:"gpuRequest" yaml:"gpuRequest"` GPURequest string `mapstructure:"gpuRequest,omitempty" yaml:"gpuRequest,omitempty" json:"gpuRequest,omitempty"`
ServersMemory string `mapstructure:"serversMemory" yaml:"serversMemory"` ServersMemory string `mapstructure:"serversMemory,omitempty" yaml:"serversMemory,omitempty" json:"serversMemory,omitempty"`
AgentsMemory string `mapstructure:"agentsMemory" yaml:"agentsMemory"` AgentsMemory string `mapstructure:"agentsMemory,omitempty" yaml:"agentsMemory,omitempty" json:"agentsMemory,omitempty"`
} }
type SimpleConfigOptionsK3d struct { type SimpleConfigOptionsK3d struct {
Wait bool `mapstructure:"wait" yaml:"wait"` Wait bool `mapstructure:"wait" yaml:"wait" json:"wait"`
Timeout time.Duration `mapstructure:"timeout" yaml:"timeout"` Timeout time.Duration `mapstructure:"timeout" yaml:"timeout,omitempty" json:"timeout,omitempty"`
DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer"` DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer" json:"disableLoadbalancer"`
DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume"` DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume" json:"disableImageVolume"`
NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback"` NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback" json:"disableRollback"`
PrepDisableHostIPInjection bool `mapstructure:"disableHostIPInjection" yaml:"disableHostIPInjection"` PrepDisableHostIPInjection bool `mapstructure:"disableHostIPInjection" json:"disableHostIPInjection"`
NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty"` NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty" json:"nodeHookActions,omitempty"`
} }
type SimpleConfigOptionsK3s struct { type SimpleConfigOptionsK3s struct {
ExtraServerArgs []string `mapstructure:"extraServerArgs" yaml:"extraServerArgs"` ExtraServerArgs []string `mapstructure:"extraServerArgs,omitempty" yaml:"extraServerArgs,omitempty" json:"extraServerArgs,omitempty"`
ExtraAgentArgs []string `mapstructure:"extraAgentArgs" yaml:"extraAgentArgs"` ExtraAgentArgs []string `mapstructure:"extraAgentArgs,omitempty" yaml:"extraAgentArgs,omitempty" json:"extraAgentArgs,omitempty"`
} }
// SimpleConfig describes the toplevel k3d configuration file. // SimpleConfig describes the toplevel k3d configuration file.
type SimpleConfig struct { type SimpleConfig struct {
configtypes.TypeMeta `mapstructure:",squash" yaml:",inline"` configtypes.TypeMeta `mapstructure:",squash" yaml:",inline"`
Name string `mapstructure:"name" yaml:"name" json:"name,omitempty"` Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image" json:"image,omitempty"` Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network" json:"network,omitempty"` Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"`
Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels" json:"labels,omitempty"` Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels,omitempty" json:"labels,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"`
Registries struct { Registries struct {
Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"` Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"`
Create bool `mapstructure:"create" yaml:"create,omitempty" json:"create,omitempty"` Create bool `mapstructure:"create" yaml:"create,omitempty" json:"create,omitempty"`

@ -119,7 +119,6 @@
"default": true "default": true
}, },
"timeout": { "timeout": {
"type": "string",
"examples": [ "examples": [
"60s", "60s",
"1m", "1m",

@ -57,34 +57,34 @@ var DefaultConfig = fmt.Sprintf(
) )
type VolumeWithNodeFilters struct { type VolumeWithNodeFilters struct {
Volume string `mapstructure:"volume" yaml:"volume" json:"volume,omitempty"` Volume string `mapstructure:"volume" yaml:"volume,omitempty" json:"volume,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type PortWithNodeFilters struct { type PortWithNodeFilters struct {
Port string `mapstructure:"port" yaml:"port" json:"port,omitempty"` Port string `mapstructure:"port" yaml:"port,omitempty" json:"port,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type LabelWithNodeFilters struct { type LabelWithNodeFilters struct {
Label string `mapstructure:"label" yaml:"label" json:"label,omitempty"` Label string `mapstructure:"label" yaml:"label,omitempty" json:"label,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type EnvVarWithNodeFilters struct { type EnvVarWithNodeFilters struct {
EnvVar string `mapstructure:"envVar" yaml:"envVar" json:"envVar,omitempty"` EnvVar string `mapstructure:"envVar" yaml:"envVar,omitempty" json:"envVar,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type K3sArgWithNodeFilters struct { type K3sArgWithNodeFilters struct {
Arg string `mapstructure:"arg" yaml:"arg" json:"arg,omitempty"` Arg string `mapstructure:"arg" yaml:"arg,omitempty" json:"arg,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"`
} }
type SimpleConfigRegistryCreateConfig struct { type SimpleConfigRegistryCreateConfig struct {
Name string `mapstructure:"name" yaml:"name" json:"name"` Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"`
Host string `mapstructure:"host" yaml:"host" json:"host"` Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort" json:"hostPort"` HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"`
} }
// SimpleConfigOptionsKubeconfig describes the set of options referring to the kubeconfig during cluster creation. // SimpleConfigOptionsKubeconfig describes the set of options referring to the kubeconfig during cluster creation.
@ -94,36 +94,36 @@ type SimpleConfigOptionsKubeconfig struct {
} }
type SimpleConfigOptions struct { type SimpleConfigOptions struct {
K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d"` K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d" json:"k3d"`
K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s"` K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s" json:"k3s"`
KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig"` KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig" json:"kubeconfig"`
Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime"` Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime" json:"runtime"`
} }
type SimpleConfigOptionsRuntime struct { type SimpleConfigOptionsRuntime struct {
GPURequest string `mapstructure:"gpuRequest" yaml:"gpuRequest"` GPURequest string `mapstructure:"gpuRequest" yaml:"gpuRequest,omitempty" json:"gpuRequest,omitempty"`
ServersMemory string `mapstructure:"serversMemory" yaml:"serversMemory"` ServersMemory string `mapstructure:"serversMemory" yaml:"serversMemory,omitempty" json:"serversMemory,omitempty"`
AgentsMemory string `mapstructure:"agentsMemory" yaml:"agentsMemory"` AgentsMemory string `mapstructure:"agentsMemory" yaml:"agentsMemory,omitempty" json:"agentsMemory,omitempty"`
Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels"` Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels,omitempty" json:"labels,omitempty"`
} }
type SimpleConfigOptionsK3d struct { type SimpleConfigOptionsK3d struct {
Wait bool `mapstructure:"wait" yaml:"wait"` Wait bool `mapstructure:"wait" yaml:"wait" json:"wait"`
Timeout time.Duration `mapstructure:"timeout" yaml:"timeout"` Timeout time.Duration `mapstructure:"timeout" yaml:"timeout,omitempty" json:"timeout,omitempty"`
DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer"` DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer" json:"disableLoadbalancer"`
DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume"` DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume" json:"disableImageVolume"`
NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback"` NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback" json:"disableRollback"`
NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty"` NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty" json:"nodeHookActions,omitempty"`
Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" yaml:"loadbalancer,omitempty"` Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" yaml:"loadbalancer,omitempty" json:"loadbalancer,omitempty"`
} }
type SimpleConfigOptionsK3dLoadbalancer struct { type SimpleConfigOptionsK3dLoadbalancer struct {
ConfigOverrides []string `mapstructure:"configOverrides" yaml:"configOverrides,omitempty"` ConfigOverrides []string `mapstructure:"configOverrides" yaml:"configOverrides,omitempty" json:"configOverrides,omitempty"`
} }
type SimpleConfigOptionsK3s struct { type SimpleConfigOptionsK3s struct {
ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" yaml:"extraArgs"` ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" yaml:"extraArgs,omitempty" json:"extraArgs,omitempty"`
NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" yaml:"nodeLabels"` NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" yaml:"nodeLabels,omitempty" json:"nodeLabels,omitempty"`
} }
type SimpleConfigRegistries struct { type SimpleConfigRegistries struct {
@ -141,35 +141,35 @@ type SimpleConfigRegistriesIntermediateV1alpha2 struct {
// SimpleConfig describes the toplevel k3d configuration file. // SimpleConfig describes the toplevel k3d configuration file.
type SimpleConfig struct { type SimpleConfig struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash" yaml:",inline"`
Name string `mapstructure:"name" yaml:"name" json:"name,omitempty"` Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image" json:"image,omitempty"` Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network" json:"network,omitempty"` Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"`
Registries SimpleConfigRegistries `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` Registries SimpleConfigRegistries `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"`
} }
type SimpleConfigIntermediateV1alpha2 struct { type SimpleConfigIntermediateV1alpha2 struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash" yaml:",inline"`
Name string `mapstructure:"name" yaml:"name" json:"name,omitempty"` Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image" json:"image,omitempty"` Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network" json:"network,omitempty"` Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"`
Registries SimpleConfigRegistriesIntermediateV1alpha2 `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` Registries SimpleConfigRegistriesIntermediateV1alpha2 `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"`
} }

@ -31,7 +31,6 @@ registries:
"my.company.registry": "my.company.registry":
endpoint: endpoint:
- http://my.company.registry:5000 - http://my.company.registry:5000
options: options:
k3d: k3d:
wait: true wait: true

@ -27,7 +27,6 @@ registries:
name: k3d-test-registry name: k3d-test-registry
host: "0.0.0.0" host: "0.0.0.0"
hostPort: random hostPort: random
use: []
config: | config: |
mirrors: mirrors:
"my.company.registry": "my.company.registry":

Loading…
Cancel
Save