mirror of https://github.com/helm/helm
Merge pull request #6272 from adamreese/feat/initless
feat(cmd/helm): remove need for helm init commandpull/6286/head v3.0.0-beta.1
commit
f76b5f21ad
@ -1,234 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"helm.sh/helm/cmd/helm/require"
|
||||
"helm.sh/helm/pkg/helmpath"
|
||||
"helm.sh/helm/pkg/plugin"
|
||||
"helm.sh/helm/pkg/plugin/installer"
|
||||
"helm.sh/helm/pkg/repo"
|
||||
)
|
||||
|
||||
const initDesc = `
|
||||
This command sets up local configuration.
|
||||
|
||||
Helm stores configuration based on the XDG base directory specification, so
|
||||
|
||||
- cached files are stored in $XDG_CACHE_HOME/helm
|
||||
- configuration is stored in $XDG_CONFIG_HOME/helm
|
||||
- data is stored in $XDG_DATA_HOME/helm
|
||||
|
||||
By default, the default directories depend on the Operating System. The defaults are listed below:
|
||||
|
||||
+------------------+---------------------------+--------------------------------+-------------------------+
|
||||
| Operating System | Cache Path | Configuration Path | Data Path |
|
||||
+------------------+---------------------------+--------------------------------+-------------------------+
|
||||
| Linux | $HOME/.cache/helm | $HOME/.config/helm | $HOME/.local/share/helm |
|
||||
| macOS | $HOME/Library/Caches/helm | $HOME/Library/Preferences/helm | $HOME/Library/helm |
|
||||
| Windows | %TEMP%\helm | %APPDATA%\helm | %APPDATA%\helm |
|
||||
+------------------+---------------------------+--------------------------------+-------------------------+
|
||||
`
|
||||
|
||||
type initOptions struct {
|
||||
skipRefresh bool // --skip-refresh
|
||||
pluginsFilename string // --plugins
|
||||
}
|
||||
|
||||
type pluginsFileEntry struct {
|
||||
URL string `json:"url"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type pluginsFile struct {
|
||||
Plugins []*pluginsFileEntry `json:"plugins"`
|
||||
}
|
||||
|
||||
func newInitCmd(out io.Writer) *cobra.Command {
|
||||
o := &initOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "initialize Helm client",
|
||||
Long: initDesc,
|
||||
Args: require.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return o.run(out)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.BoolVar(&o.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache")
|
||||
f.StringVar(&o.pluginsFilename, "plugins", "", "a YAML file specifying plugins to install")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// run initializes local config.
|
||||
func (o *initOptions) run(out io.Writer) error {
|
||||
if err := ensureDirectories(out); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureReposFile(out, o.skipRefresh); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureRepoFileFormat(helmpath.RepositoryFile(), out); err != nil {
|
||||
return err
|
||||
}
|
||||
if o.pluginsFilename != "" {
|
||||
if err := ensurePluginsInstalled(o.pluginsFilename, out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(out, "Helm is now configured to use the following directories:")
|
||||
fmt.Fprintf(out, "Cache: %s\n", helmpath.CachePath())
|
||||
fmt.Fprintf(out, "Configuration: %s\n", helmpath.ConfigPath())
|
||||
fmt.Fprintf(out, "Data: %s\n", helmpath.DataPath())
|
||||
fmt.Fprintln(out, "Happy Helming!")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensureDirectories checks to see if the directories Helm uses exists.
|
||||
//
|
||||
// If they do not exist, this function will create it.
|
||||
func ensureDirectories(out io.Writer) error {
|
||||
directories := []string{
|
||||
helmpath.CachePath(),
|
||||
helmpath.ConfigPath(),
|
||||
helmpath.DataPath(),
|
||||
helmpath.RepositoryCache(),
|
||||
helmpath.Plugins(),
|
||||
helmpath.PluginCache(),
|
||||
helmpath.Starters(),
|
||||
helmpath.Archive(),
|
||||
}
|
||||
for _, p := range directories {
|
||||
if fi, err := os.Stat(p); err != nil {
|
||||
fmt.Fprintf(out, "Creating %s \n", p)
|
||||
if err := os.MkdirAll(p, 0755); err != nil {
|
||||
return errors.Wrapf(err, "could not create %s", p)
|
||||
}
|
||||
} else if !fi.IsDir() {
|
||||
return errors.Errorf("%s must be a directory", p)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureReposFile(out io.Writer, skipRefresh bool) error {
|
||||
repoFile := helmpath.RepositoryFile()
|
||||
if fi, err := os.Stat(repoFile); err != nil {
|
||||
fmt.Fprintf(out, "Creating %s \n", repoFile)
|
||||
f := repo.NewFile()
|
||||
if err := f.WriteFile(repoFile, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if fi.IsDir() {
|
||||
return errors.Errorf("%s must be a file, not a directory", repoFile)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureRepoFileFormat(file string, out io.Writer) error {
|
||||
r, err := repo.LoadFile(file)
|
||||
if err == repo.ErrRepoOutOfDate {
|
||||
fmt.Fprintln(out, "Updating repository file format...")
|
||||
if err := r.WriteFile(file, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensurePluginsInstalled(pluginsFilename string, out io.Writer) error {
|
||||
bytes, err := ioutil.ReadFile(pluginsFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pf := new(pluginsFile)
|
||||
if err := yaml.Unmarshal(bytes, &pf); err != nil {
|
||||
return errors.Wrapf(err, "failed to parse %s", pluginsFilename)
|
||||
}
|
||||
|
||||
for _, requiredPlugin := range pf.Plugins {
|
||||
if err := ensurePluginInstalled(requiredPlugin, pluginsFilename, out); err != nil {
|
||||
return errors.Wrapf(err, "failed to install plugin from %s", requiredPlugin.URL)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensurePluginInstalled(requiredPlugin *pluginsFileEntry, pluginsFilename string, out io.Writer) error {
|
||||
i, err := installer.NewForSource(requiredPlugin.URL, requiredPlugin.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, pathErr := os.Stat(i.Path()); os.IsNotExist(pathErr) {
|
||||
if err := installer.Install(i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := plugin.LoadDir(i.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := runHook(p, plugin.Install); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "Installed plugin: %s\n", p.Metadata.Name)
|
||||
} else if requiredPlugin.Version != "" {
|
||||
p, err := plugin.LoadDir(i.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Metadata.Version != "" {
|
||||
pluginVersion, err := semver.NewVersion(p.Metadata.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
constraint, err := semver.NewConstraint(requiredPlugin.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !constraint.Check(pluginVersion) {
|
||||
fmt.Fprintf(out, "WARNING: Installed plugin '%s' is at version %s, while %s specifies %s\n",
|
||||
p.Metadata.Name, p.Metadata.Version, pluginsFilename, requiredPlugin.Version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"helm.sh/helm/internal/test/ensure"
|
||||
"helm.sh/helm/pkg/helmpath"
|
||||
)
|
||||
|
||||
const testPluginsFile = "testdata/plugins.yaml"
|
||||
|
||||
func TestEnsureHome(t *testing.T) {
|
||||
ensure.HelmHome(t)
|
||||
defer ensure.CleanHomeDirs(t)
|
||||
|
||||
b := bytes.NewBuffer(nil)
|
||||
if err := ensureDirectories(b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := ensureReposFile(b, false); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := ensureReposFile(b, true); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := ensureRepoFileFormat(helmpath.RepositoryFile(), b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := ensurePluginsInstalled(testPluginsFile, b); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
expectedDirs := []string{helmpath.CachePath(), helmpath.ConfigPath(), helmpath.DataPath()}
|
||||
for _, dir := range expectedDirs {
|
||||
if fi, err := os.Stat(dir); err != nil {
|
||||
t.Errorf("%s", err)
|
||||
} else if !fi.IsDir() {
|
||||
t.Errorf("%s is not a directory", fi)
|
||||
}
|
||||
}
|
||||
|
||||
if fi, err := os.Stat(helmpath.RepositoryFile()); err != nil {
|
||||
t.Error(err)
|
||||
} else if fi.IsDir() {
|
||||
t.Errorf("%s should not be a directory", fi)
|
||||
}
|
||||
|
||||
if plugins, err := findPlugins(helmpath.Plugins()); err != nil {
|
||||
t.Error(err)
|
||||
} else if len(plugins) != 1 {
|
||||
t.Errorf("Expected 1 plugin, got %d", len(plugins))
|
||||
} else if plugins[0].Metadata.Name != "testplugin" {
|
||||
t.Errorf("Expected %s to be installed", "testplugin")
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
name: env
|
||||
usage: "env stuff"
|
||||
description: "show the env"
|
||||
command: "echo $HELM_PATH_CONFIG"
|
||||
command: "echo $HELM_PLUGIN_NAME"
|
||||
|
Loading…
Reference in new issue