Skip to content

Commit

Permalink
Add helm get metadata command
Browse files Browse the repository at this point in the history
Signed-off-by: Mikhail Kopylov <mih.kopylov@yandex.ru>
  • Loading branch information
mih-kopylov committed Dec 12, 2022
1 parent f91b515 commit 593dd0a
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/helm/get.go
Expand Up @@ -48,6 +48,7 @@ func newGetCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
cmd.AddCommand(newGetManifestCmd(cfg, out))
cmd.AddCommand(newGetHooksCmd(cfg, out))
cmd.AddCommand(newGetNotesCmd(cfg, out))
cmd.AddCommand(newGetMetadataCmd(cfg, out))

return cmd
}
94 changes: 94 additions & 0 deletions cmd/helm/get_metadata.go
@@ -0,0 +1,94 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"fmt"
"io"
"log"

"github.com/spf13/cobra"

"helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli/output"
)

type metadataWriter struct {
metadata *action.Metadata
}

func newGetMetadataCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
var outfmt output.Format
client := action.NewGetMetadata(cfg)

cmd := &cobra.Command{
Use: "metadata RELEASE_NAME",
Short: "This command fetches metadata for a given release",
Args: require.ExactArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return compListReleases(toComplete, args, cfg)
},
RunE: func(cmd *cobra.Command, args []string) error {
releaseMetadata, err := client.Run(args[0])
if err != nil {
return err
}
return outfmt.Write(out, &metadataWriter{releaseMetadata})
},
}

f := cmd.Flags()
f.IntVar(&client.Version, "revision", 0, "specify release revision")
err := cmd.RegisterFlagCompletionFunc("revision", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 {
return compListRevisions(toComplete, cfg, args[0])
}
return nil, cobra.ShellCompDirectiveNoFileComp
})

if err != nil {
log.Fatal(err)
}

bindOutputFlag(cmd, &outfmt)

return cmd
}

func (w metadataWriter) WriteTable(out io.Writer) error {
_, _ = fmt.Fprintln(out, fmt.Sprintf("NAME: %v", w.metadata.Name))
_, _ = fmt.Fprintln(out, fmt.Sprintf("CHART: %v", w.metadata.Chart))
_, _ = fmt.Fprintln(out, fmt.Sprintf("VERSION: %v", w.metadata.Version))
_, _ = fmt.Fprintln(out, fmt.Sprintf("APP_VERSION: %v", w.metadata.AppVersion))
_, _ = fmt.Fprintln(out, fmt.Sprintf("NAMESPACE: %v", w.metadata.Namespace))
_, _ = fmt.Fprintln(out, fmt.Sprintf("REVISION: %v", w.metadata.Revision))
_, _ = fmt.Fprintln(out, fmt.Sprintf("STATUS: %v", w.metadata.Status))
_, _ = fmt.Fprintln(out, fmt.Sprintf("DEPLOYED_AT: %v", w.metadata.DeployedAt))
return nil
}

func (w metadataWriter) WriteJSON(out io.Writer) error {
return output.EncodeJSON(out, w.metadata)
}

func (w metadataWriter) WriteYAML(out io.Writer) error {
return output.EncodeYAML(out, w.metadata)
}
66 changes: 66 additions & 0 deletions cmd/helm/get_metadata_test.go
@@ -0,0 +1,66 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"testing"

"helm.sh/helm/v3/pkg/release"
)

func TestGetMetadataCmd(t *testing.T) {
tests := []cmdTestCase{{
name: "get metadata with a release",
cmd: "get metadata thomas-guide",
golden: "output/get-metadata.txt",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})},
}, {
name: "get metadata requires release name arg",
cmd: "get metadata",
golden: "output/get-metadata-args.txt",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})},
wantError: true,
}, {
name: "get metadata to json",
cmd: "get metadata thomas-guide --output json",
golden: "output/get-metadata.json",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})},
}, {
name: "get metadata to yaml",
cmd: "get metadata thomas-guide --output yaml",
golden: "output/get-metadata.yaml",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "thomas-guide"})},
}}
runTestCmd(t, tests)
}

func TestGetMetadataCompletion(t *testing.T) {
checkReleaseCompletion(t, "get metadata", false)
}

func TestGetMetadataRevisionCompletion(t *testing.T) {
revisionFlagCompletionTest(t, "get metadata")
}

func TestGetMetadataOutputCompletion(t *testing.T) {
outputFlagCompletionTest(t, "get metadata")
}

func TestGetMetadataFileCompletion(t *testing.T) {
checkFileCompletion(t, "get metadata", false)
checkFileCompletion(t, "get metadata myrelease", false)
}
3 changes: 3 additions & 0 deletions cmd/helm/testdata/output/get-metadata-args.txt
@@ -0,0 +1,3 @@
Error: "helm get metadata" requires 1 argument

Usage: helm get metadata RELEASE_NAME [flags]
1 change: 1 addition & 0 deletions cmd/helm/testdata/output/get-metadata.json
@@ -0,0 +1 @@
{"name":"thomas-guide","chart":"foo","version":"0.1.0-beta.1","appVersion":"1.0","namespace":"default","revision":1,"status":"deployed","deployedAt":"1977-09-02T22:04:05Z"}
8 changes: 8 additions & 0 deletions cmd/helm/testdata/output/get-metadata.txt
@@ -0,0 +1,8 @@
NAME: thomas-guide
CHART: foo
VERSION: 0.1.0-beta.1
APP_VERSION: 1.0
NAMESPACE: default
REVISION: 1
STATUS: deployed
DEPLOYED_AT: 1977-09-02T22:04:05Z
8 changes: 8 additions & 0 deletions cmd/helm/testdata/output/get-metadata.yaml
@@ -0,0 +1,8 @@
appVersion: "1.0"
chart: foo
deployedAt: "1977-09-02T22:04:05Z"
name: thomas-guide
namespace: default
revision: 1
status: deployed
version: 0.1.0-beta.1
69 changes: 69 additions & 0 deletions pkg/action/get_metadata.go
@@ -0,0 +1,69 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package action

import "time"

// GetMetadata is the action for checking a given release's metadata.
//
// It provides the implementation of 'helm get metadata'.
type GetMetadata struct {
cfg *Configuration

Version int
}

type Metadata struct {
Name string `json:"name" yaml:"name"`
Chart string `json:"chart" yaml:"chart"`
Version string `json:"version" yaml:"version"`
AppVersion string `json:"appVersion" yaml:"appVersion"`
Namespace string `json:"namespace" yaml:"namespace"`
Revision int `json:"revision" yaml:"revision"`
Status string `json:"status" yaml:"status"`
DeployedAt string `json:"deployedAt" yaml:"deployedAt"`
}

// NewGetMetadata creates a new GetMetadata object with the given configuration.
func NewGetMetadata(cfg *Configuration) *GetMetadata {
return &GetMetadata{
cfg: cfg,
}
}

// Run executes 'helm get metadata' against the given release.
func (g *GetMetadata) Run(name string) (*Metadata, error) {
if err := g.cfg.KubeClient.IsReachable(); err != nil {
return nil, err
}

rel, err := g.cfg.releaseContent(name, g.Version)
if err != nil {
return nil, err
}

return &Metadata{
Name: rel.Name,
Chart: rel.Chart.Metadata.Name,
Version: rel.Chart.Metadata.Version,
AppVersion: rel.Chart.Metadata.AppVersion,
Namespace: rel.Namespace,
Revision: rel.Version,
Status: rel.Info.Status.String(),
DeployedAt: rel.Info.LastDeployed.Format(time.RFC3339),
}, nil
}

0 comments on commit 593dd0a

Please sign in to comment.