fix: print consistent json/yaml output (#1094)

pull/1103/head
Sunghoon Kang 2 years ago committed by GitHub
parent a4ae100932
commit 24bb5f4493
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      cmd/cluster/clusterCreate.go
  2. 18
      cmd/cluster/clusterList.go
  3. 7
      cmd/config/configMigrate.go
  4. 5
      cmd/debug/debug.go
  5. 8
      cmd/root.go
  6. 7
      cmd/util/config/config.go
  7. 5
      cmd/util/listings.go
  8. 18
      pkg/client/cluster.go
  9. 5
      pkg/client/loadbalancer.go
  10. 13
      pkg/client/node.go
  11. 5
      pkg/client/ports.go
  12. 17
      pkg/client/registry.go
  13. 8
      pkg/config/transform.go
  14. 6
      pkg/config/types/types.go
  15. 104
      pkg/config/v1alpha2/types.go
  16. 150
      pkg/config/v1alpha3/types.go
  17. 128
      pkg/config/v1alpha4/types.go
  18. 18
      pkg/runtimes/types/types.go
  19. 28
      pkg/types/k3s/registry.go
  20. 8
      pkg/types/k8s/registry.go
  21. 12
      pkg/types/loadbalancer.go
  22. 30
      pkg/types/registry.go
  23. 125
      pkg/types/types.go
  24. 27
      pkg/util/util.go
  25. 57
      pkg/util/yaml.go
  26. 94
      pkg/util/yaml_test.go

@ -32,11 +32,10 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"inet.af/netaddr"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"gopkg.in/yaml.v2" "inet.af/netaddr"
"sigs.k8s.io/yaml"
cliutil "github.com/k3d-io/k3d/v5/cmd/util" cliutil "github.com/k3d-io/k3d/v5/cmd/util"
cliconfig "github.com/k3d-io/k3d/v5/cmd/util/config" cliconfig "github.com/k3d-io/k3d/v5/cmd/util/config"

@ -28,15 +28,15 @@ import (
"os" "os"
"strings" "strings"
"github.com/liggitt/tabwriter"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/cmd/util" "github.com/k3d-io/k3d/v5/cmd/util"
k3cluster "github.com/k3d-io/k3d/v5/pkg/client" k3cluster "github.com/k3d-io/k3d/v5/pkg/client"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"github.com/liggitt/tabwriter"
) )
// TODO : deal with --all flag to manage differentiate started cluster and stopped cluster like `docker ps` and `docker ps -a` // TODO : deal with --all flag to manage differentiate started cluster and stopped cluster like `docker ps` and `docker ps -a`
@ -103,11 +103,11 @@ func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) {
// the output details printed when we dump JSON/YAML // the output details printed when we dump JSON/YAML
type jsonOutput struct { type jsonOutput struct {
k3d.Cluster k3d.Cluster
ServersRunning int `yaml:"servers_running" json:"serversRunning"` ServersRunning int `json:"serversRunning"`
ServersCount int `yaml:"servers_count" json:"serversCount"` ServersCount int `json:"serversCount"`
AgentsRunning int `yaml:"agents_running" json:"agentsRunning"` AgentsRunning int `json:"agentsRunning"`
AgentsCount int `yaml:"agents_count" json:"agentsCount"` AgentsCount int `json:"agentsCount"`
LoadBalancer bool `yaml:"has_lb,omitempty" json:"hasLoadbalancer,omitempty"` LoadBalancer bool `json:"hasLoadbalancer,omitempty"`
} }
jsonOutputEntries := []jsonOutput{} jsonOutputEntries := []jsonOutput{}

@ -25,11 +25,12 @@ import (
"os" "os"
"strings" "strings"
"github.com/k3d-io/k3d/v5/pkg/config"
l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"gopkg.in/yaml.v2" "sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/pkg/config"
l "github.com/k3d-io/k3d/v5/pkg/logger"
) )
// NewCmdConfigMigrate returns a new cobra command // NewCmdConfigMigrate returns a new cobra command

@ -24,13 +24,14 @@ package debug
import ( import (
"fmt" "fmt"
"github.com/spf13/cobra"
"sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/cmd/util" "github.com/k3d-io/k3d/v5/cmd/util"
"github.com/k3d-io/k3d/v5/pkg/client" "github.com/k3d-io/k3d/v5/pkg/client"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
"github.com/k3d-io/k3d/v5/pkg/types" "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
) )
// NewCmdDebug returns a new cobra command // NewCmdDebug returns a new cobra command

