Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4b4455b
disable execution of codeql when code is pushed to main branch, it wi…
ivancorrales Apr 7, 2023
7759a61
disable execution of codeql when code is pushed to main branch, it wi…
ivancorrales Apr 7, 2023
569671e
disable execution of linters when code is pushed to main branch, it w…
ivancorrales Apr 7, 2023
28ff2fc
freebsd is discarded from the gorelease configuration
ivancorrales Apr 7, 2023
fccaae5
Update goreleaser configuration
ivancorrales Apr 7, 2023
dc7cf1d
Update goreleaser configuration
ivancorrales Apr 7, 2023
9532d71
Update documentation
ivancorrales Apr 7, 2023
3d9ad1a
Update documentation
ivancorrales Apr 7, 2023
2c78526
Update documentation
ivancorrales Apr 7, 2023
1a95603
Update documentation
ivancorrales Apr 7, 2023
d543394
ADd templates for creating new issues
ivancorrales Apr 7, 2023
027382f
Update documentation
ivancorrales Apr 7, 2023
9721a48
Fix typos in README
ivancorrales Apr 8, 2023
f3eaebb
Remove unused Makefile targets to run the rest of the commands from a…
ivancorrales Apr 8, 2023
a511c69
Remove unnexesary flags from Go compilation
ivancorrales Apr 8, 2023
bda7a8e
ADd documentation for public packages
ivancorrales Apr 8, 2023
2e85bea
Merge branch 'main' into feature/release-v0.1.0
ivancorrales Apr 8, 2023
2a4133f
Make the README easiert to be followed
ivancorrales Apr 8, 2023
c2fad18
Make the README easiert to be followed
ivancorrales Apr 8, 2023
3a9d040
Update documentation
ivancorrales Apr 8, 2023
fdb32f9
Update documentation
ivancorrales Apr 8, 2023
ad11afe
Fix linter issues
ivancorrales Apr 8, 2023
36301ca
Fix detected with git source protocol
ivancorrales Apr 8, 2023
6be14fd
Remove commented code
ivancorrales Apr 8, 2023
80d1583
Update usage of plugin
ivancorrales Apr 8, 2023
370a6ca
remove unnecesary flags from the plugin
ivancorrales Apr 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ project_name: kubebuilder-initializer-plugin
before:
hooks:
- go mod download
-

builds:
- <<: &build_defaults
Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ GO_CMD ?= go
PROJECT_NAME := kubebuilder-initializer-plugin
UNAME := $(shell uname)

all: init fmt test lint compile
all: init fmt test lint build

help: ## Display this help screen
@echo "Makefile targets:"
Expand All @@ -23,5 +23,4 @@ include build/code.mk
include build/test.mk
include build/compile.mk
include build/release.mk
include build/docker.mk
include build/install.mk
155 changes: 101 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,48 @@

# Kubebuilder Initializer Plugin

A powerful Kubebuilder plugin to initialize dynamically the structure of your kubebuilder operator repositories.
A powerful Kubebuilder plugin to initialize dynamically the structure of your kubebuilder operator project.

### Prerequisites
## Prerequisites

