diff --git a/.gitignore b/.gitignore index e0f20f7..2a43eb9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ *.out bin/ + +.idea/ diff --git a/.goreleaser.yml b/.goreleaser.yml index 0100cdc..cc4939d 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,10 +1,10 @@ -project_name: {{ .PluginName }} +project_name: node-pod release: github: - owner: {{ .Owner }} - name: {{ .Repo }} + owner: mattfenwick + name: krew-node-pod builds: - - id: {{ .PluginName }} + - id: node-pod goos: - linux - windows @@ -17,12 +17,12 @@ builds: - GO111MODULE=on main: cmd/plugin/main.go ldflags: -s -w - -X github.com/{{ .Owner }}/{{ .Repo }}/pkg/version.version= + -X github.com/mattfenwick/krew-node-pod/pkg/version.version= archives: - - id: {{ .PluginName }} + - id: node-pod builds: - - {{ .PluginName }} - name_template: {{ `"{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"` }} + - node-pod + name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" format_overrides: - goos: windows format: zip diff --git a/Makefile b/Makefile index b015370..6e841a3 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ test: .PHONY: bin bin: fmt vet - go build -o bin/{{ .PluginName }} github.com/{{ .Owner }}/{{ .Repo }}/cmd/plugin + go build -o bin/node-pod github.com/mattfenwick/krew-node-pod/cmd/plugin .PHONY: fmt fmt: diff --git a/README.md b/README.md index f4c610a..ab00980 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,11 @@ -# kubectl krew template repo +# node-pod kubectl -There's a lot of scaffolding needed to set up a good kubectl plugin. This repo is a GitHub Template Repo to make it easy to set all of this scaffolding up for a new repo. +A `kubectl` plugin to ... -The assumptions made are: -1. You'll write your plugin in go -2. You want client-go to interact with the cluster -3. You want all of the kubectl flags available to your plugin -4. Your plugin's home will be a github.com repo -5. Your plugin will work in Linux, MacOS and Windows +## Quick Start -## Create your repo - -[Start here](https://github.com/replicatedhq/krew-plugin-template/generate) to create a new repo based on this template. This is not a fork, it will make a copy of this repo into your own organization or GitHub account. - -Click that, and create your own version of this repo. Clone it locally. The rest of the steps you will be performing on your local copy. - -## Make it yours - -Once you have your own repo created locally, change to the directory and run: - -```shell -make setup ``` - -This will prompt you for a few things, such as your GitHub org, repo name and plugin name. The setup application will then update the import paths and code with the data you provided. - -(Note, once you've run this step, these instructions will no longer be present in your repo. You can always vew then at [https://github.com/replicatedhq/krew-plugin-template](https://github.com/replicatedhq/krew-plugin-template)). - -Commit and check it in to your repo! - -```shell -git add . -git commit -m "Updating from template" -git push -u origin master +kubectl krew install node-pod +kubectl node-pod ``` -## Write your Plugin - -Next, open the pkg/plugin/plugin.go file. This is where you can start writing your plugin. - -For an example, take a look at the [outdated](https://github.com/replicatedhq/outdated) plugin that inspired this template. - -To make a local build: - -```shell -make bin -``` - -## Creating a release - -To create a new release of your plugin, create and push a tag. - -```shell -git tag v0.1.0 -m 'initial release' -git push --tags -``` - -This repo has a built-in GitHub Action that will handle the build process. We use [GoReleaser](https://goreleaser.com) to create tagged releases. This will create all three binaries and push them to the releases page when you push a tag. It will take a few minutes to complete, so be patient. - -## Submitting to Krew - -Be sure to read the guidelines on the Krew Developer guide before submitting you plugin. This is not automated (yet). We've created a starting point for your plugin manifest, look for it in deploy/krew/plugin.yaml. - -## Share! - -Finally, we'd love to hear if you've used this template. Let us know on Twitter at @replicatedhq. We've written a few kubectl plugins too, and are always curious to see what other people are working on. diff --git a/cmd/plugin/cli/root.go b/cmd/plugin/cli/root.go index 8c27526..dd1a949 100644 --- a/cmd/plugin/cli/root.go +++ b/cmd/plugin/cli/root.go @@ -6,8 +6,8 @@ import ( "strings" "time" - "github.com/{{ .Owner }}/{{ .Repo }}/pkg/logger" - "github.com/{{ .Owner }}/{{ .Repo }}/pkg/plugin" + "github.com/mattfenwick/krew-node-pod/pkg/logger" + "github.com/mattfenwick/krew-node-pod/pkg/plugin" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -21,7 +21,7 @@ var ( func RootCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "{{ .PluginName }}", + Use: "node-pod", Short: "", Long: `.`, SilenceErrors: true, diff --git a/cmd/plugin/main.go b/cmd/plugin/main.go index 0d86ebf..720d460 100644 --- a/cmd/plugin/main.go +++ b/cmd/plugin/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/{{ .Owner }}/{{ .Repo }}/cmd/plugin/cli" + "github.com/mattfenwick/krew-node-pod/cmd/plugin/cli" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // required for GKE ) diff --git a/deploy/krew/plugin.yaml b/deploy/krew/plugin.yaml index 06be856..c092f2b 100644 --- a/deploy/krew/plugin.yaml +++ b/deploy/krew/plugin.yaml @@ -1,7 +1,7 @@ apiVersion: krew.googlecontainertools.github.com/v1alpha2 kind: Plugin metadata: - name: {{ .PluginName }} + name: node-pod spec: version: "v0.1.0" platforms: @@ -9,47 +9,47 @@ spec: matchLabels: os: linux arch: amd64 - uri: https://github.com/{{ .Owner }}/{{ .Repo }}/releases/download/v0.1.0/{{ .PluginName }}_linux_amd64.tar.gz + uri: https://github.com/mattfenwick/krew-node-pod/releases/download/v0.1.0/node-pod_linux_amd64.tar.gz sha256: "" files: - - from: "./{{ .PluginName }}" + - from: "./node-pod" to: "." - from: LICENSE to: "." - bin: "{{ .PluginName }}" + bin: "node-pod" - selector: matchLabels: os: darwin arch: amd64 - uri: https://github.com/{{ .Owner }}/{{ .Repo }}/releases/download/v0.1.0/{{ .PluginName }}_darwin_amd64.tar.gz + uri: https://github.com/mattfenwick/krew-node-pod/releases/download/v0.1.0/node-pod_darwin_amd64.tar.gz sha256: "" files: - - from: "./{{ .PluginName }}" + - from: "./node-pod" to: "." - from: LICENSE to: "." - bin: "{{ .PluginName }}" + bin: "node-pod" - selector: matchLabels: os: windows arch: amd64 - uri: https://github.com/{{ .Owner }}/{{ .Repo }}/releases/download/v0.1.0/{{ .PluginName }}_windows_amd64.zip + uri: https://github.com/mattfenwick/krew-node-pod/releases/download/v0.1.0/node-pod_windows_amd64.zip sha256: "" files: - - from: "/{{ .PluginName }}.exe" + - from: "/node-pod.exe" to: "." - from: LICENSE to: "." - bin: "{{ .PluginName }}.exe" + bin: "node-pod.exe" shortDescription: A new plugin - homepage: https://github.com/{{ .Owner }}/{{ .Repo }} + homepage: https://github.com/mattfenwick/krew-node-pod caveats: | Usage: - $ kubectl {{ .PluginName }} + $ kubectl node-pod For additional options: - $ kubectl {{ .PluginName }} --help - or https://github.com/{{ .Owner }}/{{ .Repo }}/blob/v0.1.0/doc/USAGE.md + $ kubectl node-pod --help + or https://github.com/mattfenwick/krew-node-pod/blob/v0.1.0/doc/USAGE.md description: | This is a new plugin diff --git a/doc/USAGE.md b/doc/USAGE.md index 00aef67..6456c75 100644 --- a/doc/USAGE.md +++ b/doc/USAGE.md @@ -3,19 +3,19 @@ The following assumes you have the plugin installed via ```shell -kubectl krew install {{ .PluginName }} +kubectl krew install node-pod ``` ### Scan images in your current kubecontext ```shell -kubectl {{ .PluginName }} +kubectl node-pod ``` ### Scan images in another kubecontext ```shell -kubectl {{ .PluginName }} --context=context-name +kubectl node-pod --context=context-name ``` ## How it works diff --git a/go.mod b/go.mod index 5454504..16004de 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/replicatedhq/krew-plugin-template +module github.com/mattfenwick/krew-node-pod go 1.12 diff --git a/setup/Makefile b/setup/Makefile deleted file mode 100644 index ff7cb12..0000000 --- a/setup/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -export GO111MODULE=on - -.PHONY: all -all: - go run ./... \ No newline at end of file diff --git a/setup/gomod.go b/setup/gomod.go deleted file mode 100644 index 7fef5fb..0000000 --- a/setup/gomod.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "path" - "strings" - - "github.com/pkg/errors" -) - -func renderGoMod(templateContext TemplateContext) error { - input, err := ioutil.ReadFile(path.Join("..", "go.mod")) - if err != nil { - return errors.Wrap(err, "failed to read go.mod") - } - - lines := strings.Split(string(input), "\n") - - lines[0] = fmt.Sprintf(`module github.com/%s/%s`, templateContext.Owner, templateContext.Repo) - - output := strings.Join(lines, "\n") - err = ioutil.WriteFile(path.Join("..", "go.mod"), []byte(output), 0644) - if err != nil { - return errors.Wrap(err, "failed to write go.mod") - } - - return nil -} diff --git a/setup/hack/README.txt b/setup/hack/README.txt deleted file mode 100644 index 0adba7a..0000000 --- a/setup/hack/README.txt +++ /dev/null @@ -1,11 +0,0 @@ -# {{ .PluginName }} kubectl - -A `kubectl` plugin to ... - -## Quick Start - -``` -kubectl krew install {{ .PluginName }} -kubectl {{ .PluginName }} -``` - diff --git a/setup/main.go b/setup/main.go deleted file mode 100644 index c100f10..0000000 --- a/setup/main.go +++ /dev/null @@ -1,161 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path" - "path/filepath" - "strings" - - "github.com/manifoldco/promptui" - "github.com/pkg/errors" - "github.com/replicatedhq/krew-plugin-template/pkg/logger" -) - -type TemplateContext struct { - Owner string - Repo string - PluginName string -} - -func main() { - owner, err := promptForOwner() - if err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - repo, err := promptForRepo() - if err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - pluginName, err := promptForPluginName() - if err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - templateContext := TemplateContext{ - Owner: owner, - Repo: repo, - PluginName: pluginName, - } - - log := logger.NewLogger() - log.Info("Updating README") - if err := renderReadme(templateContext); err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - log.Info("Updating sample code with names") - if err := renderTemplates(templateContext); err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - log.Info("Updating go.mod") - if err := renderGoMod(templateContext); err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - log.Info("Removing the setup application") - if err := os.RemoveAll(path.Join("..", "setup")); err != nil { - fmt.Printf("%v\n", errors.Cause(err)) - os.Exit(1) - } - - log.Instructions("Your kubectl krew plugin has been initialized in this directory.") - log.Instructions("For next steps, visit https://github.com/replicatedhq/krew-plugin-template") - log.Info("") -} - -func promptForOwner() (string, error) { - cwd, err := os.Getwd() - if err != nil { - return "", errors.Wrap(err, "failed to get working dir") - } - - pathParts := strings.Split(filepath.Dir(cwd), string(os.PathSeparator)) - - validate := func(input string) error { - if len(input) == 0 { - return errors.New("Invalid") - } - return nil - } - - prompt := promptui.Prompt{ - Label: "GitHub Organization or Username", - Validate: validate, - Default: pathParts[len(pathParts)-2], - } - - result, err := prompt.Run() - if err != nil { - return "", errors.Wrap(err, "failed to prompt for github owner") - } - - return result, nil -} - -func promptForRepo() (string, error) { - cwd, err := os.Getwd() - if err != nil { - return "", errors.Wrap(err, "failed to get working dir") - } - - pathParts := strings.Split(filepath.Dir(cwd), string(os.PathSeparator)) - - validate := func(input string) error { - if len(input) == 0 { - return errors.New("Invalid") - } - return nil - } - - prompt := promptui.Prompt{ - Label: "GitHub Repo Name", - Validate: validate, - Default: pathParts[len(pathParts)-1], - } - - result, err := prompt.Run() - if err != nil { - return "", errors.Wrap(err, "failed to prompt for github repo") - } - - return result, nil -} - -func promptForPluginName() (string, error) { - cwd, err := os.Getwd() - if err != nil { - return "", errors.Wrap(err, "failed to get working dir") - } - - pathParts := strings.Split(filepath.Dir(cwd), string(os.PathSeparator)) - - validate := func(input string) error { - if len(input) == 0 { - return errors.New("Invalid") - } - return nil - } - - prompt := promptui.Prompt{ - Label: "Plugin Name", - Validate: validate, - Default: pathParts[len(pathParts)-1], - } - - result, err := prompt.Run() - if err != nil { - return "", errors.Wrap(err, "failed to prompt for plugin name") - } - - return result, nil -} diff --git a/setup/readme.go b/setup/readme.go deleted file mode 100644 index aa491ef..0000000 --- a/setup/readme.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "io/ioutil" - "path" - - "github.com/pkg/errors" -) - -func renderReadme(templateContext TemplateContext) error { - input, err := ioutil.ReadFile(path.Join("hack", "README.txt")) - if err != nil { - return errors.Wrap(err, "failed to read README.txt") - } - - err = ioutil.WriteFile(path.Join("..", "README.md"), input, 0644) - if err != nil { - return errors.Wrap(err, "failed to write README.md") - } - - return nil -} diff --git a/setup/templates.go b/setup/templates.go deleted file mode 100644 index 98131a8..0000000 --- a/setup/templates.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "strings" - "text/template" - - "github.com/pkg/errors" -) - -func renderTemplates(templateContext TemplateContext) error { - err := filepath.Walk("..", - func(path string, info os.FileInfo, err error) error { - // ignore .git - pathSplit := strings.Split(path, string(os.PathSeparator)) - if len(pathSplit) >= 2 { - if pathSplit[1] == ".git" { - return nil - } - } - - // ignore the setup pkg - if len(pathSplit) >= 2 { - if pathSplit[1] == "setup" { - return nil - } - } - - // Ignore bin - if len(pathSplit) >= 2 { - if pathSplit[1] == "bin" { - return nil - } - } - - fi, err := os.Stat(path) - if err != nil { - return errors.Wrap(err, "failed to read file info") - } - - if fi.IsDir() { - return nil - } - - tmpl, err := template.ParseFiles(path) - if err != nil { - return errors.Wrap(err, "failed to parse template") - } - - f, err := os.Create(path) - if err != nil { - return errors.Wrap(err, "failed to create file") - } - - if err := tmpl.Execute(f, templateContext); err != nil { - return errors.Wrap(err, "failed to execute template") - } - - return nil - }) - if err != nil { - return errors.Wrap(err, "failed to walk directory") - } - - return nil -}