@ -33,8 +33,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/writer"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"github.com/k3d-io/k3d/v5/cmd/cluster" "github.com/k3d-io/k3d/v5/cmd/cluster"
cfg "github.com/k3d-io/k3d/v5/cmd/config" cfg "github.com/k3d-io/k3d/v5/cmd/config"
@ -46,9 +47,8 @@ import (
cliutil "github.com/k3d-io/k3d/v5/cmd/util" cliutil "github.com/k3d-io/k3d/v5/cmd/util"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
"github.com/k3d-io/k3d/v5/pkg/util"
"github.com/k3d-io/k3d/v5/version" "github.com/k3d-io/k3d/v5/version"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/writer"
) )
// RootFlags describes a struct that holds flags that can be set on root level of the command // RootFlags describes a struct that holds flags that can be set on root level of the command
@ -109,7 +109,7 @@ All Nodes of a k3d cluster are part of the same docker network.`,
if err != nil { if err != nil {
l.Log().Fatalln(err) l.Log().Fatalln(err)
} }
err = yaml.NewEncoder(os.Stdout).Encode(info) err = util.NewYAMLEncoder(os.Stdout).Encode(info)
if err != nil { if err != nil {
l.Log().Fatalln(err) l.Log().Fatalln(err)
} }

@ -27,11 +27,12 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/k3d-io/k3d/v5/pkg/config"
l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper" "github.com/spf13/viper"
"gopkg.in/yaml.v2" "sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/pkg/config"
l "github.com/k3d-io/k3d/v5/pkg/logger"
) )
func InitViperWithConfigFile(cfgViper *viper.Viper, configFile string) error { func InitViperWithConfigFile(cfgViper *viper.Viper, configFile string) error {

@ -28,10 +28,11 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/liggitt/tabwriter"
"sigs.k8s.io/yaml"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/liggitt/tabwriter"
"gopkg.in/yaml.v2"
) )
type NodePrinter interface { type NodePrinter interface {

@ -35,6 +35,11 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/imdario/mergo" "github.com/imdario/mergo"
copystruct "github.com/mitchellh/copystructure"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/pkg/actions" "github.com/k3d-io/k3d/v5/pkg/actions"
config "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4" config "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
@ -45,10 +50,6 @@ import (
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/k3d-io/k3d/v5/pkg/types/k3s" "github.com/k3d-io/k3d/v5/pkg/types/k3s"
"github.com/k3d-io/k3d/v5/pkg/util" "github.com/k3d-io/k3d/v5/pkg/util"
copystruct "github.com/mitchellh/copystructure"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v2"
) )
// ClusterRun orchestrates the steps of cluster creation, configuration and starting // ClusterRun orchestrates the steps of cluster creation, configuration and starting
@ -1057,7 +1058,7 @@ func ClusterStart(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Clust
} }
var outputBuf bytes.Buffer var outputBuf bytes.Buffer
outputEncoder := yaml.NewEncoder(&outputBuf) outputEncoder := util.NewYAMLEncoder(&outputBuf)
for _, d := range split { for _, d := range split {
var doc map[string]interface{} var doc map[string]interface{}
@ -1066,7 +1067,10 @@ func ClusterStart(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Clust
} }
if kind, ok := doc["kind"]; ok { if kind, ok := doc["kind"]; ok {
if strings.ToLower(kind.(string)) == "configmap" { if strings.ToLower(kind.(string)) == "configmap" {
configmapData := doc["data"].(map[interface{}]interface{}) configmapData, ok := doc["data"].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid ConfigMap data type: %T", doc["data"])
}
configmapData["NodeHosts"] = hosts configmapData["NodeHosts"] = hosts
} }
} }
@ -1074,7 +1078,7 @@ func ClusterStart(ctx context.Context, runtime k3drt.Runtime, cluster *k3d.Clust
return nil, err return nil, err
} }
} }
outputEncoder.Close() _ = outputEncoder.Close()
return outputBuf.Bytes(), nil return outputBuf.Bytes(), nil
}, },
} }

@ -33,12 +33,13 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/go-test/deep" "github.com/go-test/deep"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"github.com/spf13/viper"
"sigs.k8s.io/yaml"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
"github.com/k3d-io/k3d/v5/pkg/types" "github.com/k3d-io/k3d/v5/pkg/types"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
) )
var ( var (

@ -34,25 +34,24 @@ import (
"strings" "strings"
"time" "time"
copystruct "github.com/mitchellh/copystructure"
"gopkg.in/yaml.v2"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
dockerunits "github.com/docker/go-units" dockerunits "github.com/docker/go-units"
"github.com/imdario/mergo" "github.com/imdario/mergo"
copystruct "github.com/mitchellh/copystructure"
"golang.org/x/sync/errgroup"
"sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/pkg/actions" "github.com/k3d-io/k3d/v5/pkg/actions"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
"github.com/k3d-io/k3d/v5/pkg/runtimes/docker" "github.com/k3d-io/k3d/v5/pkg/runtimes/docker"
runtimeTypes "github.com/k3d-io/k3d/v5/pkg/runtimes/types"
"github.com/k3d-io/k3d/v5/version"
runtimeErrors "github.com/k3d-io/k3d/v5/pkg/runtimes/errors" runtimeErrors "github.com/k3d-io/k3d/v5/pkg/runtimes/errors"
runtimeTypes "github.com/k3d-io/k3d/v5/pkg/runtimes/types"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/k3d-io/k3d/v5/pkg/types/fixes" "github.com/k3d-io/k3d/v5/pkg/types/fixes"
"github.com/k3d-io/k3d/v5/pkg/types/k3s" "github.com/k3d-io/k3d/v5/pkg/types/k3s"
"github.com/k3d-io/k3d/v5/pkg/util" "github.com/k3d-io/k3d/v5/pkg/util"
"golang.org/x/sync/errgroup" "github.com/k3d-io/k3d/v5/version"
) )
// NodeAddToCluster adds a node to an existing cluster // NodeAddToCluster adds a node to an existing cluster

@ -28,14 +28,15 @@ import (
"strings" "strings"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/sirupsen/logrus"
"sigs.k8s.io/yaml"
"github.com/k3d-io/k3d/v5/pkg/config/types" "github.com/k3d-io/k3d/v5/pkg/config/types"
config "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4" config "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/k3d-io/k3d/v5/pkg/util" "github.com/k3d-io/k3d/v5/pkg/util"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
) )
var ( var (

@ -28,13 +28,14 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"sigs.k8s.io/yaml"
l "github.com/k3d-io/k3d/v5/pkg/logger" l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
"github.com/k3d-io/k3d/v5/pkg/runtimes/docker" "github.com/k3d-io/k3d/v5/pkg/runtimes/docker"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/k3d-io/k3d/v5/pkg/types/k3s" "github.com/k3d-io/k3d/v5/pkg/types/k3s"
"github.com/k3d-io/k3d/v5/pkg/types/k8s" "github.com/k3d-io/k3d/v5/pkg/types/k8s"
"gopkg.in/yaml.v2"
) )
func RegistryRun(ctx context.Context, runtime runtimes.Runtime, reg *k3d.Registry) (*k3d.Node, error) { func RegistryRun(ctx context.Context, runtime runtimes.Runtime, reg *k3d.Registry) (*k3d.Node, error) {
@ -275,19 +276,19 @@ func RegistryFromNode(node *k3d.Node) (*k3d.Registry, error) {
func RegistryGenerateLocalRegistryHostingConfigMapYAML(ctx context.Context, runtime runtimes.Runtime, registries []*k3d.Registry) ([]byte, error) { func RegistryGenerateLocalRegistryHostingConfigMapYAML(ctx context.Context, runtime runtimes.Runtime, registries []*k3d.Registry) ([]byte, error) {
type cmMetadata struct { type cmMetadata struct {
Name string `yaml:"name"` Name string `json:"name"`
Namespace string `yaml:"namespace"` Namespace string `json:"namespace"`
} }
type cmData struct { type cmData struct {
RegHostV1 string `yaml:"localRegistryHosting.v1"` RegHostV1 string `json:"localRegistryHosting.v1"`
} }
type configmap struct { type configmap struct {
APIVersion string `yaml:"apiVersion"` APIVersion string `json:"apiVersion"`
Kind string `yaml:"kind"` Kind string `json:"kind"`
Metadata cmMetadata `yaml:"metadata"` Metadata cmMetadata `json:"metadata"`
Data cmData `yaml:"data"` Data cmData `json:"data"`
} }
if len(registries) > 1 { if len(registries) > 1 {

@ -30,18 +30,18 @@ import (
"strings" "strings"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"inet.af/netaddr"
"sigs.k8s.io/yaml"
cliutil "github.com/k3d-io/k3d/v5/cmd/util" // TODO: move parseapiport to pkg cliutil "github.com/k3d-io/k3d/v5/cmd/util" // TODO: move parseapiport to pkg
"github.com/k3d-io/k3d/v5/pkg/client" "github.com/k3d-io/k3d/v5/pkg/client"
conf "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4" conf "github.com/k3d-io/k3d/v5/pkg/config/v1alpha4"
l "github.com/k3d-io/k3d/v5/pkg/logger"
"github.com/k3d-io/k3d/v5/pkg/runtimes" "github.com/k3d-io/k3d/v5/pkg/runtimes"
k3d "github.com/k3d-io/k3d/v5/pkg/types" k3d "github.com/k3d-io/k3d/v5/pkg/types"
"github.com/k3d-io/k3d/v5/pkg/types/k3s" "github.com/k3d-io/k3d/v5/pkg/types/k3s"
"github.com/k3d-io/k3d/v5/pkg/util" "github.com/k3d-io/k3d/v5/pkg/util"
"github.com/k3d-io/k3d/v5/version" "github.com/k3d-io/k3d/v5/version"
"gopkg.in/yaml.v2"
"inet.af/netaddr"
l "github.com/k3d-io/k3d/v5/pkg/logger"
) )
// TransformSimpleToClusterConfig transforms a simple configuration to a full-fledged cluster configuration // TransformSimpleToClusterConfig transforms a simple configuration to a full-fledged cluster configuration

@ -23,13 +23,13 @@ package types
// TypeMeta is basically copied from https://github.com/kubernetes/apimachinery/blob/a3b564b22db316a41e94fdcffcf9995424fe924c/pkg/apis/meta/v1/types.go#L36-L56 // TypeMeta is basically copied from https://github.com/kubernetes/apimachinery/blob/a3b564b22db316a41e94fdcffcf9995424fe924c/pkg/apis/meta/v1/types.go#L36-L56
type TypeMeta struct { type TypeMeta struct {
Kind string `mapstructure:"kind,omitempty" yaml:"kind,omitempty" json:"kind,omitempty"` Kind string `mapstructure:"kind,omitempty" json:"kind,omitempty"`
APIVersion string `mapstructure:"apiVersion,omitempty" yaml:"apiVersion,omitempty" json:"apiVersion,omitempty"` APIVersion string `mapstructure:"apiVersion,omitempty" json:"apiVersion,omitempty"`
} }
// ObjectMeta got its name from the Kubernetes counterpart. // ObjectMeta got its name from the Kubernetes counterpart.
type ObjectMeta struct { type ObjectMeta struct {
Name string `mapstructure:"name,omitempty" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name,omitempty" json:"name,omitempty"`
} }
// Config interface. // Config interface.