This is a plugin for the kubebuilder tool. In case of you haven't installed the tool yet, please visit the
[kubebuilder documentation](https://github.com/kubernetes-sigs/kubebuilder) and follow the instructions to get
kuberbuilder properly installed in your computer.
This is a plugin for the kubebuilder cli tool If you don't have the Kubebuilder cli installed in your computer, please
visit the official documentation, [kubebuilder documentation](https://github.com/kubernetes-sigs/kubebuilder).

### Installation
## Installation

#### Homebrew
We provide you a variety of alternatives to install the plugin in your computer, take the onw that best fits your needs.

### Download the executable

1. Visit the latest release at [Release page](https://github.com/astrokube/kubebuilder-initializer-plugin/releases)
2. Download the version that works for you
3. Extract the tarball
4. Copy the executable file to the path used by Kubebuilder to read the external plugins
- OSX: ~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
- Linux: $HOME/.config/kubebuilder/plugins/kubebuilder-initializer/v1-alpha

### From the code

To compile the code from your own computer, you just need to run the following commands

1. Add the Astrokube repo
```bash
git clone https://github.com/astrokube/kubebuilder-initializer-plugin.git
cd kubebuilder-initializer-plugin
make build install
```

To check that the installation was success, verify that the executable was copied to the below path (depending on the
operating system)

- OSX: ~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
- Linux: $HOME/.config/kubebuilder/plugins/kubebuilder-initializer/v1-alpha


### Homebrew

Additionally, you could download the executable from our Astrokube Brew repository.

1. Add the Astrokube Brew repository
```bash
brew tap astrokube/tools
```
Expand All @@ -30,80 +59,93 @@ brew tap astrokube/tools
brew install kubebuilder-initializer-plugin
```

3. Please, create a symbolic link (this is required as the Kubebuilder cli will look at that folder to load the external plugins)
3. You will need to create a symbolic link to the path used by Kubebuilder to read the external plugins.

```bash
mkdir -p ~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer-plugin/v1-alpha/
ln -s /usr/local/Cellar/kubebuilder-initializer-plugin/0.1.0/bin/kubebuilder-initializer-plugin \
~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer-plugin/v1-alpha/kubebuilder-initializer-plugin
```

#### Download the executable files
### Verify the installation

1. Visit the latest release at [Release page](https://github.com/astrokube/kubebuilder-initializer-plugin/releases)
2. Download the version that works for you
3. Extract the files in the tarball that you downloaded in the previous step
4. Copy the executable file to the path used by Kubebuilder to read the external plugins
- OSX: ~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
- Linux: $HOME/.config/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
Once the plugin is installed in your computer, a new plugin is available for you to be used when running the Kubebuilder
cli tool, you can run `kubebuilder help` to check it.

#### Build from the code
The `kubebuilder-initializer-plugin/v1-alpha` appears in the list of available plugins.

```bash
git clone https://github.com/astrokube/kubebuilder-initializer-plugin.git
cd kubebuilder-initializer-plugin
make build install
```
To check that installation was success, please check that the executable file was copied to the folder used by Kubebuilder
to read the plugins
- OSX: ~/Library/Application\ Support/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
- Linux: $HOME/.config/kubebuilder/plugins/kubebuilder-initializer/v1-alpha
![Kubebuilder pLugins](docs/assets/plugins.png)

## Getting started
## Define your own template

To deep dive into how Kubebuilder deals with external plugins you can visit the following article
[Extensible CLI and Scaffolding Plugins - Phase 2](https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-2.md)
The Kubebuilder Initializer plugin understand a template like a Git repository in which the name of the elements in the repository
(both folders and files) and the content of the files can contain variables.

Once you have installed the plugin you can use the Kubebuilder cli as usual.
The plugin takes advantage of Go templates to process the templates; that provides us with a very flexible way to define templates.
That implies that we could not only to define variables

1. Check that the plugin has been installed correctly
[go.mod](https://github.com/astrokube/kubebuilder-operator-template/blob/main/go.mod#L1)
```text
module {{.repository.server}}/{{.repository.owner}}/{{.repository.name}}
```

```bash
kubebuilder help
but also add some logic to our own templates

[OWNERS_ALIASES](https://github.com/astrokube/kubebuilder-operator-template/blob/main/OWNERS_ALIASES#L4-L9)
```text
# See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md

aliases:
{{- range .owners}}
{{.alias}}:
{{- range .members}}
- [{{.}}](https://github.com/{{.}})
{{- end}}
{{- end}}
```

And the `kubebuilder-initializer-plugin/v1-alpha` is displayed as part of the list of available plugins.
You can find some examples of templates in [AWESOME_TEMPLATES.md](AWESOME_TEMPLATES.md), and we encourage you to contribute
with your own templates, so please, feel free to open a pull request with an entry in this file if you want to share a
template with others.

![Kubebuilder pLugins](docs/assets/plugins.png)
**TODO**
We ask you to share an example files with the variables that need to be passed in order to customize the templates,
See an example [here](). Only yaml files are supported (JSON could be supported for futures release If this was required
by the community )

*For upcoming releases, the plugin will inspect the files in the templates and It will be able to generate the yaml file for you*

## Getting started

This plugin is used exclusively in the initial scaffolding (`kubebuilder init`) and It's compatible with any other plugin.
When we run the `init` command, the Kubebuilder cli creates the PROJECT file, this is the main piece for Kubebuilder
to create consistency and being able to inject code when we run other commands such as `kubebuildfer create api` or
`kubebuilder create webhook`
On the other hand, the `Kubebuilder Initializer plugin` must be used in conjunction with other plugins that will
take the control once we need to create a Webhook or an API.

2. Choose the template for scaffolding the initial structure of our Kubebuilder operator. You can
create your own template as described (here]() or alternatively you could take advantage of some of the well-known templates
that you can find in [AWESOME_TEMPLATES.md](AWESOME_TEMPLATES.md)
To take advantage of the Initializer plugin, we just need a repository, that will be used as a template, and the
variables file that will allow us to customize the template. By the default, the plugin read the variables from a
named file `.kubebuilder-initializer.yaml`, but this can be customized If required.

3. Once we have chosen the template that we want to use, we just need to write the yaml file that contains the values that
will make us to customize the template. By default, the plugin will take a file named `.kubebuilder-layout.yaml`, otherwise
you will need to pass an extra argument with the path to the file.
To sum up, to initialize our project we just need to pass the argument `--from` and we could additionally pass the argument
`--vars` in case of we don't want to use the default `.kubebuilder-initializer.yaml`.

4. Initialize your project. Keep in mind that this plugin is used exclusively to initialize our project structure, so we should
use also a plugin that supports the APIs and webhooks creation,for instance the `go.kubebuilder.io/v3` that is prpvided out
>>>>>>> main
of the box by Kubbebuilder.
In the below example, we would use our plugin in conjunction with the `go.kubebuilder.io/v3` that help us to work with
implementation of operators in Go.

```bash
kubebuilder init --plugins go.kubebuilder.io/v3,kubebuilder-layout/v1-alpha \
--from "github.com/astrokube/kubebuilder-operator-template" \
--domain astrokube \
--owner astrokube \
--repo github.com/astrokube/k8s-testing-operator
kubebuilder init --plugins go.kubebuilder.io/v3,kubebuilder-initializer-plugin/v1-alpha \
--domain astrokube --owner astrokube --repo github.com/astrokube/k8s-testing-operator \
--from "https://github.com/astrokube/kubebuilder-operator-template"
```

The only argument that needs to be passed is the `from`

*In the above example, the args `domain`, `repo` and `owner` are required by the plugin `go.kubebuilder.io/v3`.*
Be aware that, in the above example, the arguments `domain`, `repo` and `owner` are required by the plugin
`go.kubebuilder.io/v3`.

**Non default branches**

By default, the plugin will fetch the code in the default branch, buy we can specify a branch:
By default, the plugin will fetch the code in the default branch, but we can specify another branch:

```bash
--from "github.com/astrokube/kubebuilder-operator-template#<branch>"
Expand All @@ -121,6 +163,11 @@ the below
```


## Kubebuilder

To deep dive into how Kubebuilder deals with external plugins you can visit the following article
[Extensible CLI and Scaffolding Plugins - Phase 2](https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-2.md)



## Contributing
Expand Down
6 changes: 1 addition & 5 deletions build/compile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ BUILD_DATE = $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
VERSION ?= $(shell git describe --tags --always --dirty | sed -e '/^v/s/^v\(.*\)$$/\1/g')
VERSION_TAG := $(shell git describe --tags --always --abbrev=0 | sed -e '/^v/s/^v\(.*\)$$/\1/g')

LDFLAGS = -s -w \
-X github.com/astrokube/kubebuilder-initializer-plugin/internal/info.Commit=$(COMMIT) \
-X github.com/astrokube/kubebuilder-initializer-plugin/internal/info.Version=$(VERSION) \
-X github.com/astrokube/kubebuilder-initializer-plugin/internal/info.BuildDate=$(BUILD_DATE) \
-X github.com/astrokube/kubebuilder-initializer-plugin/internal/info.Compiler=$(GOLANG_VERSION)
LDFLAGS = -s -w

.PHONY: build
build: ## build executable for the current os
Expand Down
4 changes: 0 additions & 4 deletions build/docker.mk

This file was deleted.

59 changes: 42 additions & 17 deletions internal/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@ package command

import (
"fmt"
"strings"

"github.com/spf13/pflag"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
)

const (
flagVars = "vars"

flagDomain = "domain"
flagRepo = "repo"
flagProjectName = "project-name"
flagFrom = "from"
flagSource = "source"
flagInit = "init"
flagVars = "vars"
flagFrom = "from"
flagSource = "source"
flagInit = "init"
)

const (
Expand All @@ -33,16 +30,26 @@ func Run(request *external.PluginRequest) external.PluginResponse {
}

var err error
var flagSet *pflag.FlagSet

switch request.Command {
case ActionInit:
flagSet := processFlags(request, initFlags)
flagSet, err = processFlags(request, initFlags)
if err != nil {
break
}
response.Universe, err = runInit(flagSet)
case ActionFlags:
flagSet := processFlags(request, flagsFlags)
flagSet, err = processFlags(request, flagsFlags)
if err != nil {
break
}
response.Flags, err = runFlags(flagSet)
case ActionMetadata:
flagSet := processFlags(request, metadataFlags)
flagSet, err = processFlags(request, metadataFlags)
if err != nil {
break
}
response.Metadata, err = runMetadata(flagSet)
case ActionCreateAPI:
break
Expand All @@ -53,29 +60,47 @@ func Run(request *external.PluginRequest) external.PluginResponse {
default:
err = fmt.Errorf("unknown command '%s'", request.Command)
}

if err != nil {
response.Error = true
response.ErrorMsgs = []string{err.Error()}
}
return response
}

func processFlags(request *external.PluginRequest, flags []external.Flag) *pflag.FlagSet {
func processFlags(request *external.PluginRequest, flags []external.Flag) (*pflag.FlagSet, error) {
flagsSet := pflag.NewFlagSet(fmt.Sprintf("%sFlags", request.Command), pflag.ContinueOnError)
for _, f := range flags {
switch f.Type {
case "string":
flagsSet.String(f.Name, f.Default, f.Usage)
case "boolean":
flagsSet.Bool(f.Name, f.Default == "true", f.Usage)
case "array":
flagsSet.StringArray(f.Name, []string{}, f.Usage)
default:
flagsSet.String(f.Name, f.Default, f.Usage)
}
}
_ = flagsSet.Parse(request.Args)
args := filterProvidedArgs(request.Args, flags)
if err := flagsSet.Parse(args); err != nil {
return nil, err
}
return flagsSet, nil
}

return flagsSet
func filterProvidedArgs(args []string, supportedFlags []external.Flag) (out []string) {
supportedFlagsMap := make(map[string]struct{}, len(supportedFlags))
for i := range supportedFlags {
key := fmt.Sprintf("--%s", supportedFlags[i].Name)
supportedFlagsMap[key] = struct{}{}
}
expectArgValue := false
for i := range args {
arg := args[i]
if expectArgValue {
out = append(out, arg)
} else if _, ok := supportedFlagsMap[args[i]]; ok {
out = append(out, arg)
}
expectArgValue = strings.HasPrefix(arg, "--")
}
return
}
Loading