Merge pull request #1 from fluxcd/install
Implement check, install, uninstall and create source commands
This commit is contained in:
6
.github/actions/kustomize/Dockerfile
vendored
Normal file
6
.github/actions/kustomize/Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM giantswarm/tiny-tools
|
||||||
|
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
9
.github/actions/kustomize/action.yml
vendored
Normal file
9
.github/actions/kustomize/action.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
name: 'kustomize'
|
||||||
|
description: 'A GitHub Action to run kustomize commands'
|
||||||
|
author: 'Stefan Prodan'
|
||||||
|
branding:
|
||||||
|
icon: 'command'
|
||||||
|
color: 'blue'
|
||||||
|
runs:
|
||||||
|
using: 'docker'
|
||||||
|
image: 'Dockerfile'
|
||||||
12
.github/actions/kustomize/entrypoint.sh
vendored
Normal file
12
.github/actions/kustomize/entrypoint.sh
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh -l
|
||||||
|
|
||||||
|
VERSION=3.5.4
|
||||||
|
curl -sL https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${VERSION}/kustomize_v${VERSION}_linux_amd64.tar.gz | tar xz
|
||||||
|
|
||||||
|
mkdir -p $GITHUB_WORKSPACE/bin
|
||||||
|
cp ./kustomize $GITHUB_WORKSPACE/bin
|
||||||
|
chmod +x $GITHUB_WORKSPACE/bin/kustomize
|
||||||
|
ls -lh $GITHUB_WORKSPACE/bin
|
||||||
|
|
||||||
|
echo "::add-path::$GITHUB_WORKSPACE/bin"
|
||||||
|
echo "::add-path::$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin"
|
||||||
50
.github/workflows/e2e.yaml
vendored
Normal file
50
.github/workflows/e2e.yaml
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: e2e
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
kind:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Restore Go cache
|
||||||
|
uses: actions/cache@v1
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v2-beta
|
||||||
|
with:
|
||||||
|
go-version: 1.14.x
|
||||||
|
- name: Setup Kubernetes
|
||||||
|
uses: engineerd/setup-kind@v0.3.0
|
||||||
|
- name: Setup Kustomize
|
||||||
|
uses: ./.github/actions/kustomize
|
||||||
|
- name: Run test
|
||||||
|
run: make test
|
||||||
|
- name: Check if working tree is dirty
|
||||||
|
run: |
|
||||||
|
if [[ $(git diff --stat) != '' ]]; then
|
||||||
|
echo 'run make test and commit changes'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: Build
|
||||||
|
run: sudo go build -o ./bin/tk ./cmd/tk
|
||||||
|
- name: Run integration tests
|
||||||
|
run: |
|
||||||
|
./bin/tk check
|
||||||
|
./bin/tk install --manifests ./manifests/install/
|
||||||
|
./bin/tk create source podinfo --git-url https://github.com/stefanprodan/podinfo-deploy --git-semver=">=0.0.1-rc.1 <0.1.0"
|
||||||
|
- name: Debug failure
|
||||||
|
if: failure()
|
||||||
|
run: |
|
||||||
|
kubectl version --client --short
|
||||||
|
kustomize version --short
|
||||||
|
kubectl -n gitops-system get all
|
||||||
34
.github/workflows/release.yaml
vendored
Normal file
34
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Unshallow
|
||||||
|
run: git fetch --prune --unshallow
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v2-beta
|
||||||
|
with:
|
||||||
|
go-version: 1.14.x
|
||||||
|
- name: Download release notes utility
|
||||||
|
env:
|
||||||
|
GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
|
||||||
|
run: cd /tmp && curl -sSL ${GH_REL_URL} | tar xz && sudo mv github-release-notes /usr/local/bin/
|
||||||
|
- name: Generate release notes
|
||||||
|
run: |
|
||||||
|
echo 'CHANGELOG' > /tmp/release.txt
|
||||||
|
github-release-notes -org fluxcd -repo toolkit -since-latest-release >> /tmp/release.txt
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v1
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: release --release-notes=/tmp/release.txt
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
14
.goreleaser.yml
Normal file
14
.goreleaser.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
builds:
|
||||||
|
- main: ./cmd/tk
|
||||||
|
binary: tk
|
||||||
|
goos:
|
||||||
|
- darwin
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||||
|
files:
|
||||||
|
- none*
|
||||||
16
Makefile
16
Makefile
@@ -1,9 +1,9 @@
|
|||||||
VERSION?=$(shell grep 'VERSION' cmd/tk/main.go | awk '{ print $$4 }' | tr -d '"')
|
VERSION?=$(shell grep 'VERSION' cmd/tk/main.go | awk '{ print $$4 }' | tr -d '"')
|
||||||
|
|
||||||
all: tidy fmt vet test build
|
all: test build
|
||||||
|
|
||||||
build:
|
tidy:
|
||||||
CGO_ENABLED=0 go build -o ./bin/tk ./cmd/tk
|
go mod tidy
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
go fmt ./...
|
go fmt ./...
|
||||||
@@ -11,9 +11,11 @@ fmt:
|
|||||||
vet:
|
vet:
|
||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
||||||
tidy:
|
test: tidy fmt vet
|
||||||
go mod tidy
|
|
||||||
|
|
||||||
test:
|
|
||||||
go test ./... -coverprofile cover.out
|
go test ./... -coverprofile cover.out
|
||||||
|
|
||||||
|
build:
|
||||||
|
CGO_ENABLED=0 go build -o ./bin/tk ./cmd/tk
|
||||||
|
|
||||||
|
install:
|
||||||
|
go install cmd/tk
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
# toolkit
|
# toolkit
|
||||||
Experimental toolkit for assembling CD pipelines
|
|
||||||
|
[](https://github.com/fluxcd/toolkit/actions)
|
||||||
|
|
||||||
|
Experimental toolkit for assembling CD pipelines.
|
||||||
|
|
||||||
|
Components:
|
||||||
|
* [source-controller](https://github.com/fluxcd/source-controller)
|
||||||
|
* [kustomize-controller](https://github.com/fluxcd/kustomize-controller)
|
||||||
|
|||||||
135
cmd/tk/check.go
135
cmd/tk/check.go
@@ -1,16 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/blang/semver"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var checkCmd = &cobra.Command{
|
var checkCmd = &cobra.Command{
|
||||||
Use: "check --pre",
|
Use: "check",
|
||||||
Short: "Check for potential problems",
|
Short: "Check requirements",
|
||||||
Long: `
|
Long: `
|
||||||
The check command will perform a series of checks to validate that
|
The check command will perform a series of checks to validate that
|
||||||
the local environment is configured correctly.`,
|
the local environment is configured correctly.`,
|
||||||
@@ -30,49 +31,145 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCheckCmd(cmd *cobra.Command, args []string) error {
|
func runCheckCmd(cmd *cobra.Command, args []string) error {
|
||||||
if !checkLocal() {
|
logAction("starting verification")
|
||||||
os.Exit(1)
|
checkFailed := false
|
||||||
|
if !sshCheck() {
|
||||||
|
checkFailed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !kubectlCheck(">=1.18.0") {
|
||||||
|
checkFailed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !kustomizeCheck(">=3.5.0") {
|
||||||
|
checkFailed = true
|
||||||
|
}
|
||||||
|
|
||||||
if checkPre {
|
if checkPre {
|
||||||
fmt.Println(`✔`, "all prerequisites checks passed")
|
if checkFailed {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
logSuccess("all prerequisites checks passed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !checkRemote() {
|
if !kubernetesCheck(">=1.14.0") {
|
||||||
os.Exit(1)
|
checkFailed = true
|
||||||
} else {
|
|
||||||
fmt.Println(`✔`, "all checks passed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if checkFailed {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
logSuccess("all checks passed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLocal() bool {
|
func sshCheck() bool {
|
||||||
ok := true
|
ok := true
|
||||||
for _, cmd := range []string{"kubectl", "kustomize"} {
|
for _, cmd := range []string{"ssh-keygen", "ssh-keyscan"} {
|
||||||
_, err := exec.LookPath(cmd)
|
_, err := exec.LookPath(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(`✗`, cmd, "not found")
|
logFailure("%s not found", cmd)
|
||||||
ok = false
|
ok = false
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(`✔`, cmd, "found")
|
logSuccess("%s found", cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRemote() bool {
|
func kubectlCheck(version string) bool {
|
||||||
client, err := NewKubernetesClient()
|
_, err := exec.LookPath("kubectl")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(`✗`, "kubernetes client initialization failed", err.Error())
|
logFailure("kubectl not found")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := execCommand("kubectl version --client --short | awk '{ print $3 }'")
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kubectl version can't be determined")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := semver.ParseTolerant(output)
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kubectl version can't be parsed")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rng, _ := semver.ParseRange(version)
|
||||||
|
if !rng(v) {
|
||||||
|
logFailure("kubectl version must be %s", version)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess("kubectl %s %s", v.String(), version)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func kustomizeCheck(version string) bool {
|
||||||
|
_, err := exec.LookPath("kustomize")
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kustomize not found")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := execCommand("kustomize version --short | awk '{ print $1 }' | cut -c2-")
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kustomize version can't be determined")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(output, "kustomize/") {
|
||||||
|
output, err = execCommand("kustomize version --short | awk '{ print $1 }' | cut -c12-")
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kustomize version can't be determined")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := semver.ParseTolerant(output)
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kustomize version can't be parsed")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rng, _ := semver.ParseRange(version)
|
||||||
|
if !rng(v) {
|
||||||
|
logFailure("kustomize version must be %s", version)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess("kustomize %s %s", v.String(), version)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func kubernetesCheck(version string) bool {
|
||||||
|
client, err := kubernetesClient()
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kubernetes client initialization failed: %s", err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ver, err := client.Discovery().ServerVersion()
|
ver, err := client.Discovery().ServerVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(`✗`, "kubernetes API call failed", err.Error())
|
logFailure("kubernetes API call failed %s", err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(`✔`, "kubernetes version", ver.String())
|
v, err := semver.ParseTolerant(ver.String())
|
||||||
|
if err != nil {
|
||||||
|
logFailure("kubernetes version can't be determined")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rng, _ := semver.ParseRange(version)
|
||||||
|
if !rng(v) {
|
||||||
|
logFailure("kubernetes version must be %s", version)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess("kubernetes %s %s", v.String(), version)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
19
cmd/tk/create.go
Normal file
19
cmd/tk/create.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var createCmd = &cobra.Command{
|
||||||
|
Use: "create",
|
||||||
|
Short: "Create commands",
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
interval string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
createCmd.PersistentFlags().StringVar(&interval, "interval", "1m", "source sync interval")
|
||||||
|
rootCmd.AddCommand(createCmd)
|
||||||
|
}
|
||||||
236
cmd/tk/create_source.go
Normal file
236
cmd/tk/create_source.go
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/manifoldco/promptui"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var createSourceCmd = &cobra.Command{
|
||||||
|
Use: "source [name]",
|
||||||
|
Short: "Create source resource",
|
||||||
|
Long: `
|
||||||
|
The create source command generates a source.fluxcd.io resource and waits for it to sync.
|
||||||
|
For Git over SSH, host and SSH keys are automatically generated.`,
|
||||||
|
Example: ` # Create a gitrepository.source.fluxcd.io for a public repository
|
||||||
|
create source podinfo --git-url https://github.com/stefanprodan/podinfo-deploy --git-branch master
|
||||||
|
|
||||||
|
# Create a gitrepository.source.fluxcd.io that syncs tags based on a semver range
|
||||||
|
create source podinfo --git-url https://github.com/stefanprodan/podinfo-deploy --git-semver=">=0.0.1-rc.1 <0.1.0"
|
||||||
|
|
||||||
|
# Create a gitrepository.source.fluxcd.io with SSH authentication
|
||||||
|
create source podinfo --git-url ssh://git@github.com/stefanprodan/podinfo-deploy
|
||||||
|
|
||||||
|
# Create a gitrepository.source.fluxcd.io with basic authentication
|
||||||
|
create source podinfo --git-url https://github.com/stefanprodan/podinfo-deploy -u username -p password
|
||||||
|
`,
|
||||||
|
RunE: createSourceCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
sourceGitURL string
|
||||||
|
sourceGitBranch string
|
||||||
|
sourceGitSemver string
|
||||||
|
sourceUsername string
|
||||||
|
sourcePassword string
|
||||||
|
sourceVerbose bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
createSourceCmd.Flags().StringVar(&sourceGitURL, "git-url", "", "git address, e.g. ssh://git@host/org/repository")
|
||||||
|
createSourceCmd.Flags().StringVar(&sourceGitBranch, "git-branch", "master", "git branch")
|
||||||
|
createSourceCmd.Flags().StringVar(&sourceGitSemver, "git-semver", "", "git tag semver range")
|
||||||
|
createSourceCmd.Flags().StringVarP(&sourceUsername, "username", "u", "", "basic authentication username")
|
||||||
|
createSourceCmd.Flags().StringVarP(&sourcePassword, "password", "p", "", "basic authentication password")
|
||||||
|
createSourceCmd.Flags().BoolVarP(&sourceVerbose, "verbose", "", false, "print generated source object")
|
||||||
|
|
||||||
|
createCmd.AddCommand(createSourceCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSourceCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return fmt.Errorf("source name is required")
|
||||||
|
}
|
||||||
|
name := args[0]
|
||||||
|
|
||||||
|
if sourceGitURL == "" {
|
||||||
|
return fmt.Errorf("git-url is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpDir, err := ioutil.TempDir("", name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
u, err := url.Parse(sourceGitURL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("git URL parse failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
withAuth := false
|
||||||
|
if strings.HasPrefix(sourceGitURL, "ssh") {
|
||||||
|
if err := generateSSH(name, u.Host, tmpDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
withAuth = true
|
||||||
|
} else if sourceUsername != "" && sourcePassword != "" {
|
||||||
|
if err := generateBasicAuth(name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
withAuth = true
|
||||||
|
}
|
||||||
|
|
||||||
|
logAction("generating source %s in %s namespace", name, namespace)
|
||||||
|
|
||||||
|
t, err := template.New("tmpl").Parse(gitSource)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("template parse error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
source := struct {
|
||||||
|
Name string
|
||||||
|
Namespace string
|
||||||
|
URL string
|
||||||
|
Branch string
|
||||||
|
Semver string
|
||||||
|
Interval string
|
||||||
|
WithAuth bool
|
||||||
|
}{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
URL: sourceGitURL,
|
||||||
|
Branch: sourceGitBranch,
|
||||||
|
Semver: sourceGitSemver,
|
||||||
|
Interval: interval,
|
||||||
|
WithAuth: withAuth,
|
||||||
|
}
|
||||||
|
|
||||||
|
var data bytes.Buffer
|
||||||
|
writer := bufio.NewWriter(&data)
|
||||||
|
if err := t.Execute(writer, source); err != nil {
|
||||||
|
return fmt.Errorf("template execution failed: %w", err)
|
||||||
|
}
|
||||||
|
if err := writer.Flush(); err != nil {
|
||||||
|
return fmt.Errorf("source flush failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sourceVerbose {
|
||||||
|
fmt.Print(data.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
command := fmt.Sprintf("echo '%s' | kubectl apply -f-", data.String())
|
||||||
|
c := exec.CommandContext(ctx, "/bin/sh", "-c", command)
|
||||||
|
|
||||||
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
|
c.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
|
c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
|
|
||||||
|
err = c.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("source apply failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
logAction("waiting for source sync")
|
||||||
|
if output, err := execCommand(fmt.Sprintf(
|
||||||
|
"kubectl -n %s wait gitrepository/%s --for=condition=ready --timeout=1m",
|
||||||
|
namespace, name)); err != nil {
|
||||||
|
return fmt.Errorf("source sync failed: %s", output)
|
||||||
|
} else {
|
||||||
|
fmt.Print(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateBasicAuth(name string) error {
|
||||||
|
logAction("saving credentials")
|
||||||
|
credentials := fmt.Sprintf("--from-literal=username='%s' --from-literal=password='%s'",
|
||||||
|
sourceUsername, sourcePassword)
|
||||||
|
secret := fmt.Sprintf("kubectl -n %s create secret generic %s %s --dry-run=client -oyaml | kubectl apply -f-",
|
||||||
|
namespace, name, credentials)
|
||||||
|
if output, err := execCommand(secret); err != nil {
|
||||||
|
return fmt.Errorf("kubectl create secret failed: %s", output)
|
||||||
|
} else {
|
||||||
|
fmt.Print(output)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSSH(name, host, tmpDir string) error {
|
||||||
|
logAction("generating host key for %s", host)
|
||||||
|
|
||||||
|
keyscan := fmt.Sprintf("ssh-keyscan %s > %s/known_hosts", host, tmpDir)
|
||||||
|
if output, err := execCommand(keyscan); err != nil {
|
||||||
|
return fmt.Errorf("ssh-keyscan failed: %s", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
logAction("generating deploy key")
|
||||||
|
|
||||||
|
keygen := fmt.Sprintf("ssh-keygen -b 2048 -t rsa -f %s/identity -q -N \"\"", tmpDir)
|
||||||
|
if output, err := execCommand(keygen); err != nil {
|
||||||
|
return fmt.Errorf("ssh-keygen failed: %s", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
deployKey, err := execCommand(fmt.Sprintf("cat %s/identity.pub", tmpDir))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read identity.pub: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print(deployKey)
|
||||||
|
prompt := promptui.Prompt{
|
||||||
|
Label: "Have you added the deploy key to your repository",
|
||||||
|
IsConfirm: true,
|
||||||
|
}
|
||||||
|
if _, err := prompt.Run(); err != nil {
|
||||||
|
logFailure("aborting")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logAction("saving deploy key")
|
||||||
|
files := fmt.Sprintf("--from-file=%s/identity --from-file=%s/identity.pub --from-file=%s/known_hosts",
|
||||||
|
tmpDir, tmpDir, tmpDir)
|
||||||
|
secret := fmt.Sprintf("kubectl -n %s create secret generic %s %s --dry-run=client -oyaml | kubectl apply -f-",
|
||||||
|
namespace, name, files)
|
||||||
|
if output, err := execCommand(secret); err != nil {
|
||||||
|
return fmt.Errorf("kubectl create secret failed: %s", output)
|
||||||
|
} else {
|
||||||
|
fmt.Print(output)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var gitSource = `---
|
||||||
|
apiVersion: source.fluxcd.io/v1alpha1
|
||||||
|
kind: GitRepository
|
||||||
|
metadata:
|
||||||
|
name: {{.Name}}
|
||||||
|
namespace: {{.Namespace}}
|
||||||
|
spec:
|
||||||
|
interval: {{.Interval}}
|
||||||
|
url: {{.URL}}
|
||||||
|
ref:
|
||||||
|
{{- if .Semver }}
|
||||||
|
semver: "{{.Semver}}"
|
||||||
|
{{- else }}
|
||||||
|
branch: {{.Branch}}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .WithAuth }}
|
||||||
|
secretRef:
|
||||||
|
name: {{.Name}}
|
||||||
|
{{- end }}
|
||||||
|
`
|
||||||
93
cmd/tk/install.go
Normal file
93
cmd/tk/install.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var installCmd = &cobra.Command{
|
||||||
|
Use: "install",
|
||||||
|
Short: "Install the toolkit components",
|
||||||
|
Long: `
|
||||||
|
The Install command deploys the toolkit components
|
||||||
|
on the configured Kubernetes cluster in ~/.kube/config`,
|
||||||
|
Example: ` install --manifests github.com/fluxcd/toolkit//manifests/install --dry-run`,
|
||||||
|
RunE: installCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
installDryRun bool
|
||||||
|
installManifestsPath string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
installCmd.Flags().BoolVarP(&installDryRun, "dry-run", "", false,
|
||||||
|
"only print the object that would be applied")
|
||||||
|
installCmd.Flags().StringVarP(&installManifestsPath, "manifests", "", "",
|
||||||
|
"path to the manifest directory")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(installCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func installCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
if installManifestsPath == "" {
|
||||||
|
return fmt.Errorf("no manifests specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(installManifestsPath, "github.com/") {
|
||||||
|
if _, err := os.Stat(installManifestsPath); err != nil {
|
||||||
|
return fmt.Errorf("manifests not found: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
dryRun := ""
|
||||||
|
if installDryRun {
|
||||||
|
dryRun = "--dry-run=client"
|
||||||
|
}
|
||||||
|
command := fmt.Sprintf("kustomize build %s | kubectl apply -f- %s",
|
||||||
|
installManifestsPath, dryRun)
|
||||||
|
c := exec.CommandContext(ctx, "/bin/sh", "-c", command)
|
||||||
|
|
||||||
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
|
c.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
|
c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
|
|
||||||
|
logAction("installing components in %s namespace", namespace)
|
||||||
|
err := c.Run()
|
||||||
|
if err != nil {
|
||||||
|
logFailure("install failed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if installDryRun {
|
||||||
|
logSuccess("install dry-run finished")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logAction("verifying installation")
|
||||||
|
for _, deployment := range []string{"source-controller", "kustomize-controller"} {
|
||||||
|
command = fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s",
|
||||||
|
namespace, deployment, timeout.String())
|
||||||
|
c = exec.CommandContext(ctx, "/bin/sh", "-c", command)
|
||||||
|
c.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
|
c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
|
err := c.Run()
|
||||||
|
if err != nil {
|
||||||
|
logFailure("install failed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess("install finished")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -4,8 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
@@ -16,13 +17,17 @@ import (
|
|||||||
var VERSION = "0.0.1"
|
var VERSION = "0.0.1"
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "tk",
|
Use: "tk",
|
||||||
Short: "Kubernetes CD assembler",
|
Short: "Kubernetes CD assembler",
|
||||||
Version: VERSION,
|
Version: VERSION,
|
||||||
|
SilenceUsage: true,
|
||||||
|
SilenceErrors: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
kubeconfig string
|
kubeconfig string
|
||||||
|
namespace string
|
||||||
|
timeout time.Duration
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -30,18 +35,19 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", filepath.Join(home, ".kube", "config"),
|
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", filepath.Join(home, ".kube", "config"),
|
||||||
"path to the kubeconfig file")
|
"path to the kubeconfig file")
|
||||||
} else {
|
} else {
|
||||||
checkCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "",
|
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "",
|
||||||
"absolute path to the kubeconfig file")
|
"absolute path to the kubeconfig file")
|
||||||
}
|
}
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&namespace, "namespace", "", "gitops-system",
|
||||||
|
"the namespace scope for this operation")
|
||||||
|
rootCmd.PersistentFlags().DurationVarP(&timeout, "timeout", "", 5*time.Minute,
|
||||||
|
"timeout for this operation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
rootCmd.SetArgs(os.Args[1:])
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
e := err.Error()
|
logFailure("%v", err)
|
||||||
fmt.Println(strings.ToUpper(e[:1]) + e[1:])
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +59,7 @@ func homeDir() string {
|
|||||||
return os.Getenv("USERPROFILE") // windows
|
return os.Getenv("USERPROFILE") // windows
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKubernetesClient() (*kubernetes.Clientset, error) {
|
func kubernetesClient() (*kubernetes.Clientset, error) {
|
||||||
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -66,3 +72,24 @@ func NewKubernetesClient() (*kubernetes.Clientset, error) {
|
|||||||
|
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func execCommand(command string) (string, error) {
|
||||||
|
c := exec.Command("/bin/sh", "-c", command)
|
||||||
|
output, err := c.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func logAction(format string, a ...interface{}) {
|
||||||
|
fmt.Println(`✚`, fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func logSuccess(format string, a ...interface{}) {
|
||||||
|
fmt.Println(`✔`, fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func logFailure(format string, a ...interface{}) {
|
||||||
|
fmt.Println(`✗`, fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|||||||
79
cmd/tk/uninstall.go
Normal file
79
cmd/tk/uninstall.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/manifoldco/promptui"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var uninstallCmd = &cobra.Command{
|
||||||
|
Use: "uninstall",
|
||||||
|
Short: "Uninstall the toolkit components",
|
||||||
|
Long: `
|
||||||
|
The uninstall command removes the namespace, cluster roles,
|
||||||
|
cluster role bindings and CRDs`,
|
||||||
|
Example: ` uninstall --namespace=gitops-system --crds --dry-run`,
|
||||||
|
RunE: uninstallCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
uninstallCRDs bool
|
||||||
|
uninstallDryRun bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
uninstallCmd.Flags().BoolVarP(&uninstallCRDs, "crds", "", false,
|
||||||
|
"removes all CRDs previously installed")
|
||||||
|
uninstallCmd.Flags().BoolVarP(&uninstallDryRun, "dry-run", "", false,
|
||||||
|
"only print the object that would be deleted")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(uninstallCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uninstallCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
dryRun := ""
|
||||||
|
if uninstallDryRun {
|
||||||
|
dryRun = "--dry-run=client"
|
||||||
|
} else {
|
||||||
|
prompt := promptui.Prompt{
|
||||||
|
Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", namespace),
|
||||||
|
IsConfirm: true,
|
||||||
|
}
|
||||||
|
if _, err := prompt.Run(); err != nil {
|
||||||
|
logFailure("aborting")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kinds := "namespace,clusterroles,clusterrolebindings"
|
||||||
|
if uninstallCRDs {
|
||||||
|
kinds += ",crds"
|
||||||
|
}
|
||||||
|
|
||||||
|
command := fmt.Sprintf("kubectl delete %s -l app.kubernetes.io/instance=%s --timeout=%s %s",
|
||||||
|
kinds, namespace, timeout.String(), dryRun)
|
||||||
|
c := exec.CommandContext(ctx, "/bin/sh", "-c", command)
|
||||||
|
|
||||||
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
|
c.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
|
||||||
|
c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)
|
||||||
|
|
||||||
|
logAction("uninstalling components")
|
||||||
|
err := c.Run()
|
||||||
|
if err != nil {
|
||||||
|
logFailure("uninstall failed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess("uninstall finished")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@@ -3,6 +3,8 @@ module github.com/fluxcd/toolkit
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
|
github.com/manifoldco/promptui v0.7.0
|
||||||
github.com/spf13/cobra v0.0.6
|
github.com/spf13/cobra v0.0.6
|
||||||
k8s.io/client-go v0.18.0
|
k8s.io/client-go v0.18.0
|
||||||
)
|
)
|
||||||
|
|||||||
19
go.sum
19
go.sum
@@ -26,7 +26,15 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||||
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
@@ -107,6 +115,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
|||||||
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
|
||||||
|
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
@@ -118,8 +128,16 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
|
||||||
|
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4=
|
||||||
|
github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
|
||||||
|
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
@@ -226,6 +244,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
|||||||
5
manifests/bases/kustomize-controller/kustomization.yaml
Normal file
5
manifests/bases/kustomize-controller/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- github.com/fluxcd/kustomize-controller/config//crd?ref=v0.0.1-alpha.4
|
||||||
|
- github.com/fluxcd/kustomize-controller/config//manager?ref=v0.0.1-alpha.4
|
||||||
5
manifests/bases/source-controller/kustomization.yaml
Normal file
5
manifests/bases/source-controller/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- github.com/fluxcd/source-controller/config//crd?ref=v0.0.1-alpha.2
|
||||||
|
- github.com/fluxcd/source-controller/config//manager?ref=v0.0.1-alpha.2
|
||||||
11
manifests/install/kustomization.yaml
Normal file
11
manifests/install/kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: gitops-system
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- ../bases/source-controller
|
||||||
|
- ../bases/kustomize-controller
|
||||||
|
- ../rbac
|
||||||
|
- ../policies
|
||||||
|
transformers:
|
||||||
|
- labels.yaml
|
||||||
9
manifests/install/labels.yaml
Normal file
9
manifests/install/labels.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: builtin
|
||||||
|
kind: LabelTransformer
|
||||||
|
metadata:
|
||||||
|
name: labels
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: gitops-system
|
||||||
|
fieldSpecs:
|
||||||
|
- path: metadata/labels
|
||||||
|
create: true
|
||||||
4
manifests/install/namespace.yaml
Normal file
4
manifests/install/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: gitops-system
|
||||||
8
manifests/policies/deny-ingress.yaml
Normal file
8
manifests/policies/deny-ingress.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: deny-ingress
|
||||||
|
spec:
|
||||||
|
podSelector: {}
|
||||||
|
policyTypes:
|
||||||
|
- Ingress
|
||||||
4
manifests/policies/kustomization.yaml
Normal file
4
manifests/policies/kustomization.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- deny-ingress.yaml
|
||||||
23
manifests/rbac/cluster_role.yaml
Normal file
23
manifests/rbac/cluster_role.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: cluster-reconciler
|
||||||
|
rules:
|
||||||
|
- apiGroups: ['*']
|
||||||
|
resources: ['*']
|
||||||
|
verbs: ['*']
|
||||||
|
- nonResourceURLs: ['*']
|
||||||
|
verbs: ['*']
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: cluster-reconciler
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: cluster-reconciler
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: system
|
||||||
5
manifests/rbac/kustomization.yaml
Normal file
5
manifests/rbac/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- cluster_role.yaml
|
||||||
|
- role.yaml
|
||||||
24
manifests/rbac/role.yaml
Normal file
24
manifests/rbac/role.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: crd-controller
|
||||||
|
rules:
|
||||||
|
- apiGroups: ['source.fluxcd.io']
|
||||||
|
resources: ['*']
|
||||||
|
verbs: ['*']
|
||||||
|
- apiGroups: ['kustomize.fluxcd.io']
|
||||||
|
resources: ['*']
|
||||||
|
verbs: ['*']
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: crd-controller
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: crd-controller
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: system
|
||||||
Reference in New Issue
Block a user