@ -57,87 +57,87 @@ var DefaultConfig = fmt.Sprintf(
) )
type VolumeWithNodeFilters struct { type VolumeWithNodeFilters struct {
Volume string `mapstructure:"volume" yaml:"volume,omitempty" json:"volume,omitempty"` Volume string `mapstructure:"volume" json:"volume,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type PortWithNodeFilters struct { type PortWithNodeFilters struct {
Port string `mapstructure:"port" yaml:"port,omitempty" json:"port,omitempty"` Port string `mapstructure:"port" json:"port,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type LabelWithNodeFilters struct { type LabelWithNodeFilters struct {
Label string `mapstructure:"label" yaml:"label,omitempty" json:"label,omitempty"` Label string `mapstructure:"label" json:"label,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type EnvVarWithNodeFilters struct { type EnvVarWithNodeFilters struct {
EnvVar string `mapstructure:"envVar" yaml:"envVar,omitempty" json:"envVar,omitempty"` EnvVar string `mapstructure:"envVar" json:"envVar,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" 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.
type SimpleConfigOptionsKubeconfig struct { type SimpleConfigOptionsKubeconfig struct {
UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" yaml:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true
SwitchCurrentContext bool `mapstructure:"switchCurrentContext" yaml:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true SwitchCurrentContext bool `mapstructure:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true
} }
type SimpleConfigOptions struct { type SimpleConfigOptions struct {
K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d" json:"k3d"` K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" json:"k3d"`
K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s" json:"k3s"` K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" json:"k3s"`
KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig" json:"kubeconfig"` KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime" json:"runtime"` Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" json:"runtime"`
} }
type SimpleConfigOptionsRuntime struct { type SimpleConfigOptionsRuntime struct {
GPURequest string `mapstructure:"gpuRequest,omitempty" yaml:"gpuRequest,omitempty" json:"gpuRequest,omitempty"` GPURequest string `mapstructure:"gpuRequest,omitempty" json:"gpuRequest,omitempty"`
ServersMemory string `mapstructure:"serversMemory,omitempty" yaml:"serversMemory,omitempty" json:"serversMemory,omitempty"` ServersMemory string `mapstructure:"serversMemory,omitempty" json:"serversMemory,omitempty"`
AgentsMemory string `mapstructure:"agentsMemory,omitempty" yaml:"agentsMemory,omitempty" json:"agentsMemory,omitempty"` AgentsMemory string `mapstructure:"agentsMemory,omitempty" json:"agentsMemory,omitempty"`
} }
type SimpleConfigOptionsK3d struct { type SimpleConfigOptionsK3d struct {
Wait bool `mapstructure:"wait" yaml:"wait" json:"wait"` Wait bool `mapstructure:"wait" json:"wait"`
Timeout time.Duration `mapstructure:"timeout" yaml:"timeout,omitempty" json:"timeout,omitempty"` Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`
DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer" json:"disableLoadbalancer"` DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" json:"disableLoadbalancer"`
DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume" json:"disableImageVolume"` DisableImageVolume bool `mapstructure:"disableImageVolume" json:"disableImageVolume"`
NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback" json:"disableRollback"` NoRollback bool `mapstructure:"disableRollback" json:"disableRollback"`
PrepDisableHostIPInjection bool `mapstructure:"disableHostIPInjection" json:"disableHostIPInjection"` PrepDisableHostIPInjection bool `mapstructure:"disableHostIPInjection" json:"disableHostIPInjection"`
NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty" json:"nodeHookActions,omitempty"` NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" json:"nodeHookActions,omitempty"`
} }
type SimpleConfigOptionsK3s struct { type SimpleConfigOptionsK3s struct {
ExtraServerArgs []string `mapstructure:"extraServerArgs,omitempty" yaml:"extraServerArgs,omitempty" json:"extraServerArgs,omitempty"` ExtraServerArgs []string `mapstructure:"extraServerArgs,omitempty" json:"extraServerArgs,omitempty"`
ExtraAgentArgs []string `mapstructure:"extraAgentArgs,omitempty" yaml:"extraAgentArgs,omitempty" json:"extraAgentArgs,omitempty"` ExtraAgentArgs []string `mapstructure:"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"`
Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"` Image string `mapstructure:"image" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"` Network string `mapstructure:"network" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" json:"ports,omitempty"`
Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels,omitempty" json:"labels,omitempty"` Labels []LabelWithNodeFilters `mapstructure:"labels" json:"labels,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" json:"env,omitempty"`
Registries struct { Registries struct {
Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"` Use []string `mapstructure:"use" json:"use,omitempty"`
Create bool `mapstructure:"create" yaml:"create,omitempty" json:"create,omitempty"` Create bool `mapstructure:"create" json:"create,omitempty"`
Config string `mapstructure:"config" yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) Config string `mapstructure:"config" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override)
} `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` } `mapstructure:"registries" json:"registries,omitempty"`
} }
// SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts // SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts
type SimpleExposureOpts struct { type SimpleExposureOpts struct {
Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"` Host string `mapstructure:"host" json:"host,omitempty"`
HostIP string `mapstructure:"hostIP" yaml:"hostIP,omitempty" json:"hostIP,omitempty"` HostIP string `mapstructure:"hostIP" json:"hostIP,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"` HostPort string `mapstructure:"hostPort" json:"hostPort,omitempty"`
} }
// Kind implements Config.Kind // Kind implements Config.Kind
@ -151,10 +151,10 @@ func (c SimpleConfig) GetAPIVersion() string {
// ClusterConfig describes a single cluster config // ClusterConfig describes a single cluster config
type ClusterConfig struct { type ClusterConfig struct {
configtypes.TypeMeta `mapstructure:",squash" yaml:",inline"` configtypes.TypeMeta `mapstructure:",squash"`
Cluster k3d.Cluster `mapstructure:",squash" yaml:",inline"` k3d.Cluster `mapstructure:",squash"`
ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" yaml:"options"` ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" json:"options"`
KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig"` KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
} }
// Kind implements Config.Kind // Kind implements Config.Kind
@ -168,8 +168,8 @@ func (c ClusterConfig) GetAPIVersion() string {
// ClusterListConfig describes a list of clusters // ClusterListConfig describes a list of clusters
type ClusterListConfig struct { type ClusterListConfig struct {
configtypes.TypeMeta `mapstructure:",squash" yaml:",inline"` configtypes.TypeMeta `mapstructure:",squash"`
Clusters []k3d.Cluster `mapstructure:"clusters" yaml:"clusters"` Clusters []k3d.Cluster `mapstructure:"clusters" json:"clusters"`
} }
func (c ClusterListConfig) GetKind() string { func (c ClusterListConfig) GetKind() string {

@ -57,127 +57,127 @@ var DefaultConfig = fmt.Sprintf(
) )
type VolumeWithNodeFilters struct { type VolumeWithNodeFilters struct {
Volume string `mapstructure:"volume" yaml:"volume,omitempty" json:"volume,omitempty"` Volume string `mapstructure:"volume" json:"volume,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type PortWithNodeFilters struct { type PortWithNodeFilters struct {
Port string `mapstructure:"port" yaml:"port,omitempty" json:"port,omitempty"` Port string `mapstructure:"port" json:"port,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type LabelWithNodeFilters struct { type LabelWithNodeFilters struct {
Label string `mapstructure:"label" yaml:"label,omitempty" json:"label,omitempty"` Label string `mapstructure:"label" json:"label,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type EnvVarWithNodeFilters struct { type EnvVarWithNodeFilters struct {
EnvVar string `mapstructure:"envVar" yaml:"envVar,omitempty" json:"envVar,omitempty"` EnvVar string `mapstructure:"envVar" json:"envVar,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type K3sArgWithNodeFilters struct { type K3sArgWithNodeFilters struct {
Arg string `mapstructure:"arg" yaml:"arg,omitempty" json:"arg,omitempty"` Arg string `mapstructure:"arg" json:"arg,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type SimpleConfigRegistryCreateConfig struct { type SimpleConfigRegistryCreateConfig struct {
Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name" json:"name,omitempty"`
Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"` Host string `mapstructure:"host" json:"host,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"` HostPort string `mapstructure:"hostPort" 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.
type SimpleConfigOptionsKubeconfig struct { type SimpleConfigOptionsKubeconfig struct {
UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" yaml:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true
SwitchCurrentContext bool `mapstructure:"switchCurrentContext" yaml:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true SwitchCurrentContext bool `mapstructure:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true
} }
type SimpleConfigOptions struct { type SimpleConfigOptions struct {
K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d" json:"k3d"` K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" json:"k3d"`
K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s" json:"k3s"` K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" json:"k3s"`
KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig" json:"kubeconfig"` KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime" json:"runtime"` Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" json:"runtime"`
} }
type SimpleConfigOptionsRuntime struct { type SimpleConfigOptionsRuntime struct {
GPURequest string `mapstructure:"gpuRequest" yaml:"gpuRequest,omitempty" json:"gpuRequest,omitempty"` GPURequest string `mapstructure:"gpuRequest" json:"gpuRequest,omitempty"`
ServersMemory string `mapstructure:"serversMemory" yaml:"serversMemory,omitempty" json:"serversMemory,omitempty"` ServersMemory string `mapstructure:"serversMemory" json:"serversMemory,omitempty"`
AgentsMemory string `mapstructure:"agentsMemory" yaml:"agentsMemory,omitempty" json:"agentsMemory,omitempty"` AgentsMemory string `mapstructure:"agentsMemory" json:"agentsMemory,omitempty"`
Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels,omitempty" json:"labels,omitempty"` Labels []LabelWithNodeFilters `mapstructure:"labels" json:"labels,omitempty"`
} }
type SimpleConfigOptionsK3d struct { type SimpleConfigOptionsK3d struct {
Wait bool `mapstructure:"wait" yaml:"wait" json:"wait"` Wait bool `mapstructure:"wait" json:"wait"`
Timeout time.Duration `mapstructure:"timeout" yaml:"timeout,omitempty" json:"timeout,omitempty"` Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`
DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer" json:"disableLoadbalancer"` DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" json:"disableLoadbalancer"`
DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume" json:"disableImageVolume"` DisableImageVolume bool `mapstructure:"disableImageVolume" json:"disableImageVolume"`
NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback" json:"disableRollback"` NoRollback bool `mapstructure:"disableRollback" json:"disableRollback"`
NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty" json:"nodeHookActions,omitempty"` NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" json:"nodeHookActions,omitempty"`
Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" yaml:"loadbalancer,omitempty" json:"loadbalancer,omitempty"` Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" json:"loadbalancer,omitempty"`
} }
type SimpleConfigOptionsK3dLoadbalancer struct { type SimpleConfigOptionsK3dLoadbalancer struct {
ConfigOverrides []string `mapstructure:"configOverrides" yaml:"configOverrides,omitempty" json:"configOverrides,omitempty"` ConfigOverrides []string `mapstructure:"configOverrides" json:"configOverrides,omitempty"`
} }
type SimpleConfigOptionsK3s struct { type SimpleConfigOptionsK3s struct {
ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" yaml:"extraArgs,omitempty" json:"extraArgs,omitempty"` ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" json:"extraArgs,omitempty"`
NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" yaml:"nodeLabels,omitempty" json:"nodeLabels,omitempty"` NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" json:"nodeLabels,omitempty"`
} }
type SimpleConfigRegistries struct { type SimpleConfigRegistries struct {
Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"` Use []string `mapstructure:"use" json:"use,omitempty"`
Create *SimpleConfigRegistryCreateConfig `mapstructure:"create" yaml:"create,omitempty" json:"create,omitempty"` Create *SimpleConfigRegistryCreateConfig `mapstructure:"create" json:"create,omitempty"`
Config string `mapstructure:"config" yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) Config string `mapstructure:"config" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override)
} }
type SimpleConfigRegistriesIntermediateV1alpha2 struct { type SimpleConfigRegistriesIntermediateV1alpha2 struct {
Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"` Use []string `mapstructure:"use" json:"use,omitempty"`
// Field "Create" changed significantly, so it's dropped here // Field "Create" changed significantly, so it's dropped here
Config string `mapstructure:"config" yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) Config string `mapstructure:"config" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override)
} }
// 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"`
Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"` Image string `mapstructure:"image" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"` Network string `mapstructure:"network" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" json:"ports,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" json:"env,omitempty"`
Registries SimpleConfigRegistries `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` Registries SimpleConfigRegistries `mapstructure:"registries" json:"registries,omitempty"`
} }
type SimpleConfigIntermediateV1alpha2 struct { type SimpleConfigIntermediateV1alpha2 struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash"`
Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name" json:"name,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"` Image string `mapstructure:"image" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"` Network string `mapstructure:"network" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" json:"ports,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" json:"env,omitempty"`
Registries SimpleConfigRegistriesIntermediateV1alpha2 `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` Registries SimpleConfigRegistriesIntermediateV1alpha2 `mapstructure:"registries" json:"registries,omitempty"`
} }
// SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts // SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts
type SimpleExposureOpts struct { type SimpleExposureOpts struct {
Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"` Host string `mapstructure:"host" json:"host,omitempty"`
HostIP string `mapstructure:"hostIP" yaml:"hostIP,omitempty" json:"hostIP,omitempty"` HostIP string `mapstructure:"hostIP" json:"hostIP,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"` HostPort string `mapstructure:"hostPort" json:"hostPort,omitempty"`
} }
// GetKind implements Config.GetKind // GetKind implements Config.GetKind
@ -191,10 +191,10 @@ func (c SimpleConfig) GetAPIVersion() string {
// ClusterConfig describes a single cluster config // ClusterConfig describes a single cluster config
type ClusterConfig struct { type ClusterConfig struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash"`
Cluster k3d.Cluster `mapstructure:",squash" yaml:",inline"` k3d.Cluster `mapstructure:",squash"`
ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" yaml:"options"` ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" json:"options"`
KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig"` KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
} }
// GetKind implements Config.GetKind // GetKind implements Config.GetKind
@ -208,8 +208,8 @@ func (c ClusterConfig) GetAPIVersion() string {
// ClusterListConfig describes a list of clusters // ClusterListConfig describes a list of clusters
type ClusterListConfig struct { type ClusterListConfig struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash"`
Clusters []k3d.Cluster `mapstructure:"clusters" yaml:"clusters"` Clusters []k3d.Cluster `mapstructure:"clusters" json:"clusters"`
} }
func (c ClusterListConfig) GetKind() string { func (c ClusterListConfig) GetKind() string {

@ -58,109 +58,109 @@ var DefaultConfig = fmt.Sprintf(
) )
type VolumeWithNodeFilters struct { type VolumeWithNodeFilters struct {
Volume string `mapstructure:"volume" yaml:"volume,omitempty" json:"volume,omitempty"` Volume string `mapstructure:"volume" json:"volume,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type PortWithNodeFilters struct { type PortWithNodeFilters struct {
Port string `mapstructure:"port" yaml:"port,omitempty" json:"port,omitempty"` Port string `mapstructure:"port" json:"port,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type LabelWithNodeFilters struct { type LabelWithNodeFilters struct {
Label string `mapstructure:"label" yaml:"label,omitempty" json:"label,omitempty"` Label string `mapstructure:"label" json:"label,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type EnvVarWithNodeFilters struct { type EnvVarWithNodeFilters struct {
EnvVar string `mapstructure:"envVar" yaml:"envVar,omitempty" json:"envVar,omitempty"` EnvVar string `mapstructure:"envVar" json:"envVar,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type K3sArgWithNodeFilters struct { type K3sArgWithNodeFilters struct {
Arg string `mapstructure:"arg" yaml:"arg,omitempty" json:"arg,omitempty"` Arg string `mapstructure:"arg" json:"arg,omitempty"`
NodeFilters []string `mapstructure:"nodeFilters" yaml:"nodeFilters,omitempty" json:"nodeFilters,omitempty"` NodeFilters []string `mapstructure:"nodeFilters" json:"nodeFilters,omitempty"`
} }
type SimpleConfigRegistryCreateConfig struct { type SimpleConfigRegistryCreateConfig struct {
Name string `mapstructure:"name" yaml:"name,omitempty" json:"name,omitempty"` Name string `mapstructure:"name" json:"name,omitempty"`
Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"` Host string `mapstructure:"host" json:"host,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"` HostPort string `mapstructure:"hostPort" json:"hostPort,omitempty"`
Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"` Image string `mapstructure:"image" json:"image,omitempty"`
Proxy k3d.RegistryProxy `mapstructure:"proxy" yaml:"proxy,omitempty" json:"proxy,omitempty"` Proxy k3d.RegistryProxy `mapstructure:"proxy" json:"proxy,omitempty"`
Volumes []string `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []string `mapstructure:"volumes" json:"volumes,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.
type SimpleConfigOptionsKubeconfig struct { type SimpleConfigOptionsKubeconfig struct {
UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" yaml:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true UpdateDefaultKubeconfig bool `mapstructure:"updateDefaultKubeconfig" json:"updateDefaultKubeconfig,omitempty"` // default: true
SwitchCurrentContext bool `mapstructure:"switchCurrentContext" yaml:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true SwitchCurrentContext bool `mapstructure:"switchCurrentContext" json:"switchCurrentContext,omitempty"` //nolint:lll // default: true
} }
type SimpleConfigOptions struct { type SimpleConfigOptions struct {
K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" yaml:"k3d" json:"k3d"` K3dOptions SimpleConfigOptionsK3d `mapstructure:"k3d" json:"k3d"`
K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" yaml:"k3s" json:"k3s"` K3sOptions SimpleConfigOptionsK3s `mapstructure:"k3s" json:"k3s"`
KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig" json:"kubeconfig"` KubeconfigOptions SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" yaml:"runtime" json:"runtime"` Runtime SimpleConfigOptionsRuntime `mapstructure:"runtime" json:"runtime"`
} }
type SimpleConfigOptionsRuntime struct { type SimpleConfigOptionsRuntime struct {
GPURequest string `mapstructure:"gpuRequest" yaml:"gpuRequest,omitempty" json:"gpuRequest,omitempty"` GPURequest string `mapstructure:"gpuRequest" json:"gpuRequest,omitempty"`
ServersMemory string `mapstructure:"serversMemory" yaml:"serversMemory,omitempty" json:"serversMemory,omitempty"` ServersMemory string `mapstructure:"serversMemory" json:"serversMemory,omitempty"`
AgentsMemory string `mapstructure:"agentsMemory" yaml:"agentsMemory,omitempty" json:"agentsMemory,omitempty"` AgentsMemory string `mapstructure:"agentsMemory" json:"agentsMemory,omitempty"`
HostPidMode bool `mapstructure:"hostPidMode" yaml:"hostPidMode,omitempty" json:"hostPidMode,omitempty"` HostPidMode bool `mapstructure:"hostPidMode" yjson:"hostPidMode,omitempty"`
Labels []LabelWithNodeFilters `mapstructure:"labels" yaml:"labels,omitempty" json:"labels,omitempty"` Labels []LabelWithNodeFilters `mapstructure:"labels" json:"labels,omitempty"`
} }
type SimpleConfigOptionsK3d struct { type SimpleConfigOptionsK3d struct {
Wait bool `mapstructure:"wait" yaml:"wait" json:"wait"` Wait bool `mapstructure:"wait" json:"wait"`
Timeout time.Duration `mapstructure:"timeout" yaml:"timeout,omitempty" json:"timeout,omitempty"` Timeout time.Duration `mapstructure:"timeout" json:"timeout,omitempty"`
DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" yaml:"disableLoadbalancer" json:"disableLoadbalancer"` DisableLoadbalancer bool `mapstructure:"disableLoadbalancer" json:"disableLoadbalancer"`
DisableImageVolume bool `mapstructure:"disableImageVolume" yaml:"disableImageVolume" json:"disableImageVolume"` DisableImageVolume bool `mapstructure:"disableImageVolume" json:"disableImageVolume"`
NoRollback bool `mapstructure:"disableRollback" yaml:"disableRollback" json:"disableRollback"` NoRollback bool `mapstructure:"disableRollback" json:"disableRollback"`
NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" yaml:"nodeHookActions,omitempty" json:"nodeHookActions,omitempty"` NodeHookActions []k3d.NodeHookAction `mapstructure:"nodeHookActions" json:"nodeHookActions,omitempty"`
Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" yaml:"loadbalancer,omitempty" json:"loadbalancer,omitempty"` Loadbalancer SimpleConfigOptionsK3dLoadbalancer `mapstructure:"loadbalancer" json:"loadbalancer,omitempty"`
} }
type SimpleConfigOptionsK3dLoadbalancer struct { type SimpleConfigOptionsK3dLoadbalancer struct {
ConfigOverrides []string `mapstructure:"configOverrides" yaml:"configOverrides,omitempty" json:"configOverrides,omitempty"` ConfigOverrides []string `mapstructure:"configOverrides" json:"configOverrides,omitempty"`
} }
type SimpleConfigOptionsK3s struct { type SimpleConfigOptionsK3s struct {
ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" yaml:"extraArgs,omitempty" json:"extraArgs,omitempty"` ExtraArgs []K3sArgWithNodeFilters `mapstructure:"extraArgs" json:"extraArgs,omitempty"`
NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" yaml:"nodeLabels,omitempty" json:"nodeLabels,omitempty"` NodeLabels []LabelWithNodeFilters `mapstructure:"nodeLabels" json:"nodeLabels,omitempty"`
} }
type SimpleConfigRegistries struct { type SimpleConfigRegistries struct {
Use []string `mapstructure:"use" yaml:"use,omitempty" json:"use,omitempty"` Use []string `mapstructure:"use" json:"use,omitempty"`
Create *SimpleConfigRegistryCreateConfig `mapstructure:"create" yaml:"create,omitempty" json:"create,omitempty"` Create *SimpleConfigRegistryCreateConfig `mapstructure:"create" json:"create,omitempty"`
Config string `mapstructure:"config" yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) Config string `mapstructure:"config" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override)
} }
// 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"`
config.ObjectMeta `mapstructure:"metadata" yaml:"metadata,omitempty" json:"metadata,omitempty"` config.ObjectMeta `mapstructure:"metadata" json:"metadata,omitempty"`
Servers int `mapstructure:"servers" yaml:"servers,omitempty" json:"servers,omitempty"` //nolint:lll // default 1 Servers int `mapstructure:"servers" json:"servers,omitempty"` //nolint:lll // default 1
Agents int `mapstructure:"agents" yaml:"agents,omitempty" json:"agents,omitempty"` //nolint:lll // default 0 Agents int `mapstructure:"agents" json:"agents,omitempty"` //nolint:lll // default 0
ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" yaml:"kubeAPI,omitempty" json:"kubeAPI,omitempty"` ExposeAPI SimpleExposureOpts `mapstructure:"kubeAPI" json:"kubeAPI,omitempty"`
Image string `mapstructure:"image" yaml:"image,omitempty" json:"image,omitempty"` Image string `mapstructure:"image" json:"image,omitempty"`
Network string `mapstructure:"network" yaml:"network,omitempty" json:"network,omitempty"` Network string `mapstructure:"network" json:"network,omitempty"`
Subnet string `mapstructure:"subnet" yaml:"subnet,omitempty" json:"subnet,omitempty"` Subnet string `mapstructure:"subnet" json:"subnet,omitempty"`
ClusterToken string `mapstructure:"token" yaml:"clusterToken,omitempty" json:"clusterToken,omitempty"` // default: auto-generated ClusterToken string `mapstructure:"token" json:"clusterToken,omitempty"` // default: auto-generated
Volumes []VolumeWithNodeFilters `mapstructure:"volumes" yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []VolumeWithNodeFilters `mapstructure:"volumes" json:"volumes,omitempty"`
Ports []PortWithNodeFilters `mapstructure:"ports" yaml:"ports,omitempty" json:"ports,omitempty"` Ports []PortWithNodeFilters `mapstructure:"ports" json:"ports,omitempty"`
Options SimpleConfigOptions `mapstructure:"options" yaml:"options,omitempty" json:"options,omitempty"` Options SimpleConfigOptions `mapstructure:"options" json:"options,omitempty"`
Env []EnvVarWithNodeFilters `mapstructure:"env" yaml:"env,omitempty" json:"env,omitempty"` Env []EnvVarWithNodeFilters `mapstructure:"env" json:"env,omitempty"`
Registries SimpleConfigRegistries `mapstructure:"registries" yaml:"registries,omitempty" json:"registries,omitempty"` Registries SimpleConfigRegistries `mapstructure:"registries" json:"registries,omitempty"`
HostAliases []k3d.HostAlias `mapstructure:"hostAliases" yaml:"hostAliases,omitempty" json:"hostAliases,omitempty"` HostAliases []k3d.HostAlias `mapstructure:"hostAliases" json:"hostAliases,omitempty"`
} }
// SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts // SimpleExposureOpts provides a simplified syntax compared to the original k3d.ExposureOpts
type SimpleExposureOpts struct { type SimpleExposureOpts struct {
Host string `mapstructure:"host" yaml:"host,omitempty" json:"host,omitempty"` Host string `mapstructure:"host" json:"host,omitempty"`
HostIP string `mapstructure:"hostIP" yaml:"hostIP,omitempty" json:"hostIP,omitempty"` HostIP string `mapstructure:"hostIP" json:"hostIP,omitempty"`
HostPort string `mapstructure:"hostPort" yaml:"hostPort,omitempty" json:"hostPort,omitempty"` HostPort string `mapstructure:"hostPort" json:"hostPort,omitempty"`
} }
// GetKind implements Config.GetKind // GetKind implements Config.GetKind
@ -174,10 +174,10 @@ func (c SimpleConfig) GetAPIVersion() string {
// ClusterConfig describes a single cluster config // ClusterConfig describes a single cluster config
type ClusterConfig struct { type ClusterConfig struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash"`
Cluster k3d.Cluster `mapstructure:",squash" yaml:",inline"` k3d.Cluster `mapstructure:",squash"`
ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" yaml:"options"` ClusterCreateOpts k3d.ClusterCreateOpts `mapstructure:"options" json:"options"`
KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" yaml:"kubeconfig"` KubeconfigOpts SimpleConfigOptionsKubeconfig `mapstructure:"kubeconfig" json:"kubeconfig"`
} }
// GetKind implements Config.GetKind // GetKind implements Config.GetKind
@ -191,8 +191,8 @@ func (c ClusterConfig) GetAPIVersion() string {
// ClusterListConfig describes a list of clusters // ClusterListConfig describes a list of clusters
type ClusterListConfig struct { type ClusterListConfig struct {
config.TypeMeta `mapstructure:",squash" yaml:",inline"` config.TypeMeta `mapstructure:",squash"`
Clusters []k3d.Cluster `mapstructure:"clusters" yaml:"clusters"` Clusters []k3d.Cluster `mapstructure:"clusters" json:"clusters"`
} }
func (c ClusterListConfig) GetKind() string { func (c ClusterListConfig) GetKind() string {

@ -22,15 +22,15 @@ THE SOFTWARE.
package types package types
type RuntimeInfo struct { type RuntimeInfo struct {
Name string Name string `json:"name,omitempty"`
Endpoint string `yaml:",omitempty" json:",omitempty"` Endpoint string `json:"endpoint,omitempty"`
Version string `yaml:",omitempty" json:",omitempty"` Version string `json:"version,omitempty"`
OSType string `yaml:",omitempty" json:",omitempty"` OSType string `json:"ostype,omitempty"`
OS string `yaml:",omitempty" json:",omitempty"` OS string `json:"os,omitempty"`
Arch string `yaml:",omitempty" json:",omitempty"` Arch string `json:"arch,omitempty"`
CgroupVersion string `yaml:",omitempty" json:",omitempty"` CgroupVersion string `json:"cgroupversion,omitempty"`
CgroupDriver string `yaml:",omitempty" json:",omitempty"` CgroupDriver string `json:"cgroupdriver,omitempty"`
Filesystem string `yaml:",omitempty" json:",omitempty"` Filesystem string `json:"filesystem,omitempty"`
} }
type NodeLogsOpts struct { type NodeLogsOpts struct {

@ -32,50 +32,50 @@ type Mirror struct {
// one by one until a working one is found. The endpoint must be a valid url // one by one until a working one is found. The endpoint must be a valid url
// with host specified. // with host specified.
// The scheme, host and path from the endpoint URL will be used. // The scheme, host and path from the endpoint URL will be used.
Endpoints []string `toml:"endpoint" yaml:"endpoint"` Endpoints []string `toml:"endpoint" json:"endpoint"`
} }
// AuthConfig contains the config related to authentication to a specific registry // AuthConfig contains the config related to authentication to a specific registry
type AuthConfig struct { type AuthConfig struct {
// Username is the username to login the registry. // Username is the username to login the registry.
Username string `toml:"username" yaml:"username"` Username string `toml:"username" json:"username"`
// Password is the password to login the registry. // Password is the password to login the registry.
Password string `toml:"password" yaml:"password"` Password string `toml:"password" json:"password"`
// Auth is a base64 encoded string from the concatenation of the username, // Auth is a base64 encoded string from the concatenation of the username,
// a colon, and the password. // a colon, and the password.
Auth string `toml:"auth" yaml:"auth"` Auth string `toml:"auth" json:"auth"`
// IdentityToken is used to authenticate the user and get // IdentityToken is used to authenticate the user and get
// an access token for the registry. // an access token for the registry.
IdentityToken string `toml:"identitytoken" yaml:"identity_token"` IdentityToken string `toml:"identitytoken" json:"identity_token"`
} }
// TLSConfig contains the CA/Cert/Key used for a registry // TLSConfig contains the CA/Cert/Key used for a registry
type TLSConfig struct { type TLSConfig struct {
CAFile string `toml:"ca_file" yaml:"ca_file"` CAFile string `toml:"ca_file" json:"ca_file"`
CertFile string `toml:"cert_file" yaml:"cert_file"` CertFile string `toml:"cert_file" json:"cert_file"`
KeyFile string `toml:"key_file" yaml:"key_file"` KeyFile string `toml:"key_file" json:"key_file"`
InsecureSkipVerify bool `toml:"insecure_skip_verify" yaml:"insecure_skip_verify"` InsecureSkipVerify bool `toml:"insecure_skip_verify" json:"insecure_skip_verify"`
} }
// Registry is registry settings configured // Registry is registry settings configured
type Registry struct { type Registry struct {
// Mirrors are namespace to mirror mapping for all namespaces. // Mirrors are namespace to mirror mapping for all namespaces.
Mirrors map[string]Mirror `toml:"mirrors" yaml:"mirrors"` Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"`
// Configs are configs for each registry. // Configs are configs for each registry.
// The key is the FDQN or IP of the registry. // The key is the FDQN or IP of the registry.
Configs map[string]RegistryConfig `toml:"configs" yaml:"configs"` Configs map[string]RegistryConfig `toml:"configs" json:"configs"`
// Auths are registry endpoint to auth config mapping. The registry endpoint must // Auths are registry endpoint to auth config mapping. The registry endpoint must
// be a valid url with host specified. // be a valid url with host specified.
// DEPRECATED: Use Configs instead. Remove in containerd 1.4. // DEPRECATED: Use Configs instead. Remove in containerd 1.4.
Auths map[string]AuthConfig `toml:"auths" yaml:"auths"` Auths map[string]AuthConfig `toml:"auths" json:"auths"`
} }
// RegistryConfig contains configuration used to communicate with the registry. // RegistryConfig contains configuration used to communicate with the registry.
type RegistryConfig struct { type RegistryConfig struct {
// Auth contains information to authenticate to the registry. // Auth contains information to authenticate to the registry.
Auth *AuthConfig `toml:"auth" yaml:"auth"` Auth *AuthConfig `toml:"auth" json:"auth"`
// TLS is a pair of CA/Cert/Key which then are used when creating the transport // TLS is a pair of CA/Cert/Key which then are used when creating the transport
// that communicates with the registry. // that communicates with the registry.
TLS *TLSConfig `toml:"tls" yaml:"tls"` TLS *TLSConfig `toml:"tls" json:"tls"`
} }

@ -50,7 +50,7 @@ type LocalRegistryHostingV1 struct {
// //
// This is the registry host that tools outside the cluster should push images // This is the registry host that tools outside the cluster should push images
// to. // to.
Host string `yaml:"host,omitempty" json:"host,omitempty"` Host string `json:"host,omitempty"`
// HostFromClusterNetwork documents the host (hostname and port) of the // HostFromClusterNetwork documents the host (hostname and port) of the
// registry, as seen from networking inside the container pods. // registry, as seen from networking inside the container pods.
@ -58,7 +58,7 @@ type LocalRegistryHostingV1 struct {
// This is the registry host that tools running on pods inside the cluster // This is the registry host that tools running on pods inside the cluster
// should push images to. If not set, then tools inside the cluster should // should push images to. If not set, then tools inside the cluster should
// assume the local registry is not available to them. // assume the local registry is not available to them.
HostFromClusterNetwork string `yaml:"hostFromClusterNetwork,omitempty" json:"hostFromClusterNetwork,omitempty"` HostFromClusterNetwork string `json:"hostFromClusterNetwork,omitempty"`
// HostFromContainerRuntime documents the host (hostname and port) of the // HostFromContainerRuntime documents the host (hostname and port) of the
// registry, as seen from the cluster's container runtime. // registry, as seen from the cluster's container runtime.
@ -70,7 +70,7 @@ type LocalRegistryHostingV1 struct {
// Note that it doesn't make sense semantically to define this field, but not // Note that it doesn't make sense semantically to define this field, but not
// define Host or HostFromClusterNetwork. That would imply a way to pull // define Host or HostFromClusterNetwork. That would imply a way to pull
// images without a way to push images. // images without a way to push images.
HostFromContainerRuntime string `yaml:"hostFromContainerRuntime,omitempty" json:"hostFromContainerRuntime,omitempty"` HostFromContainerRuntime string `json:"hostFromContainerRuntime,omitempty"`
// Help contains a URL pointing to documentation for users on how to set // Help contains a URL pointing to documentation for users on how to set
// up and configure a local registry. // up and configure a local registry.
@ -83,7 +83,7 @@ type LocalRegistryHostingV1 struct {
// fail, the tool should display this help URL to the user. The help URL // fail, the tool should display this help URL to the user. The help URL
// should contain instructions on how to diagnose broken or misconfigured // should contain instructions on how to diagnose broken or misconfigured
// registries. // registries.
Help string `yaml:"help,omitempty" json:"help,omitempty"` Help string `json:"help,omitempty"`
} }
// LocalRegistryHosting defaults // LocalRegistryHosting defaults

@ -34,8 +34,8 @@ package types
*/ */
type Loadbalancer struct { type Loadbalancer struct {
Node *Node `mapstructure:",squash" yaml:",inline"` // the underlying node *Node `mapstructure:",squash"` // the underlying node
Config *LoadbalancerConfig `mapstructure:"config" yaml:"config"` // its configuration Config *LoadbalancerConfig `mapstructure:"config" json:"config"` // its configuration
} }
func NewLoadbalancer() *Loadbalancer { func NewLoadbalancer() *Loadbalancer {
@ -68,13 +68,13 @@ func NewLoadbalancer() *Loadbalancer {
* - k3d-k3s-default-agent-1 * - k3d-k3s-default-agent-1
*/ */
type LoadbalancerConfig struct { type LoadbalancerConfig struct {
Ports map[string][]string `yaml:"ports"` Ports map[string][]string `json:"ports"`
Settings LoadBalancerSettings `yaml:"settings"` Settings LoadBalancerSettings `json:"settings"`
} }
type LoadBalancerSettings struct { type LoadBalancerSettings struct {
WorkerConnections int `yaml:"workerConnections"` WorkerConnections int `json:"workerConnections"`
DefaultProxyTimeout int `yaml:"defaultProxyTimeout,omitempty"` DefaultProxyTimeout int `json:"defaultProxyTimeout,omitempty"`
} }
const ( const (

@ -33,33 +33,33 @@ const (
) )
type RegistryOptions struct { type RegistryOptions struct {
ConfigFile string `yaml:"configFile,omitempty" json:"configFile,omitempty"` ConfigFile string `json:"configFile,omitempty"`
Proxy RegistryProxy `yaml:"proxy,omitempty" json:"proxy,omitempty"` Proxy RegistryProxy `json:"proxy,omitempty"`
} }
type RegistryProxy struct { type RegistryProxy struct {
RemoteURL string `yaml:"remoteURL" json:"remoteURL"` RemoteURL string `json:"remoteURL"`
Username string `yaml:"username,omitempty" json:"username,omitempty"` Username string `json:"username,omitempty"`
Password string `yaml:"password,omitempty" json:"password,omitempty"` Password string `json:"password,omitempty"`
} }
// Registry describes a k3d-managed registry // Registry describes a k3d-managed registry
type Registry struct { type Registry struct {
ClusterRef string // filled automatically -> if created with a cluster ClusterRef string // filled automatically -> if created with a cluster
Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"` // default: http Protocol string `json:"protocol,omitempty"` // default: http
Host string `yaml:"host" json:"host"` Host string `json:"host"`
Image string `yaml:"image,omitempty" json:"image,omitempty"` Image string `json:"image,omitempty"`
Network string `yaml:"Network,omitempty" json:"Network,omitempty"` Network string `json:"Network,omitempty"`
Volumes []string `yaml:"Volumes,omitempty" json:"Volumes,omitempty"` Volumes []string `json:"Volumes,omitempty"`
ExposureOpts ExposureOpts `yaml:"expose" json:"expose"` ExposureOpts ExposureOpts `json:"expose"`
Options RegistryOptions `yaml:"options,omitempty" json:"options,omitempty"` Options RegistryOptions `json:"options,omitempty"`
} }
// RegistryExternal describes a minimal spec for an "external" registry // RegistryExternal describes a minimal spec for an "external" registry
// "external" meaning, that it's unrelated to the current cluster // "external" meaning, that it's unrelated to the current cluster
// e.g. used for the --registry-use flag registry reference // e.g. used for the --registry-use flag registry reference
type RegistryExternal struct { type RegistryExternal struct {
Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"` // default: http Protocol string `json:"protocol,omitempty"` // default: http
Host string `yaml:"host" json:"host"` Host string `json:"host"`
Port string `yaml:"port" json:"port"` Port string `json:"port"`
} }

@ -27,9 +27,10 @@ import (
"time" "time"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"inet.af/netaddr"
runtimeTypes "github.com/k3d-io/k3d/v5/pkg/runtimes/types" runtimeTypes "github.com/k3d-io/k3d/v5/pkg/runtimes/types"
"github.com/k3d-io/k3d/v5/pkg/types/k3s" "github.com/k3d-io/k3d/v5/pkg/types/k3s"
"inet.af/netaddr"
) )
// NodeStatusRestarting defines the status string that signals the node container is restarting // NodeStatusRestarting defines the status string that signals the node container is restarting
@ -103,34 +104,34 @@ var DoNotCopyServerFlags = []string{
} }
type HostAlias struct { type HostAlias struct {
IP string `mapstructure:"ip" yaml:"ip" json:"ip"` IP string `mapstructure:"ip" json:"ip"`
Hostnames []string `mapstructure:"hostnames" yaml:"hostnames" json:"hostnames"` Hostnames []string `mapstructure:"hostnames" json:"hostnames"`
} }
// ClusterCreateOpts describe a set of options one can set when creating a cluster // ClusterCreateOpts describe a set of options one can set when creating a cluster
type ClusterCreateOpts struct { type ClusterCreateOpts struct {
DisableImageVolume bool `yaml:"disableImageVolume" json:"disableImageVolume,omitempty"` DisableImageVolume bool `json:"disableImageVolume,omitempty"`
WaitForServer bool `yaml:"waitForServer" json:"waitForServer,omitempty"` WaitForServer bool `json:"waitForServer,omitempty"`
Timeout time.Duration `yaml:"timeout" json:"timeout,omitempty"` Timeout time.Duration `json:"timeout,omitempty"`
DisableLoadBalancer bool `yaml:"disableLoadbalancer" json:"disableLoadbalancer,omitempty"` DisableLoadBalancer bool `json:"disableLoadbalancer,omitempty"`
GPURequest string `yaml:"gpuRequest" json:"gpuRequest,omitempty"` GPURequest string `json:"gpuRequest,omitempty"`
ServersMemory string `yaml:"serversMemory" json:"serversMemory,omitempty"` ServersMemory string `json:"serversMemory,omitempty"`
AgentsMemory string `yaml:"agentsMemory" json:"agentsMemory,omitempty"` AgentsMemory string `json:"agentsMemory,omitempty"`
NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` NodeHooks []NodeHook `json:"nodeHooks,omitempty"`
GlobalLabels map[string]string `yaml:"globalLabels,omitempty" json:"globalLabels,omitempty"` GlobalLabels map[string]string `json:"globalLabels,omitempty"`
GlobalEnv []string `yaml:"globalEnv,omitempty" json:"globalEnv,omitempty"` GlobalEnv []string `json:"globalEnv,omitempty"`
HostAliases []HostAlias `yaml:"hostAliases,omitempty" json:"hostAliases,omitempty"` HostAliases []HostAlias `json:"hostAliases,omitempty"`
Registries struct { Registries struct {
Create *Registry `yaml:"create,omitempty" json:"create,omitempty"` Create *Registry `json:"create,omitempty"`
Use []*Registry `yaml:"use,omitempty" json:"use,omitempty"` Use []*Registry `json:"use,omitempty"`
Config *k3s.Registry `yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) Config *k3s.Registry `json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override)
} `yaml:"registries,omitempty" json:"registries,omitempty"` } `json:"registries,omitempty"`
} }
// NodeHook is an action that is bound to a specifc stage of a node lifecycle // NodeHook is an action that is bound to a specifc stage of a node lifecycle
type NodeHook struct { type NodeHook struct {
Stage LifecycleStage `yaml:"stage,omitempty" json:"stage,omitempty"` Stage LifecycleStage `json:"stage,omitempty"`
Action NodeHookAction `yaml:"action,omitempty" json:"action,omitempty"` Action NodeHookAction `json:"action,omitempty"`
} }
// LifecycleStage defines descriptors for specific stages in the lifecycle of a node or cluster object // LifecycleStage defines descriptors for specific stages in the lifecycle of a node or cluster object
@ -146,10 +147,10 @@ const (
type ClusterStartOpts struct { type ClusterStartOpts struct {
WaitForServer bool WaitForServer bool
Timeout time.Duration Timeout time.Duration
NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` NodeHooks []NodeHook `json:"nodeHooks,omitempty"`
EnvironmentInfo *EnvironmentInfo EnvironmentInfo *EnvironmentInfo
Intent Intent Intent Intent
HostAliases []HostAlias `yaml:"hostAliases,omitempty" json:"hostAliases,omitempty"` HostAliases []HostAlias `json:"hostAliases,omitempty"`
} }
// ClusterDeleteOpts describe a set of options one can set when deleting a cluster // ClusterDeleteOpts describe a set of options one can set when deleting a cluster
@ -161,7 +162,7 @@ type ClusterDeleteOpts struct {
type NodeCreateOpts struct { type NodeCreateOpts struct {
Wait bool Wait bool
Timeout time.Duration Timeout time.Duration
NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` NodeHooks []NodeHook `json:"nodeHooks,omitempty"`
EnvironmentInfo *EnvironmentInfo EnvironmentInfo *EnvironmentInfo
ClusterToken string ClusterToken string
} }
@ -170,7 +171,7 @@ type NodeCreateOpts struct {
type NodeStartOpts struct { type NodeStartOpts struct {
Wait bool Wait bool
Timeout time.Duration Timeout time.Duration
NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` NodeHooks []NodeHook `json:"nodeHooks,omitempty"`
ReadyLogMessage string ReadyLogMessage string
EnvironmentInfo *EnvironmentInfo EnvironmentInfo *EnvironmentInfo
Intent Intent Intent Intent
@ -212,8 +213,8 @@ type ImageImportOpts struct {
} }
type IPAM struct { type IPAM struct {
IPPrefix netaddr.IPPrefix `yaml:"ipPrefix" json:"ipPrefix,omitempty"` IPPrefix netaddr.IPPrefix `json:"ipPrefix,omitempty"`
IPsUsed []netaddr.IP `yaml:"ipsUsed" json:"ipsUsed,omitempty"` IPsUsed []netaddr.IP `json:"ipsUsed,omitempty"`
Managed bool // IPAM is done by k3d Managed bool // IPAM is done by k3d
} }
@ -224,25 +225,25 @@ type NetworkMember struct {
// ClusterNetwork describes a network which a cluster is running in // ClusterNetwork describes a network which a cluster is running in
type ClusterNetwork struct { type ClusterNetwork struct {
Name string `yaml:"name" json:"name,omitempty"` Name string `json:"name,omitempty"`
ID string `yaml:"id" json:"id"` // may be the same as name, but e.g. docker only differentiates by random ID, not by name ID string `json:"id"` // may be the same as name, but e.g. docker only differentiates by random ID, not by name
External bool `yaml:"external" json:"isExternal,omitempty"` External bool `json:"isExternal,omitempty"`
IPAM IPAM `yaml:"ipam" json:"ipam,omitempty"` IPAM IPAM `json:"ipam,omitempty"`
Members []*NetworkMember Members []*NetworkMember
} }
// Cluster describes a k3d cluster // Cluster describes a k3d cluster
type Cluster struct { type Cluster struct {
Name string `yaml:"name" json:"name,omitempty"` Name string `json:"name,omitempty"`
Network ClusterNetwork `yaml:"network" json:"network,omitempty"` Network ClusterNetwork `json:"network,omitempty"`
Token string `yaml:"clusterToken" json:"clusterToken,omitempty"` Token string `json:"clusterToken,omitempty"`
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"` Nodes []*Node `json:"nodes,omitempty"`
InitNode *Node // init server node InitNode *Node // init server node
ExternalDatastore *ExternalDatastore `yaml:"externalDatastore,omitempty" json:"externalDatastore,omitempty"` ExternalDatastore *ExternalDatastore `json:"externalDatastore,omitempty"`
KubeAPI *ExposureOpts `yaml:"kubeAPI" json:"kubeAPI,omitempty"` KubeAPI *ExposureOpts `json:"kubeAPI,omitempty"`
ServerLoadBalancer *Loadbalancer `yaml:"serverLoadbalancer,omitempty" json:"serverLoadBalancer,omitempty"` ServerLoadBalancer *Loadbalancer `json:"serverLoadBalancer,omitempty"`
ImageVolume string `yaml:"imageVolume" json:"imageVolume,omitempty"` ImageVolume string `json:"imageVolume,omitempty"`
Volumes []string `yaml:"volumes,omitempty" json:"volumes,omitempty"` // k3d-managed volumes attached to this cluster Volumes []string `json:"volumes,omitempty"` // k3d-managed volumes attached to this cluster
} }
// ServerCountRunning returns the number of server nodes running in the cluster and the total number // ServerCountRunning returns the number of server nodes running in the cluster and the total number
@ -282,49 +283,49 @@ type NodeIP struct {
// Node describes a k3d node // Node describes a k3d node
type Node struct { type Node struct {
Name string `yaml:"name" json:"name,omitempty"` Name string `json:"name,omitempty"`
Role Role `yaml:"role" json:"role,omitempty"` Role Role `json:"role,omitempty"`
Image string `yaml:"image" json:"image,omitempty"` Image string `json:"image,omitempty"`
Volumes []string `yaml:"volumes" json:"volumes,omitempty"` Volumes []string `json:"volumes,omitempty"`
Env []string `yaml:"env" json:"env,omitempty"` Env []string `json:"env,omitempty"`
Cmd []string // filled automatically based on role Cmd []string // filled automatically based on role
Args []string `yaml:"extraArgs" json:"extraArgs,omitempty"` Args []string `json:"extraArgs,omitempty"`
Ports nat.PortMap `yaml:"portMappings" json:"portMappings,omitempty"` Ports nat.PortMap `json:"portMappings,omitempty"`
Restart bool `yaml:"restart" json:"restart,omitempty"` Restart bool `json:"restart,omitempty"`
Created string `yaml:"created" json:"created,omitempty"` Created string `json:"created,omitempty"`
HostPidMode bool `yaml:"hostPidMode" json:"hostPidMode,omitempty"` HostPidMode bool `json:"hostPidMode,omitempty"`
RuntimeLabels map[string]string `yaml:"runtimeLabels" json:"runtimeLabels,omitempty"` RuntimeLabels map[string]string `json:"runtimeLabels,omitempty"`
K3sNodeLabels map[string]string `yaml:"k3sNodeLabels" json:"k3sNodeLabels,omitempty"` K3sNodeLabels map[string]string `json:"k3sNodeLabels,omitempty"`
Networks []string // filled automatically Networks []string // filled automatically
ExtraHosts []string // filled automatically (docker specific?) ExtraHosts []string // filled automatically (docker specific?)
ServerOpts ServerOpts `yaml:"serverOpts" json:"serverOpts,omitempty"` ServerOpts ServerOpts `json:"serverOpts,omitempty"`
AgentOpts AgentOpts `yaml:"agentOpts" json:"agentOpts,omitempty"` AgentOpts AgentOpts `json:"agentOpts,omitempty"`
GPURequest string // filled automatically GPURequest string // filled automatically
Memory string // filled automatically Memory string // filled automatically
State NodeState // filled automatically State NodeState // filled automatically
IP NodeIP // filled automatically -> refers solely to the cluster network IP NodeIP // filled automatically -> refers solely to the cluster network
HookActions []NodeHook `yaml:"hooks" json:"hooks,omitempty"` HookActions []NodeHook `json:"hooks,omitempty"`
} }
// ServerOpts describes some additional server role specific opts // ServerOpts describes some additional server role specific opts
type ServerOpts struct { type ServerOpts struct {
IsInit bool `yaml:"isInitializingServer" json:"isInitializingServer,omitempty"` IsInit bool `json:"isInitializingServer,omitempty"`
KubeAPI *ExposureOpts `yaml:"kubeAPI" json:"kubeAPI"` KubeAPI *ExposureOpts `json:"kubeAPI"`
} }
// ExposureOpts describes settings that the user can set for accessing the Kubernetes API // ExposureOpts describes settings that the user can set for accessing the Kubernetes API
type ExposureOpts struct { type ExposureOpts struct {
nat.PortMapping // filled automatically (reference to normal portmapping) nat.PortMapping // filled automatically (reference to normal portmapping)
Host string `yaml:"host,omitempty" json:"host,omitempty"` Host string `json:"host,omitempty"`
} }
// ExternalDatastore describes an external datastore used for HA/multi-server clusters // ExternalDatastore describes an external datastore used for HA/multi-server clusters
type ExternalDatastore struct { type ExternalDatastore struct {
Endpoint string `yaml:"endpoint" json:"endpoint,omitempty"` Endpoint string `json:"endpoint,omitempty"`
CAFile string `yaml:"caFile" json:"caFile,omitempty"` CAFile string `json:"caFile,omitempty"`
CertFile string `yaml:"certFile" json:"certFile,omitempty"` CertFile string `json:"certFile,omitempty"`
KeyFile string `yaml:"keyFile" json:"keyFile,omitempty"` KeyFile string `json:"keyFile,omitempty"`
Network string `yaml:"network" json:"network,omitempty"` Network string `json:"network,omitempty"`
} }
// AgentOpts describes some additional agent role specific opts // AgentOpts describes some additional agent role specific opts

@ -23,11 +23,7 @@ THE SOFTWARE.
package util package util
import ( import (
"bytes"
"io"
"strings" "strings"
"gopkg.in/yaml.v2"
) )
func RemoveElementFromStringSlice(slice []string, index int) []string { func RemoveElementFromStringSlice(slice []string, index int) []string {
@ -41,26 +37,3 @@ func ReplaceInAllElements(replacer *strings.Replacer, arr []string) []string {
} }
return arr return arr
} }
func SplitYAML(resources []byte) ([][]byte, error) {
dec := yaml.NewDecoder(bytes.NewReader(resources))
var res [][]byte
for {
var value interface{}
err := dec.Decode(&value)
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
valueBytes, err := yaml.Marshal(value)
if err != nil {
return nil, err
}
res = append(res, valueBytes)
}
return res, nil
}

@ -0,0 +1,57 @@
package util
import (
"bytes"
"io"
goyaml "gopkg.in/yaml.v2"
"sigs.k8s.io/yaml"
)
func SplitYAML(resources []byte) ([][]byte, error) {
dec := goyaml.NewDecoder(bytes.NewReader(resources))
var res [][]byte
for {
var value interface{}
err := dec.Decode(&value)
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
valueBytes, err := goyaml.Marshal(value)
if err != nil {
return nil, err
}
res = append(res, valueBytes)
}
return res, nil
}
type YAMLEncoder struct {
encoder *goyaml.Encoder
}
func NewYAMLEncoder(w io.Writer) *YAMLEncoder {
return &YAMLEncoder{
encoder: goyaml.NewEncoder(w),
}
}
func (e *YAMLEncoder) Encode(v interface{}) (err error) {
data, err := yaml.Marshal(v)
if err != nil {
return err
}
var doc interface{}
if err := yaml.Unmarshal(data, &doc); err != nil {
return err
}
return e.encoder.Encode(doc)
}
func (e *YAMLEncoder) Close() (err error) {
return e.encoder.Close()
}

@ -0,0 +1,94 @@
package util
import (
"bytes"
"strings"
"testing"
"gotest.tools/assert"
)
type DummyContext struct {
Name string
}
type DummyContextWithTag struct {
Name string `json:"newName"`
}
func TestSplitYAML(t *testing.T) {
testSets := map[string]struct {
document string
expected []string
}{
"single": {
document: `name: clusterA`,
expected: []string{
`name: clusterA`,
},
},
"multiple": {
document: `name: clusterA
---
name: clusterB
`,
expected: []string{
`name: clusterA`,
`name: clusterB`,
},
},
}
for name, testSet := range testSets {
t.Run(name, func(t *testing.T) {
actual, err := SplitYAML([]byte(testSet.document))
assert.NilError(t, err)
assert.Equal(t, len(testSet.expected), len(actual))
for idx := range testSet.expected {
assert.Equal(t, testSet.expected[idx], strings.TrimSpace(string(actual[idx])))
}
})
}
}
func TestYAMLEncoder(t *testing.T) {
testSets := map[string]struct {
values []interface{}
expected string
}{
"single value": {
values: []interface{}{
DummyContext{Name: "clusterA"},
},
expected: `Name: clusterA
`,
},
"single value with json tag": {
values: []interface{}{
DummyContextWithTag{Name: "clusterA"},
},
expected: `newName: clusterA
`,
},
"multiple values": {
values: []interface{}{
DummyContext{Name: "clusterA"},
DummyContextWithTag{Name: "clusterB"},
},
expected: `Name: clusterA
---
newName: clusterB
`,
},
}
for name, testSet := range testSets {
t.Run(name, func(t *testing.T) {
var buf bytes.Buffer
enc := NewYAMLEncoder(&buf)
for _, v := range testSet.values {
assert.NilError(t, enc.Encode(v))
}
assert.NilError(t, enc.Close())
assert.Equal(t, testSet.expected, buf.String())
})
}
}
Loading…
Cancel
Save