diff --git a/cmd/root.go b/cmd/root.go index b7526da..c408475 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,3 +1,5 @@ +// Copyright The KCL Authors. All rights reserved. +// // #### Language & Tooling Commands // // ``` @@ -69,10 +71,10 @@ package cmd import ( "github.com/spf13/cobra" + "kcl-lang.io/cli/pkg/version" ) -const rootCmdShortUsage = "The KCL Command Line Interface (CLI)." -const rootCmdLongUsage = `The KCL Command Line Interface (CLI). +const rootDesc = `The KCL Command Line Interface (CLI). KCL is an open-source, constraint-based record and functional language that enhances the writing of complex configurations, including those for cloud-native @@ -83,9 +85,10 @@ scenarios. The KCL website: https://kcl-lang.io func New() *cobra.Command { cmd := &cobra.Command{ Use: "kcl", - Short: rootCmdShortUsage, - Long: rootCmdLongUsage, + Short: "The KCL Command Line Interface (CLI).", + Long: rootDesc, SilenceUsage: true, + Version: version.GetVersionString(), } cmd.AddCommand(NewVersionCmd()) cmd.AddCommand(NewRunCmd()) diff --git a/cmd/run.go b/cmd/run.go index 9227abd..0057a40 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,38 +1,83 @@ +// Copyright The KCL Authors. All rights reserved. + package cmd import ( "github.com/spf13/cobra" - "k8s.io/kubectl/pkg/util/i18n" "kcl-lang.io/cli/pkg/options" ) +const ( + runDesc = ` +This command runs the kcl code and displays the output. 'kcl run' takes multiple input for arguments. + +For example, 'kcl run path/to/kcl.k' will run the file named path/to/kcl.k +` + runExample = ` # Run a single file and output YAML + kcl run path/to/kcl.k + + # Run a single file and output JSON + kcl run path/to/kcl.k --format json + + # Run multiple files + kcl run path/to/kcl1.k path/to/kcl2.k + + # Run OCI packages + kcl run oci://ghcr.io/kcl-lang/hello-world + + # Run the current package + kcl run + ` +) + // NewRunCmd returns the run command. func NewRunCmd() *cobra.Command { o := options.NewRunOptions() cmd := &cobra.Command{ - Use: "run", - Short: "Run KCL codes.", + Use: "run", + Short: "Run KCL codes.", + Long: runDesc, + Example: runExample, RunE: func(_ *cobra.Command, args []string) error { - o.Entries = args - err := o.Run() - if err != nil { + if err := o.Complete(args); err != nil { + return err + } + if err := o.Validate(); err != nil { return err } - return nil + return o.Run() }, SilenceUsage: true, } cmd.Flags().StringSliceVarP(&o.Arguments, "argument", "D", []string{}, - i18n.T("Specify the top-level argument")) + "Specify the top-level argument") cmd.Flags().StringSliceVarP(&o.Settings, "setting", "Y", []string{}, - i18n.T("Specify the command line setting files")) - cmd.Flags().StringVarP(&o.Output, "output", "o", "", - i18n.T("Specify the output file")) - cmd.Flags().BoolVarP(&o.DisableNone, "disable-none", "n", false, - i18n.T("Disable dumping None values")) + "Specify the command line setting files") cmd.Flags().StringSliceVarP(&o.Overrides, "overrides", "O", []string{}, - i18n.T("Specify the configuration override path and value")) + "Specify the configuration override path and value") + cmd.Flags().StringSliceVarP(&o.PathSelectors, "path_selectors", "S", []string{}, + "Specify the path selectors") + cmd.Flags().StringSliceVarP(&o.ExternalPackages, "external", "E", []string{}, + " Mapping of package name and path where the package is located") + cmd.Flags().StringVarP(&o.Output, "output", "o", "", + "Specify the YAML/JSON output file path") + cmd.Flags().StringVarP(&o.Tag, "tag", "t", "", + "Specify the tag for the OCI or Git artifact") + cmd.Flags().StringVar(&o.Format, "format", "yaml", + "Specify the output format") + cmd.Flags().BoolVarP(&o.DisableNone, "disable_none", "n", false, + "Disable dumping None values") + cmd.Flags().BoolVarP(&o.StrictRangeCheck, "strict_range_check", "r", false, + "Do perform strict numeric range checks") + cmd.Flags().BoolVarP(&o.Debug, "debug", "d", false, + "Run in debug mode") + cmd.Flags().BoolVarP(&o.SortKeys, "sort_keys", "k", false, + "Sort output result keys") + cmd.Flags().BoolVarP(&o.Vendor, "vendor", "V", false, + "Sort output result keys") + cmd.Flags().BoolVar(&o.NoStyle, "no_style", false, + "Sort output result keys") return cmd } diff --git a/cmd/run_test.go b/cmd/run_test.go new file mode 100644 index 0000000..2e75ded --- /dev/null +++ b/cmd/run_test.go @@ -0,0 +1,53 @@ +package cmd + +import ( + "strings" + "testing" +) + +func TestNewRunCmd(t *testing.T) { + cmd := NewRunCmd() + + if cmd.Use != "run" { + t.Errorf("unexpected command use: %s", cmd.Use) + } + + if cmd.Short != "Run KCL codes." { + t.Errorf("unexpected command short description: %s", cmd.Short) + } + + if cmd.Long != runDesc { + t.Errorf("unexpected command long description: %s", cmd.Long) + } + + if cmd.Example != runExample { + t.Errorf("unexpected command example: %s", cmd.Example) + } + + if cmd.SilenceUsage != true { + t.Errorf("unexpected SilenceUsage value: %v", cmd.SilenceUsage) + } + + runE := cmd.RunE + if runE == nil { + t.Fatal("RunE function is nil") + } + + args := []string{"../examples/kubernetes.k"} + err := runE(cmd, args) + if err != nil { + t.Errorf("RunE function returned an error: %v", err) + } + + args = []string{"error.k"} + err = runE(cmd, args) + if !strings.Contains(err.Error(), "Cannot find the kcl file") { + t.Errorf("RunE function returned an error: %v", err) + } + + args = []string{"error.k"} + err = runE(cmd, args) + if !strings.Contains(err.Error(), "Cannot find the kcl file") { + t.Errorf("RunE function returned an error: %v", err) + } +} diff --git a/cmd/version.go b/cmd/version.go index d474914..8f51f3d 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,3 +1,5 @@ +// Copyright The KCL Authors. All rights reserved. + package cmd import ( diff --git a/go.mod b/go.mod index eb56db7..f65f6b0 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module kcl-lang.io/cli go 1.19 require ( + github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/spf13/cobra v1.7.0 - k8s.io/kubectl v0.28.3 kcl-lang.io/kcl-go v0.6.1-0.20231023065115-16ee99bd07f7 kcl-lang.io/kcl-openapi v0.5.1 kcl-lang.io/kpm v0.3.7 @@ -53,7 +53,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc4 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/errors v0.9.1 github.com/powerman/rpc-codec v1.2.2 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect @@ -90,7 +90,6 @@ require ( github.com/Microsoft/go-winio v0.6.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect - github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudflare/circl v1.1.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.0 // indirect diff --git a/go.sum b/go.sum index 9ef7463..72890ac 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0g github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -106,8 +108,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/chai2010/jsonv v1.1.3 h1:gBIHXn/5mdEPTuWZfjC54fn/yUSRR8OGobXobcc6now= github.com/chai2010/jsonv v1.1.3/go.mod h1:mEoT1dQ9qVF4oP9peVTl0UymTmJwXoTDOh+sNA6+XII= github.com/chai2010/protorpc v1.1.4 h1:CTtFUhzXRoeuR7FtgQ2b2vdT/KgWVpCM+sIus8zJjHs= @@ -1142,8 +1142,6 @@ k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/kubectl v0.28.3 h1:H1Peu1O3EbN9zHkJCcvhiJ4NUj6lb88sGPO5wrWIM6k= -k8s.io/kubectl v0.28.3/go.mod h1:RDAudrth/2wQ3Sg46fbKKl4/g+XImzvbsSRZdP2RiyE= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= diff --git a/pkg/options/run.go b/pkg/options/run.go index 414e4ad..95ac577 100644 --- a/pkg/options/run.go +++ b/pkg/options/run.go @@ -1,43 +1,69 @@ +// Copyright The KCL Authors. All rights reserved. + package options import ( + "bufio" + "fmt" "io" "os" + "strings" + "github.com/acarl005/stripansi" + "github.com/pkg/errors" "kcl-lang.io/kcl-go/pkg/kcl" "kcl-lang.io/kpm/pkg/api" "kcl-lang.io/kpm/pkg/client" "kcl-lang.io/kpm/pkg/opt" - "kcl-lang.io/kpm/pkg/reporter" "kcl-lang.io/kpm/pkg/runner" ) -type FormatType string - const ( - Json FormatType = "json" - Yaml FormatType = "yaml" + // Json is the JSON output format. + Json string = "json" + // Yaml is the YAML output format. + Yaml string = "yaml" ) +// RunOptions is a struct that holds the options for the run command. type RunOptions struct { - Entries []string // List of entry points - Output string // Output path - Settings []string // List of settings - Arguments []string // List of arguments - Overrides []string // List of overrides - PathSelectors []string // List of path selectors - ExternalPackages []string // List of external packages - NoStyle bool // Disable style check - Vendor bool // Use vendor directory - SortKeys bool // Sort keys - DisableNone bool // Disable empty options - StrictRangeCheck bool // Strict range check - Tag string // Tag - CheckOnly bool // Check only mode - Format FormatType // Formatting type - Writer io.Writer // Writer + // Entries is the list of the kcl code entry including filepath, folder, OCI package, etc. + Entries []string + // Output is the result output filepath. Default is os.Stdout. + Output string + // Settings is the list of kcl setting files including all of the CLI config. + Settings []string + // Arguments is the list of top level dynamic arguments for the kcl option function, e.g., env="prod" + Arguments []string + // Overrides is the list of override paths and values, e.g., app.image="v2" + Overrides []string + // PathSelectors is the list of path selectors to select output result, e.g., a.b.c + PathSelectors []string + // ExternalPackages denotes the list of external packages, e.g., k8s=./vendor/k8s + ExternalPackages []string + // NoStyle denotes disabling the output information style and color. + NoStyle bool + // Vendor denotes running kcl in the vendor mode. + Vendor bool + // SortKeys denotes sorting the output result keys, e.g., `{b = 1, a = 2} => {a = 2, b = 1}`. + SortKeys bool + // DisableNone denotes running kcl and disable dumping None values. + DisableNone bool + // Debug denotes running kcl in debug mode. + Debug bool + // StrictRangeCheck performs the 32-bit strict numeric range checks on numbers. + StrictRangeCheck bool + // Tag is the package tag of the OCI or Git artifact. + Tag string + // CheckOnly is used to check a local package and all of its dependencies for errors. + CheckOnly bool + // Format is the output type, e.g., Json, Yaml, etc. Default is Yaml. + Format string + // Writer is used to output the run result. Default is os.Stdout. + Writer io.Writer } +// NewRunOptions returns a new instance of RunOptions with default values. func NewRunOptions() *RunOptions { return &RunOptions{ Writer: os.Stdout, @@ -45,73 +71,121 @@ func NewRunOptions() *RunOptions { } } +// Run runs the kcl run command with options. func (o *RunOptions) Run() error { + var result *kcl.KCLResultList + var err error opts := CompileOptionFromCli(o) cli, err := client.NewKpmClient() if err != nil { - reporter.Fatal(err) + return err + } + pwd, err := os.Getwd() + if err != nil { + return err } entry, errEvent := runner.FindRunEntryFrom(opts.Entries()) if errEvent != nil { return errEvent } - var result *kcl.KCLResultList - // kcl compiles the current package under '$pwd'. if entry.IsEmpty() { - pwd, err := os.Getwd() - opts.SetPkgPath(pwd) - if err != nil { - return reporter.NewErrorEvent( - reporter.Bug, err, "internal bugs, please contact us to fix it.", - ) - } - result, err = cli.CompileWithOpts(opts) - if err != nil { - return err + // kcl compiles the current package under '$pwd'. + if _, found := api.GetKclPackage(pwd); found == nil { + opts.SetPkgPath(pwd) + result, err = cli.CompileWithOpts(opts) + } else { + // If there is only kcl file without kcl package (kcl.mod) + result, err = api.RunWithOpt(opts) } } else { - var err error // kcl compiles the package from the local file system. if entry.IsLocalFile() || entry.IsLocalFileWithKclMod() { if entry.IsLocalFile() { - // If there is only kcl file without kcl package, + // If there is only kcl file without kcl package (kcl.mod) result, err = api.RunWithOpt(opts) } else { - // Else compile the kcl package. + // Else compile the kcl package (kcl.mod) result, err = cli.CompileWithOpts(opts) } } else if entry.IsTar() { // kcl compiles the package from the kcl package tar. result, err = cli.CompileTarPkg(entry.PackageSource(), opts) - } else { + } else if entry.IsUrl() { // kcl compiles the package from the OCI reference or url. result, err = cli.CompileOciPkg(entry.PackageSource(), o.Tag, opts) - } - if err != nil { - return err + } else { + // If there is only kcl file without kcl package (kcl.mod) + result, err = api.RunWithOpt(opts) } } - _, err = opts.LogWriter().Write([]byte(result.GetRawYamlResult() + "\n")) if err != nil { + if o.NoStyle { + err = errors.New(stripansi.Strip(err.Error())) + } return err } + return o.writeResult(result) +} + +// Complete completes the options based on the provided arguments. +func (o *RunOptions) Complete(args []string) error { + o.Entries = args return nil } +// Validate validates the options. func (o *RunOptions) Validate() error { + if o.Format != "" && strings.ToLower(o.Format) != Json && strings.ToLower(o.Format) != Yaml { + return fmt.Errorf("invalid output format, expected %v, got %v", []string{Json, Yaml}, o.Format) + } return nil } -// CompileOptionFromCli will parse the kcl options from the cli context. +// writer returns the writer to use for output. +func (o *RunOptions) writer() (io.Writer, error) { + if o.Output == "" { + return o.Writer, nil + } else { + file, err := os.OpenFile(o.Output, os.O_CREATE|os.O_RDWR, 0744) + if err != nil { + return nil, err + } + return bufio.NewWriter(file), nil + } +} + +func (o *RunOptions) writeResult(result *kcl.KCLResultList) error { + if result == nil { + return nil + } + // Get the writer and output the kcl result. + writer, err := o.writer() + if err != nil { + return err + } + var output []byte + if strings.ToLower(o.Format) == Json { + // If we have multiple result, output the JSON array format, else output the single JSON object. + if result.Len() > 1 { + output = []byte(result.GetRawJsonResult() + "\n") + } else { + output = []byte(result.First().JSONString() + "\n") + } + } else { + // Both considering the raw YAML format and the YAML stream format that contains the `---` separator. + output = []byte(result.GetRawYamlResult() + "\n") + } + _, err = writer.Write(output) + return err +} + +// CompileOptionFromCli will parse the kcl options from the cli options. func CompileOptionFromCli(o *RunOptions) *opt.CompileOptions { opts := opt.DefaultCompileOptions() - // --input + // opts.ExtendEntries(o.Entries) - // --vendor - opts.SetVendor(o.Vendor) - // --setting, -Y if len(o.Settings) != 0 { for _, sPath := range o.Settings { @@ -137,8 +211,19 @@ func CompileOptionFromCli(o *RunOptions) *opt.CompileOptions { // --disable_none, -n opts.Merge(kcl.WithDisableNone(o.DisableNone)) + // --external, -E + opts.Merge(kcl.WithExternalPkgs(o.ExternalPackages...)) + // --sort_keys, -k opts.Merge(kcl.WithSortKeys(o.SortKeys)) + // --strict_range_check, -r + opts.StrictRangeCheck = o.StrictRangeCheck + + // --vendor + opts.SetVendor(o.Vendor) + + // TODO: path_selector, check_only + return opts } diff --git a/pkg/options/run_test.go b/pkg/options/run_test.go new file mode 100644 index 0000000..b2bce68 --- /dev/null +++ b/pkg/options/run_test.go @@ -0,0 +1,154 @@ +package options + +import ( + "bytes" + "testing" +) + +func TestRunOptions_Run(t *testing.T) { + options := NewRunOptions() + options.Entries = []string{"./testdata/run/kubernetes.k"} + + // test yaml output + var buf1 bytes.Buffer + options.Writer = &buf1 + options.Format = Yaml + options.SortKeys = true + + err := options.Run() + if err != nil { + t.Errorf("RunOptions.Run() failed: %v", err) + } + + expectedOutput := `apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: nginx + name: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - image: nginx:1.14.2 + name: nginx + ports: + - containerPort: 80 +` + + if got := buf1.String(); got != expectedOutput { + t.Errorf("\nexpected: %s\ngot: %s", expectedOutput, got) + } + + // test json output + var buf2 bytes.Buffer + options.Writer = &buf2 + options.Format = Json + options.SortKeys = false + + err = options.Run() + if err != nil { + t.Errorf("RunOptions.Run() failed: %v", err) + } + + expectedOutput = `{ + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "labels": { + "app": "nginx" + }, + "name": "nginx" + }, + "spec": { + "replicas": 3, + "selector": { + "matchLabels": { + "app": "nginx" + } + }, + "template": { + "metadata": { + "labels": { + "app": "nginx" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:1.14.2", + "name": "nginx", + "ports": [ + { + "containerPort": 80 + } + ] + } + ] + } + } + } +} +` + + if got := buf2.String(); got != expectedOutput { + t.Errorf("\nexpected: %s\ngot: %s", expectedOutput, got) + } +} + +func TestRunOptions_Complete(t *testing.T) { + options := NewRunOptions() + args := []string{"file1.k", "file2.k", "file3.k"} + + err := options.Complete(args) + if err != nil { + t.Errorf("RunOptions.Complete() failed: %v", err) + } + + expectedEntries := []string{"file1.k", "file2.k", "file3.k"} + + if len(options.Entries) != len(expectedEntries) { + t.Fatalf("unexpected number of entries:\nexpected: %d\ngot: %d", len(expectedEntries), len(options.Entries)) + } + + for i := range options.Entries { + if options.Entries[i] != expectedEntries[i] { + t.Errorf("unexpected entry at index %d:\nexpected: %s\ngot: %s", i, expectedEntries[i], options.Entries[i]) + } + } +} + +func TestRunOptions_Validate(t *testing.T) { + options := NewRunOptions() + options.Format = "invalid_format" + + err := options.Validate() + if err == nil { + t.Errorf("RunOptions.Validate() did not return an error") + } else { + expectedError := "invalid output format, expected [json yaml], got invalid_format" + if err.Error() != expectedError { + t.Errorf("unexpected error message:\nexpected: %s\ngot: %s", expectedError, err.Error()) + } + } +} + +func TestRunOptions_writer(t *testing.T) { + options := NewRunOptions() + + writer, err := options.writer() + if err != nil { + t.Fatalf("RunOptions.writer() failed: %v", err) + } + + if writer == nil { + t.Fatalf("writer should not be nil") + } +} diff --git a/pkg/options/testdata/run/kubernetes.k b/pkg/options/testdata/run/kubernetes.k new file mode 100644 index 0000000..357c2d2 --- /dev/null +++ b/pkg/options/testdata/run/kubernetes.k @@ -0,0 +1,18 @@ +apiVersion = "apps/v1" +kind = "Deployment" +metadata = { + name = "nginx" + labels.app = "nginx" +} +spec = { + replicas = 3 + selector.matchLabels = metadata.labels + template.metadata.labels = metadata.labels + template.spec.containers = [ + { + name = metadata.name + image = "${metadata.name}:1.14.2" + ports = [{ containerPort = 80 }] + } + ] +} diff --git a/pkg/version/version.go b/pkg/version/version.go index 2354452..1dd8ca6 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -5,8 +5,8 @@ package version // version will be set by build flags. var version string -// GetVersionInStr() will return the latest version of kpm. -func GetVersionInStr() string { +// GetVersionString() will return the latest version of kpm. +func GetVersionString() string { if len(version) == 0 { // If version is not set by build flags, return the version constant. return VersionTypeLatest.String() diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go index 2b47922..fdbf2e0 100644 --- a/pkg/version/version_test.go +++ b/pkg/version/version_test.go @@ -2,7 +2,7 @@ package version import "testing" -func TestGetVersionInStr(t *testing.T) { +func TestGetVersionString(t *testing.T) { tests := []struct { name string want string @@ -14,8 +14,8 @@ func TestGetVersionInStr(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := GetVersionInStr(); got != tt.want { - t.Errorf("GetVersionInStr() = %v, want %v", got, tt.want) + if got := GetVersionString(); got != tt.want { + t.Errorf(" GetVersionString() = %v, want %v", got, tt.want) } }) }