@ -0,0 +1,7 @@ |
||||
.github/ |
||||
.local/ |
||||
bin/ |
||||
_dist/ |
||||
tools/ |
||||
proxy/ |
||||
site/ |
@ -0,0 +1,455 @@ |
||||
--- |
||||
########################################### |
||||
##### k3d CLI/binary release pipeline ##### |
||||
########################################### |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: main |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
|
||||
- name: lint |
||||
image: golang:1.14 |
||||
commands: |
||||
- make ci-setup |
||||
- make check-fmt lint |
||||
when: |
||||
event: |
||||
- push |
||||
- pull_request |
||||
- tag |
||||
|
||||
- name: test |
||||
image: docker:19.03 |
||||
volumes: |
||||
- name: dockersock |
||||
path: /var/run |
||||
commands: |
||||
- apk add git bash curl sudo jq make |
||||
- sleep 5 # give docker enough time to start |
||||
- make e2e |
||||
when: |
||||
event: |
||||
- push |
||||
- pull_request |
||||
- tag |
||||
|
||||
- name: build |
||||
image: golang:1.14 |
||||
environment: |
||||
GIT_TAG: "${DRONE_TAG}" |
||||
commands: |
||||
- make ci-setup |
||||
- make build-cross |
||||
depends_on: |
||||
- lint |
||||
- test |
||||
when: |
||||
branch: |
||||
- main |
||||
event: |
||||
- push |
||||
- tag |
||||
|
||||
- name: pre-release |
||||
image: plugins/github-release |
||||
settings: |
||||
api_key: |
||||
from_secret: github_token |
||||
files: |
||||
- _dist/* |
||||
checksum: |
||||
- sha256 |
||||
prerelease: true |
||||
depends_on: |
||||
- lint |
||||
- test |
||||
- build |
||||
when: |
||||
event: |
||||
- tag |
||||
ref: |
||||
include: |
||||
- "refs/tags/*rc*" |
||||
- "refs/tags/*beta*" |
||||
- "refs/tags/*alpha*" |
||||
|
||||
- name: release |
||||
image: plugins/github-release |
||||
settings: |
||||
api_key: |
||||
from_secret: github_token |
||||
files: |
||||
- _dist/* |
||||
checksum: |
||||
- sha256 |
||||
depends_on: |
||||
- lint |
||||
- test |
||||
- build |
||||
when: |
||||
event: |
||||
- tag |
||||
ref: |
||||
exclude: |
||||
- "refs/tags/*rc*" |
||||
- "refs/tags/*beta*" |
||||
- "refs/tags/*alpha*" |
||||
|
||||
services: |
||||
# Starting the docker service to be used by dind |
||||
- name: docker |
||||
image: docker:19.03-dind |
||||
privileged: true |
||||
volumes: |
||||
- name: dockersock |
||||
path: /var/run |
||||
|
||||
volumes: |
||||
- name: dockersock |
||||
temp: {} |
||||
|
||||
--- |
||||
######################### |
||||
##### Documentation ##### |
||||
######################### |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: docs |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
|
||||
- name: build |
||||
image: python:3.8 |
||||
commands: |
||||
- python3 -m pip install -r docs/requirements.txt |
||||
- mkdocs build --verbose --clean --strict |
||||
when: |
||||
branch: |
||||
- main |
||||
event: |
||||
- push |
||||
|
||||
- name: publish |
||||
image: plugins/gh-pages |
||||
settings: |
||||
password: |
||||
from_secret: github_token |
||||
username: rancherio-gh-m |
||||
pages_directory: site/ |
||||
target_branch: gh-pages |
||||
when: |
||||
branch: |
||||
- main |
||||
event: |
||||
- push |
||||
|
||||
trigger: |
||||
event: |
||||
- push |
||||
branch: |
||||
- main |
||||
|
||||
--- |
||||
##################### |
||||
##### k3d-proxy ##### |
||||
##################### |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: proxy_linux_amd64 |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-proxy |
||||
tags: |
||||
- latest-linux-amd64 |
||||
- "${DRONE_TAG}-linux-amd64" |
||||
dockerfile: proxy/Dockerfile |
||||
context: proxy/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
|
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: proxy_linux_arm |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: arm |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-proxy |
||||
tags: |
||||
- latest-linux-arm |
||||
- "${DRONE_TAG}-linux-arm" |
||||
dockerfile: proxy/Dockerfile |
||||
context: proxy/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
build_args: |
||||
- ARCH=arm |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
|
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: proxy_linux_arm64 |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: arm64 |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-proxy |
||||
tags: |
||||
- latest-linux-arm64 |
||||
- "${DRONE_TAG}-linux-arm64" |
||||
dockerfile: proxy/Dockerfile |
||||
context: proxy/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
build_args: |
||||
- ARCH=arm64 |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
|
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: proxy_manifest |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
- name: push_manifest |
||||
image: plugins/manifest |
||||
settings: |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
target: "rancher/k3d-proxy:${DRONE_TAG}" |
||||
template: "rancher/k3d-proxy:${DRONE_TAG}-OS-ARCH" |
||||
platforms: |
||||
- linux/amd64 |
||||
- linux/arm |
||||
- linux/arm64 |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
- proxy_linux_amd64 |
||||
- proxy_linux_arm |
||||
- proxy_linux_arm64 |
||||
|
||||
--- |
||||
##################### |
||||
##### k3d-tools ##### |
||||
##################### |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: tools_linux_amd64 |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-tools |
||||
tags: |
||||
- latest-linux-amd64 |
||||
- "${DRONE_TAG}-linux-amd64" |
||||
dockerfile: tools/Dockerfile |
||||
context: tools/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
|
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: tools_linux_arm |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: arm |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-tools |
||||
tags: |
||||
- latest-linux-arm |
||||
- "${DRONE_TAG}-linux-arm" |
||||
dockerfile: tools/Dockerfile |
||||
context: tools/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: tools_linux_arm64 |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: arm64 |
||||
|
||||
steps: |
||||
- name: build_push |
||||
image: plugins/docker |
||||
settings: |
||||
repo: rancher/k3d-tools |
||||
tags: |
||||
- latest-linux-arm64 |
||||
- "${DRONE_TAG}-linux-arm64" |
||||
dockerfile: tools/Dockerfile |
||||
context: tools/ |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
--- |
||||
|
||||
kind: pipeline |
||||
type: docker |
||||
name: tools_manifest |
||||
|
||||
platform: |
||||
os: linux |
||||
arch: amd64 |
||||
|
||||
steps: |
||||
- name: push_manifest |
||||
image: plugins/manifest |
||||
settings: |
||||
username: |
||||
from_secret: docker_username |
||||
password: |
||||
from_secret: docker_password |
||||
target: "rancher/k3d-tools:${DRONE_TAG}" |
||||
template: "rancher/k3d-tools:${DRONE_TAG}-OS-ARCH" |
||||
platforms: |
||||
- linux/amd64 |
||||
- linux/arm |
||||
- linux/arm64 |
||||
when: |
||||
event: |
||||
- tag |
||||
|
||||
trigger: |
||||
event: |
||||
- tag |
||||
|
||||
depends_on: |
||||
- main |
||||
- tools_linux_amd64 |
||||
- tools_linux_arm |
||||
- tools_linux_arm64 |
@ -1,47 +0,0 @@ |
||||
matrix: |
||||
include: |
||||
- dist: bionic |
||||
language: go |
||||
env: |
||||
- GO111MODULE=on |
||||
go: |
||||
- 1.14.x |
||||
git: |
||||
depth: 1 |
||||
install: true |
||||
before_script: |
||||
- make ci-setup |
||||
script: |
||||
- make -e "E2E_SKIP=test_multi_master" ci-tests build-cross |
||||
deploy: |
||||
provider: releases |
||||
skip_cleanup: true |
||||
api_key: |
||||
secure: VFb0jmL6t+cuKWAGC5OLeseTJrK3CakD5Laeyp0JVG/o3/cYgHP0lIeDmJJMZL/Luxm5aL8QHsCRfQoMBAnj6Q8hchI9rbcYhFZzuFJYyDxjcrPm0+kM3yiK14lQZNvksy2ZSsO7D63c8x9sQVrEus4idVTUoxrpSXLM2eVjl6W0O2RdZvLsxgaLPwV1ufpihrqbXdEUjt/YSYpHiC5gS3o+FcyMGucJQdN/L7p6jyAqVgg4+t8bdyWj6+MEG4p8lmWhhbGzDo38iMxtCBu+nDHRsbivay3eJZ643VguX0lj62Vt5KUTcVJntmZqQ2UF6FoEVUPOegkrSeoiMuOH1+nYwcsfMFijMkrcFhb6bAisJJd6agdhFWXiSwL88FQkJh0DqeA0tFFIzDbTS/AZTY4Li8bWng3aCBgSXiMzIBf0es+wMDw0gwhfH44Y/RAsKSQJ/Lln00AaVzkOkOWOmu5Ks0CVYDy0M5QDQOCW2E9TIb7WdIMh3aNCkZi+rGovigejJv3vUZqkN03Og07Hbrjgfg28iY3isIt3soOrVqek2hJJFnKjUhhv2OhJm3z6FpTyMViUtSmJ+LTiBjpyiWC4QuaITDadCJTxZQwobhI+18c2Zi5/HjTX1pgD1wk3quv9R4bGjVINenefG6xxaNj+CeFTfrQnnHuXOL50828= |
||||
file: |
||||
- _dist/k3d-darwin-amd64 |
||||
- _dist/k3d-linux-386 |
||||
- _dist/k3d-linux-amd64 |
||||
- _dist/k3d-linux-arm |
||||
- _dist/k3d-linux-arm64 |
||||
- _dist/k3d-windows-amd64.exe |
||||
on: |
||||
repo: rancher/k3d |
||||
tags: true |
||||
- dist: bionic |
||||
language: python |
||||
python: 3.8 |
||||
before_script: |
||||
- python3 -m pip install -r docs/requirements.txt |
||||
script: |
||||
- mkdocs build --verbose --clean --strict |
||||
deploy: |
||||
provider: pages |
||||
skip_cleanup: true |
||||
github_token: |
||||
secure: VFb0jmL6t+cuKWAGC5OLeseTJrK3CakD5Laeyp0JVG/o3/cYgHP0lIeDmJJMZL/Luxm5aL8QHsCRfQoMBAnj6Q8hchI9rbcYhFZzuFJYyDxjcrPm0+kM3yiK14lQZNvksy2ZSsO7D63c8x9sQVrEus4idVTUoxrpSXLM2eVjl6W0O2RdZvLsxgaLPwV1ufpihrqbXdEUjt/YSYpHiC5gS3o+FcyMGucJQdN/L7p6jyAqVgg4+t8bdyWj6+MEG4p8lmWhhbGzDo38iMxtCBu+nDHRsbivay3eJZ643VguX0lj62Vt5KUTcVJntmZqQ2UF6FoEVUPOegkrSeoiMuOH1+nYwcsfMFijMkrcFhb6bAisJJd6agdhFWXiSwL88FQkJh0DqeA0tFFIzDbTS/AZTY4Li8bWng3aCBgSXiMzIBf0es+wMDw0gwhfH44Y/RAsKSQJ/Lln00AaVzkOkOWOmu5Ks0CVYDy0M5QDQOCW2E9TIb7WdIMh3aNCkZi+rGovigejJv3vUZqkN03Og07Hbrjgfg28iY3isIt3soOrVqek2hJJFnKjUhhv2OhJm3z6FpTyMViUtSmJ+LTiBjpyiWC4QuaITDadCJTxZQwobhI+18c2Zi5/HjTX1pgD1wk3quv9R4bGjVINenefG6xxaNj+CeFTfrQnnHuXOL50828= |
||||
local_dir: site |
||||
on: |
||||
repo: rancher/k3d |
||||
branch: master |
||||
|
@ -0,0 +1,129 @@ |
||||
/* |
||||
Copyright © 2020 The k3d Author(s) |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
*/ |
||||
package cluster |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"os" |
||||
"strings" |
||||
|
||||
"github.com/rancher/k3d/v3/cmd/util" |
||||
k3cluster "github.com/rancher/k3d/v3/pkg/cluster" |
||||
"github.com/rancher/k3d/v3/pkg/runtimes" |
||||
k3d "github.com/rancher/k3d/v3/pkg/types" |
||||
"github.com/spf13/cobra" |
||||
|
||||
log "github.com/sirupsen/logrus" |
||||
|
||||
"github.com/liggitt/tabwriter" |
||||
) |
||||
|
||||
// TODO : deal with --all flag to manage differentiate started cluster and stopped cluster like `docker ps` and `docker ps -a`
|
||||
type clusterFlags struct { |
||||
noHeader bool |
||||
token bool |
||||
} |
||||
|
||||
// NewCmdClusterList returns a new cobra command
|
||||
func NewCmdClusterList() *cobra.Command { |
||||
|
||||
clusterFlags := clusterFlags{} |
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{ |
||||
Use: "list [NAME [NAME...]]", |
||||
Aliases: []string{"ls", "get"}, |
||||
Short: "List cluster(s)", |
||||
Long: `List cluster(s).`, |
||||
Run: func(cmd *cobra.Command, args []string) { |
||||
clusters := buildClusterList(cmd.Context(), args) |
||||
PrintClusters(clusters, clusterFlags) |
||||
}, |
||||
ValidArgsFunction: util.ValidArgsAvailableClusters, |
||||
} |
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolVar(&clusterFlags.noHeader, "no-headers", false, "Disable headers") |
||||
cmd.Flags().BoolVar(&clusterFlags.token, "token", false, "Print k3s cluster token") |
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd |
||||
} |
||||
|
||||
func buildClusterList(ctx context.Context, args []string) []*k3d.Cluster { |
||||
var clusters []*k3d.Cluster |
||||
var err error |
||||
|
||||
if len(args) == 0 { |
||||
// cluster name not specified : get all clusters
|
||||
clusters, err = k3cluster.ClusterList(ctx, runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
} else { |
||||
for _, clusterName := range args { |
||||
// cluster name specified : get specific cluster
|
||||
retrievedCluster, err := k3cluster.ClusterGet(ctx, runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName}) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
clusters = append(clusters, retrievedCluster) |
||||
} |
||||
} |
||||
|
||||
return clusters |
||||
} |
||||
|
||||
// PrintPrintClusters : display list of cluster
|
||||
func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) { |
||||
|
||||
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths) |
||||
defer tabwriter.Flush() |
||||
|
||||
if !flags.noHeader { |
||||
headers := []string{"NAME", "SERVERS", "AGENTS", "LOADBALANCER"} // TODO: getCluster: add status column
|
||||
if flags.token { |
||||
headers = append(headers, "TOKEN") |
||||
} |
||||
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t")) |
||||
if err != nil { |
||||
log.Fatalln("Failed to print headers") |
||||
} |
||||
} |
||||
|
||||
k3cluster.SortClusters(clusters) |
||||
|
||||
for _, cluster := range clusters { |
||||
serverCount := cluster.ServerCount() |
||||
agentCount := cluster.AgentCount() |
||||
hasLB := cluster.HasLoadBalancer() |
||||
|
||||
if flags.token { |
||||
fmt.Fprintf(tabwriter, "%s\t%d\t%d\t%t\t%s\n", cluster.Name, serverCount, agentCount, hasLB, cluster.Token) |
||||
} else { |
||||
fmt.Fprintf(tabwriter, "%s\t%d\t%d\t%t\n", cluster.Name, serverCount, agentCount, hasLB) |
||||
} |
||||
} |
||||
} |
@ -1,128 +0,0 @@ |
||||
/* |
||||
Copyright © 2020 The k3d Author(s) |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
*/ |
||||
package get |
||||
|
||||
import ( |
||||
"fmt" |
||||
"os" |
||||
"sort" |
||||
"strings" |
||||
|
||||
"github.com/rancher/k3d/pkg/cluster" |
||||
"github.com/rancher/k3d/pkg/runtimes" |
||||
k3d "github.com/rancher/k3d/pkg/types" |
||||
"github.com/spf13/cobra" |
||||
|
||||
log "github.com/sirupsen/logrus" |
||||
|
||||
"github.com/liggitt/tabwriter" |
||||
) |
||||
|
||||
// NewCmdGetCluster returns a new cobra command
|
||||
func NewCmdGetCluster() *cobra.Command { |
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{ |
||||
Use: "cluster [NAME [NAME...]]", |
||||
Aliases: []string{"clusters"}, |
||||
Short: "Get cluster", |
||||
Long: `Get cluster.`, |
||||
Args: cobra.MinimumNArgs(0), // 0 or more; 0 = all
|
||||
Run: func(cmd *cobra.Command, args []string) { |
||||
log.Debugln("get cluster called") |
||||
clusters, headersOff := parseGetClusterCmd(cmd, args) |
||||
var existingClusters []*k3d.Cluster |
||||
if clusters == nil { // Option a) no cluster name specified -> get all clusters
|
||||
found, err := cluster.GetClusters(runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
existingClusters = append(existingClusters, found...) |
||||
} else { // Option b) cluster name specified -> get specific cluster
|
||||
found, err := cluster.GetCluster(clusters, runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
existingClusters = append(existingClusters, found) |
||||
} |
||||
// print existing clusters
|
||||
printClusters(existingClusters, headersOff) |
||||
}, |
||||
} |
||||
|
||||
// add flags
|
||||
cmd.Flags().Bool("no-headers", false, "Disable headers") |
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd |
||||
} |
||||
|
||||
func parseGetClusterCmd(cmd *cobra.Command, args []string) (*k3d.Cluster, bool) { |
||||
|
||||
// --no-headers
|
||||
headersOff, err := cmd.Flags().GetBool("no-headers") |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
|
||||
// Args = cluster name
|
||||
if len(args) == 0 { |
||||
return nil, headersOff |
||||
} |
||||
|
||||
cluster := &k3d.Cluster{Name: args[0]} |
||||
|
||||
return cluster, headersOff |
||||
} |
||||
|
||||
func printClusters(clusters []*k3d.Cluster, headersOff bool) { |
||||
|
||||
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths) |
||||
defer tabwriter.Flush() |
||||
|
||||
if !headersOff { |
||||
headers := []string{"NAME", "MASTERS", "WORKERS"} // TODO: getCluster: add status column
|
||||
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t")) |
||||
if err != nil { |
||||
log.Fatalln("Failed to print headers") |
||||
} |
||||
} |
||||
|
||||
sort.Slice(clusters, func(i, j int) bool { |
||||
return clusters[i].Name < clusters[j].Name |
||||
}) |
||||
|
||||
for _, cluster := range clusters { |
||||
masterCount := 0 |
||||
workerCount := 0 |
||||
for _, node := range cluster.Nodes { |
||||
if node.Role == k3d.MasterRole { |
||||
masterCount++ |
||||
} else if node.Role == k3d.WorkerRole { |
||||
workerCount++ |
||||
} |
||||
} |
||||
fmt.Fprintf(tabwriter, "%s\t%d\t%d\n", cluster.Name, masterCount, workerCount) |
||||
} |
||||
} |
@ -0,0 +1,140 @@ |
||||
/* |
||||
Copyright © 2020 The k3d Author(s) |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
*/ |
||||
package kubeconfig |
||||
|
||||
import ( |
||||
"fmt" |
||||
"os" |
||||
"path" |
||||
"strings" |
||||
|
||||
"github.com/rancher/k3d/v3/cmd/util" |
||||
"github.com/rancher/k3d/v3/pkg/cluster" |
||||
"github.com/rancher/k3d/v3/pkg/runtimes" |
||||
k3d "github.com/rancher/k3d/v3/pkg/types" |
||||
k3dutil "github.com/rancher/k3d/v3/pkg/util" |
||||
"github.com/spf13/cobra" |
||||
"k8s.io/client-go/tools/clientcmd" |
||||
|
||||
log "github.com/sirupsen/logrus" |
||||
) |
||||
|
||||
type mergeKubeconfigFlags struct { |
||||
all bool |
||||
output string |
||||
targetDefault bool |
||||
} |
||||
|
||||
// NewCmdKubeconfigMerge returns a new cobra command
|
||||
func NewCmdKubeconfigMerge() *cobra.Command { |
||||
|
||||
writeKubeConfigOptions := cluster.WriteKubeConfigOptions{} |
||||
|
||||
mergeKubeconfigFlags := mergeKubeconfigFlags{} |
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{ |
||||
Use: "merge [CLUSTER [CLUSTER [...]] | --all]", |
||||
Aliases: []string{"write"}, |
||||
Long: `Merge/Write kubeconfig(s) from cluster(s) into existing kubeconfig/file.`, |
||||
Short: "Merge/Write kubeconfig(s) from cluster(s) into existing kubeconfig/file.", |
||||
ValidArgsFunction: util.ValidArgsAvailableClusters, |
||||
Args: cobra.MinimumNArgs(0), |
||||
Run: func(cmd *cobra.Command, args []string) { |
||||
var clusters []*k3d.Cluster |
||||
var err error |
||||
|
||||
if mergeKubeconfigFlags.targetDefault && mergeKubeconfigFlags.output != "" { |
||||
log.Fatalln("Cannot use both '--output' and '--merge-default-kubeconfig' at the same time") |
||||
} |
||||
|
||||
// generate list of clusters
|
||||
if mergeKubeconfigFlags.all { |
||||
clusters, err = cluster.ClusterList(cmd.Context(), runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
} else { |
||||
|
||||
clusternames := []string{k3d.DefaultClusterName} |
||||
if len(args) != 0 { |
||||
clusternames = args |
||||
} |
||||
|
||||
for _, clusterName := range clusternames { |
||||
retrievedCluster, err := cluster.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName}) |
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
clusters = append(clusters, retrievedCluster) |
||||
} |
||||
} |
||||
|
||||
// get kubeconfigs from all clusters
|
||||
errorGettingKubeconfig := false |
||||
var outputs []string |
||||
outputDir, err := k3dutil.GetConfigDirOrCreate() |
||||
if err != nil { |
||||
log.Errorln(err) |
||||
log.Fatalln("Failed to save kubeconfig to local directory") |
||||
} |
||||
for _, c := range clusters { |
||||
log.Debugf("Getting kubeconfig for cluster '%s'", c.Name) |
||||
output := mergeKubeconfigFlags.output |
||||
if output == "" && !mergeKubeconfigFlags.targetDefault { |
||||
output = path.Join(outputDir, fmt.Sprintf("kubeconfig-%s.yaml", c.Name)) |
||||
} |
||||
output, err = cluster.KubeconfigGetWrite(cmd.Context(), runtimes.SelectedRuntime, c, output, &writeKubeConfigOptions) |
||||
if err != nil { |
||||
log.Errorln(err) |
||||
errorGettingKubeconfig = true |
||||
} else { |
||||
outputs = append(outputs, output) |
||||
} |
||||
} |
||||
|
||||
// only print kubeconfig file path if output is not stdout ("-")
|
||||
if mergeKubeconfigFlags.output != "-" { |
||||
fmt.Println(strings.Join(outputs, ":")) |
||||
} |
||||
|
||||
// return with non-zero exit code, if there was an error for one of the clusters
|
||||
if errorGettingKubeconfig { |
||||
os.Exit(1) |
||||
} |
||||
}, |
||||
} |
||||
|
||||
// add flags
|
||||
cmd.Flags().StringVarP(&mergeKubeconfigFlags.output, "output", "o", "", fmt.Sprintf("Define output [ - | FILE ] (default from $KUBECONFIG or %s", clientcmd.RecommendedHomeFile)) |
||||
if err := cmd.MarkFlagFilename("output"); err != nil { |
||||
log.Fatalln("Failed to mark flag --output as filename") |
||||
} |
||||
cmd.Flags().BoolVarP(&mergeKubeconfigFlags.targetDefault, "merge-default-kubeconfig", "d", false, fmt.Sprintf("Merge into the default kubeconfig ($KUBECONFIG or %s)", clientcmd.RecommendedHomeFile)) |
||||
cmd.Flags().BoolVarP(&writeKubeConfigOptions.UpdateExisting, "update", "u", true, "Update conflicting fields in existing kubeconfig") |
||||
cmd.Flags().BoolVarP(&writeKubeConfigOptions.UpdateCurrentContext, "switch-context", "s", true, "Switch to new context") |
||||
cmd.Flags().BoolVar(&writeKubeConfigOptions.OverwriteExisting, "overwrite", false, "[Careful!] Overwrite existing file, ignoring its contents") |
||||
cmd.Flags().BoolVarP(&mergeKubeconfigFlags.all, "all", "a", false, "Get kubeconfigs from all existing clusters") |
||||
|
||||
// done
|
||||
return cmd |
||||
} |
@ -0,0 +1,97 @@ |
||||
/* |
||||
Copyright © 2020 The k3d Author(s) |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
*/ |
||||
package util |
||||
|
||||
import ( |
||||
"context" |
||||
"strings" |
||||
|
||||
k3dcluster "github.com/rancher/k3d/v3/pkg/cluster" |
||||
"github.com/rancher/k3d/v3/pkg/runtimes" |
||||
k3d "github.com/rancher/k3d/v3/pkg/types" |
||||
log "github.com/sirupsen/logrus" |
||||
"github.com/spf13/cobra" |
||||
) |
||||
|
||||
// ValidArgsAvailableClusters is used for shell completion: proposes the list of existing clusters
|
||||
func ValidArgsAvailableClusters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { |
||||
|
||||
var completions []string |
||||
var clusters []*k3d.Cluster |
||||
clusters, err := k3dcluster.ClusterList(context.Background(), runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Errorln("Failed to get list of clusters for shell completion") |
||||
return nil, cobra.ShellCompDirectiveError |
||||
} |
||||
|
||||
clusterLoop: |
||||
for _, cluster := range clusters { |
||||
for _, arg := range args { |
||||
if arg == cluster.Name { // only clusters, that are not in the args yet
|
||||
continue clusterLoop |
||||
} |
||||
} |
||||
if strings.HasPrefix(cluster.Name, toComplete) { |
||||
completions = append(completions, cluster.Name) |
||||
} |
||||
} |
||||
return completions, cobra.ShellCompDirectiveDefault |
||||
} |
||||
|
||||
// ValidArgsAvailableNodes is used for shell completion: proposes the list of existing nodes
|
||||
func ValidArgsAvailableNodes(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { |
||||
|
||||
var completions []string |
||||
var nodes []*k3d.Node |
||||
nodes, err := k3dcluster.NodeList(context.Background(), runtimes.SelectedRuntime) |
||||
if err != nil { |
||||
log.Errorln("Failed to get list of nodes for shell completion") |
||||
return nil, cobra.ShellCompDirectiveError |
||||
} |
||||
|
||||
nodeLoop: |
||||
for _, node := range nodes { |
||||
for _, arg := range args { |
||||
if arg == node.Name { // only clusters, that are not in the args yet
|
||||
continue nodeLoop |
||||
} |
||||
} |
||||
if strings.HasPrefix(node.Name, toComplete) { |
||||
completions = append(completions, node.Name) |
||||
} |
||||
} |
||||
return completions, cobra.ShellCompDirectiveDefault |
||||
} |
||||
|
||||
// ValidArgsNodeRoles is used for shell completion: proposes the list of possible node roles
|
||||
func ValidArgsNodeRoles(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { |
||||
|
||||
var completions []string |
||||
roles := []string{string(k3d.ServerRole), string(k3d.AgentRole)} |
||||
|
||||
for _, role := range roles { |
||||
if strings.HasPrefix(role, toComplete) { |
||||
completions = append(completions, role) |
||||
} |
||||
} |
||||
return completions, cobra.ShellCompDirectiveDefault |
||||
} |
@ -1,12 +1,12 @@ |
||||
# Defaults |
||||
|
||||
* multiple master nodes |
||||
* by default, when `--master` > 1 and no `--datastore-x` option is set, the first master node (master-0) will be the initializing master node |
||||
* the initializing master node will have the `--cluster-init` flag appended |
||||
* all other master nodes will refer to the initializing master node via `--server https://<init-node>:6443` |
||||
* API-Ports |
||||
* by default, we don't expose any API-Port (no host port mapping) |
||||
* kubeconfig |
||||
* if no output is set explicitly (via the `--output` flag), we use the default loading rules to get the default kubeconfig: |
||||
* First: kubeconfig specified via the KUBECONFIG environment variable (error out if multiple are specified) |
||||
* Second: default kubeconfig in home directory (e.g. `$HOME/.kube/config`) |
||||
- multiple server nodes |
||||
- by default, when `--server` > 1 and no `--datastore-x` option is set, the first server node (server-0) will be the initializing server node |
||||
- the initializing server node will have the `--cluster-init` flag appended |
||||
- all other server nodes will refer to the initializing server node via `--server https://<init-node>:6443` |
||||
- API-Ports |
||||
- by default, we don't expose any API-Port (no host port mapping) |
||||
- kubeconfig |
||||
- if `--[update|merge]-default-kubeconfig` is set, we use the default loading rules to get the default kubeconfig: |
||||
- First: kubeconfig specified via the KUBECONFIG environment variable (error out if multiple are specified) |
||||
- Second: default kubeconfig in home directory (e.g. `$HOME/.kube/config`) |
||||
|
@ -0,0 +1,215 @@ |
||||
{"version":2,"width":213,"height":47,"timestamp":1594792376,"theme":{},"env":{"SHELL":"/bin/zsh","TERM":"xterm-256color"}} |
||||
[2.221,"o","\u001b[H\u001b[2J\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K"] |
||||
[2.881,"o","k"] |
||||
[3.002,"o","\u0008k3"] |
||||
[3.187,"o","d"] |
||||
[3.32,"o"," "] |
||||
[3.42,"o","v"] |
||||
[3.53,"o","e"] |
||||
[3.662,"o","r"] |
||||
[3.827,"o","s"] |
||||
[3.913,"o","i"] |
||||
[4.113,"o","o"] |
||||
[4.245,"o","n"] |
||||
[4.443,"o","\u001b[?2004l\r\r\n"] |
||||
[4.471,"o","k3d version v3.0.0\r\nk3s version v1.18.6-k3s1 (default)\r\n"] |
||||
[4.473,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[5.719,"o","k"] |
||||
[5.829,"o","\u0008k3"] |
||||
[6.038,"o","d"] |
||||
[6.235,"o"," "] |
||||
[6.75,"o","c"] |
||||
[6.852,"o","l"] |
||||
[7.094,"o","u"] |
||||
[7.193,"o","s"] |
||||
[7.534,"o","t"] |
||||
[7.71,"o","e"] |
||||
[7.831,"o","r"] |
||||
[8.029,"o"," "] |
||||
[8.268,"o","l"] |
||||
[8.491,"o","i"] |
||||
[8.634,"o","s"] |
||||
[8.796,"o","t"] |
||||
[8.943,"o","\u001b[?2004l\r\r\n"] |
||||
[8.971,"o","NAME SERVERS AGENTS\r\n"] |
||||
[8.972,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[9.756,"o","k"] |
||||
[9.854,"o","\u0008k3"] |
||||
[10.05,"o","d"] |
||||
[10.448,"o"," "] |
||||
[10.811,"o","c"] |
||||
[10.91,"o","l"] |
||||
[11.119,"o","u"] |
||||
[11.174,"o","s"] |
||||
[11.284,"o","t"] |
||||
[11.416,"o","e"] |
||||
[11.515,"o","r"] |
||||
[11.648,"o"," "] |
||||
[11.746,"o","c"] |
||||
[11.988,"o","r"] |
||||
[12.054,"o","e"] |
||||
[12.087,"o","a"] |
||||
[12.208,"o","t"] |
||||
[12.285,"o","e"] |
||||
[13.055,"o"," "] |
||||
[13.77,"o","d"] |
||||
[13.858,"o","e"] |
||||
[13.99,"o","m"] |
||||
[14.133,"o","o"] |
||||
[14.321,"o"," "] |
||||
[14.629,"o","-"] |
||||
[14.801,"o","-"] |
||||
[14.867,"o","s"] |
||||
[15.065,"o","e"] |
||||
[15.111,"o","r"] |
||||
[15.343,"o","v"] |
||||
[15.409,"o","e"] |
||||
[15.519,"o","r"] |
||||
[15.706,"o","s"] |
||||
[15.905,"o"," "] |
||||
[16.74,"o","3"] |
||||
[16.914,"o"," "] |
||||
[17.137,"o","-"] |
||||
[17.291,"o","-"] |
||||
[17.44,"o","a"] |
||||
[17.586,"o","g"] |
||||
[17.687,"o","e"] |
||||
[17.763,"o","n"] |
||||
[17.84,"o","t"] |
||||
[18.017,"o","s"] |
||||
[18.259,"o"," "] |
||||
[18.379,"o","3"] |
||||
[19.137,"o","\u001b[?2004l\r\r\n"] |
||||
[19.222,"o","\u001b[36mINFO\u001b[0m[0000] Created network 'k3d-demo' \r\n"] |
||||
[19.225,"o","\u001b[36mINFO\u001b[0m[0000] Created volume 'k3d-demo-images' \r\n"] |
||||
[19.225,"o","\u001b[36mINFO\u001b[0m[0000] Creating initializing server node \r\n\u001b[36mINFO\u001b[0m[0000] Creating node 'k3d-demo-server-0' \r\n"] |
||||
[30.266,"o","\u001b[36mINFO\u001b[0m[0011] Creating node 'k3d-demo-server-1' \r\n"] |
||||
[31.634,"o","\u001b[36mINFO\u001b[0m[0012] Creating node 'k3d-demo-server-2' \r\n"] |
||||
[32.125,"o","\u001b[36mINFO\u001b[0m[0012] Creating node 'k3d-demo-agent-0' \r\n"] |
||||
[32.519,"o","\u001b[36mINFO\u001b[0m[0013] Creating node 'k3d-demo-agent-1' \r\n"] |
||||
[33.096,"o","\u001b[36mINFO\u001b[0m[0013] Creating node 'k3d-demo-agent-2' \r\n"] |
||||
[33.577,"o","\u001b[36mINFO\u001b[0m[0014] Creating LoadBalancer 'k3d-demo-serverlb' \r\n"] |
||||
[38.248,"o","\u001b[36mINFO\u001b[0m[0019] Cluster 'demo' created successfully! \r\n"] |
||||
[38.33,"o","\u001b[36mINFO\u001b[0m[0019] You can now use it like this: \r\nkubectl cluster-info\r\n"] |
||||
[38.335,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] |
||||
[38.336,"o","\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[40.212,"o","k"] |
||||
[40.465,"o","\u0008ku"] |
||||
[40.63,"o","b"] |
||||
[40.773,"o","e"] |
||||
[40.916,"o","c"] |
||||
[41.169,"o","t"] |
||||
[41.302,"o","l"] |
||||
[41.53,"o"," "] |
||||
[41.686,"o","c"] |
||||
[41.774,"o","o"] |
||||
[41.928,"o","n"] |
||||
[42.093,"o","f"] |
||||
[42.213,"o","i"] |
||||
[42.401,"o","g"] |
||||
[42.565,"o"," "] |
||||
[42.686,"o","v"] |
||||
[42.807,"o","i"] |
||||
[42.895,"o","e"] |
||||
[43.082,"o","w"] |
||||
[43.27,"o","\u001b[?2004l\r\r\n"] |
||||
[43.304,"o","apiVersion: v1\r\nclusters:\r\n- cluster:\r\n certificate-authority-data: DATA+OMITTED\r\n server: https://0.0.0.0:38365\r\n name: k3d-demo\r\ncontexts:\r\n- context:\r\n cluster: k3d-demo\r\n user: admin@k3d-demo\r\n name: k3d-demo\r\ncurrent-context: k3d-demo\r\nkind: Config\r\npreferences: {}\r\nusers:\r\n- name: admin@k3d-demo\r\n user:\r\n password: 1c22f8175521452403719784fa0b124f\r\n username: admin\r\n"] |
||||
[43.305,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] |
||||
[43.305,"o","\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[45.754,"o","k"] |
||||
[45.843,"o","\u0008k3"] |
||||
[45.987,"o","d"] |
||||
[46.075,"o"," "] |
||||
[46.24,"o","c"] |
||||
[46.36,"o","l"] |
||||
[46.569,"o","u"] |
||||
[46.658,"o","s"] |
||||
[46.768,"o","t"] |
||||
[46.91,"o","e"] |
||||
[46.977,"o","r"] |
||||
[47.042,"o"," "] |
||||
[47.252,"o","l"] |
||||
[47.472,"o","i"] |
||||
[47.56,"o","s"] |
||||
[47.681,"o","t"] |
||||
[47.846,"o","\u001b[?2004l\r\r\n"] |
||||
[47.88,"o","NAME SERVERS AGENTS\r\ndemo 3 3\r\n"] |
||||
[47.881,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] |
||||
[47.882,"o","\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[48.517,"o","k"] |
||||
[48.616,"o","\u0008k3"] |
||||
[48.77,"o","d"] |
||||
[48.968,"o"," "] |
||||
[50.133,"o","n"] |
||||
[50.276,"o","o"] |
||||
[50.33,"o","d"] |
||||
[50.386,"o","e"] |
||||
[50.462,"o"," "] |
||||
[50.605,"o","l"] |
||||
[50.792,"o","i"] |
||||
[50.881,"o","s"] |
||||
[51.046,"o","t"] |
||||
[51.255,"o","\u001b[?2004l\r\r\n"] |
||||
[51.266,"o","NAME ROLE CLUSTER\r\nk3d-demo-agent-0 agent "] |
||||
[51.266,"o","demo\r\nk3d-demo-agent-1 agent demo\r\nk3d-demo-agent-2 agent demo\r\nk3d-demo-server-0 server demo\r\nk3d-demo-server-1 server demo\r\nk3d-demo-server-2 server demo\r\nk3d-demo-serverlb loadbalancer demo\r\n"] |
||||
[51.267,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] |
||||
[51.267,"o","\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[58.525,"o","k"] |
||||
[58.822,"o","\u0008ku"] |
||||
[58.999,"o","b"] |
||||
[59.109,"o","e"] |
||||
[59.217,"o","c"] |
||||
[59.48,"o","t"] |
||||
[59.582,"o","l"] |
||||
[59.791,"o"," "] |
||||
[59.876,"o","g"] |
||||
[59.978,"o","e"] |
||||
[60.109,"o","t"] |
||||
[60.285,"o"," "] |
||||
[60.495,"o","n"] |
||||
[60.626,"o","o"] |
||||
[60.725,"o","d"] |
||||
[60.791,"o","e"] |
||||
[61,"o","s"] |
||||
[61.176,"o","\u001b[?2004l\r\r\n"] |
||||
[61.334,"o","NAME STATUS ROLES AGE VERSION\r\nk3d-demo-server-2 Ready master 22s v1.18.4+k3s1\r\nk3d-demo-agent-2 Ready \u003cnone\u003e 26s v1.18.4+k3s1\r\nk3d-demo-agent-0 Ready \u003cnone\u003e "] |
||||
[61.334,"o","27s v1.18.4+k3s1\r\nk3d-demo-agent-1 Ready \u003cnone\u003e 27s v1.18.4+k3s1\r\nk3d-demo-server-1 Ready master 19s v1.18.4+k3s1\r\nk3d-demo-server-0 Ready master 32s v1.18.4+k3s1\r\n"] |
||||
[61.336,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[63.901,"o","k"] |
||||
[64.08,"o","\u0008k3"] |
||||
[64.297,"o","d"] |
||||
[64.464,"o"," "] |
||||
[64.674,"o","c"] |
||||
[64.84,"o","l"] |
||||
[65.126,"o","u"] |
||||
[65.245,"o","s"] |
||||
[65.411,"o","t"] |
||||
[65.553,"o","e"] |
||||
[65.675,"o","r"] |
||||
[65.918,"o"," "] |
||||
[66.18,"o","d"] |
||||
[66.302,"o","e"] |
||||
[66.499,"o","l"] |
||||
[66.687,"o","e"] |
||||
[66.874,"o","t"] |
||||
[66.984,"o","e"] |
||||
[67.794,"o"," "] |
||||
[67.919,"o","d"] |
||||
[67.985,"o","e"] |
||||
[68.084,"o","m"] |
||||
[68.257,"o","o"] |
||||
[68.623,"o","\u001b[?2004l\r\r\n"] |
||||
[68.637,"o","\u001b[36mINFO\u001b[0m[0000] Deleting cluster 'demo' \r\n"] |
||||
[69.822,"o","\u001b[36mINFO\u001b[0m[0001] Deleted k3d-demo-serverlb \r\n"] |
||||
[70.309,"o","\u001b[36mINFO\u001b[0m[0001] Deleted k3d-demo-agent-2 \r\n"] |
||||
[71.017,"o","\u001b[36mINFO\u001b[0m[0002] Deleted k3d-demo-agent-1 \r\n"] |
||||
[71.645,"o","\u001b[36mINFO\u001b[0m[0003] Deleted k3d-demo-agent-0 \r\n"] |
||||
[72.274,"o","\u001b[36mINFO\u001b[0m[0003] Deleted k3d-demo-server-2 \r\n"] |
||||
[73.264,"o","\u001b[36mINFO\u001b[0m[0004] Deleted k3d-demo-server-1 \r\n"] |
||||
[74.155,"o","\u001b[36mINFO\u001b[0m[0005] Deleted k3d-demo-server-0 \r\n"] |
||||
[74.155,"o","\u001b[36mINFO\u001b[0m[0005] Deleting cluster network '2324ab59566f5bca41df87cbf7b65e14539cfe9feea1087f143eec45ac91652f' \r\n"] |
||||
[74.35,"o","\u001b[36mINFO\u001b[0m[0005] Deleting image volume 'k3d-demo-images' \r\n"] |
||||
[74.36,"o","\u001b[36mINFO\u001b[0m[0005] Removing cluster details from default kubeconfig... \r\n"] |
||||
[74.362,"o","\u001b[36mINFO\u001b[0m[0005] Removing standalone kubeconfig file (if there is one)... \r\n\u001b[36mINFO\u001b[0m[0005] Successfully deleted cluster demo! \r\n"] |
||||
[74.363,"o","\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32mThisCouldBeYou\u001b[0m$ \u001b[K\u001b[?2004h"] |
||||
[75.795,"o","\u001b[?2004l\r\r\n"] |
@ -0,0 +1,33 @@ |
||||
.md-header-nav__button.md-logo img, .md-header-nav__button.md-logo svg { |
||||
width: 3rem; |
||||
height: 3rem; |
||||
} |
||||
|
||||
.md-header-nav__button.md-logo { |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
.md-header { |
||||
height: 3rem; |
||||
} |
||||
|
||||
.md-header-nav { |
||||
align-items: center; |
||||
} |
||||
|
||||
.md-ellipsis { |
||||
display: inline; |
||||
} |
||||
|
||||
.md-header-nav__topic { |
||||
position: relative; |
||||
} |
||||
|
||||
[data-md-color-primary=black] .md-tabs { |
||||
background-color: #0DCEFF; |
||||
} |
||||
|
||||
.md-tabs { |
||||
color: black; |
||||
} |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 711 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 657 B After Width: | Height: | Size: 920 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 8.6 KiB |
@ -1,25 +0,0 @@ |
||||
# Creating multi-master clusters |
||||
|
||||
!!! info "Important note" |
||||
For the best results (and less unexpected issues), choose 1, 3, 5, ... master nodes. |
||||
|
||||
## Embedded dqlite |
||||
|
||||
Create a cluster with 3 master nodes using k3s' embedded dqlite database. |
||||
The first master to be created will use the `--cluster-init` flag and k3d will wait for it to be up and running before creating (and connecting) the other master nodes. |
||||
|
||||
```bash |
||||
k3d create cluster multimaster --masters 3 |
||||
``` |
||||
|
||||
## Adding master nodes to a running cluster |
||||
|
||||
In theory (and also in practice in most cases), this is as easy as executing the following command: |
||||
|
||||
```bash |
||||
k3d create node newmaster --cluster multimaster --role master |
||||
``` |
||||
|
||||
!!! important "There's a trap!" |
||||
If your cluster was initially created with only a single master node, then this will fail. |
||||
That's because the initial master node was not started with the `--cluster-init` flag and thus is not using the dqlite backend. |
@ -0,0 +1,25 @@ |
||||
# Creating multi-server clusters |
||||
|
||||
!!! info "Important note" |
||||
For the best results (and less unexpected issues), choose 1, 3, 5, ... server nodes. |
||||
|
||||
## Embedded dqlite |
||||
|
||||
Create a cluster with 3 server nodes using k3s' embedded dqlite database. |
||||
The first server to be created will use the `--cluster-init` flag and k3d will wait for it to be up and running before creating (and connecting) the other server nodes. |
||||
|
||||
```bash |
||||
k3d cluster create multiserver --servers 3 |
||||
``` |
||||
|
||||
## Adding server nodes to a running cluster |
||||
|
||||
In theory (and also in practice in most cases), this is as easy as executing the following command: |
||||
|
||||
```bash |
||||
k3d node create newserver --cluster multiserver --role server |
||||
``` |
||||
|
||||
!!! important "There's a trap!" |
||||
If your cluster was initially created with only a single server node, then this will fail. |
||||
That's because the initial server node was not started with the `--cluster-init` flag and thus is not using the dqlite backend. |
@ -1,47 +1,44 @@ |
||||
module github.com/rancher/k3d |
||||
module github.com/rancher/k3d/v3 |
||||
|
||||
go 1.14 |
||||
|
||||
require ( |
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect |
||||
github.com/Microsoft/go-winio v0.4.14 // indirect |
||||
github.com/Microsoft/hcsshim v0.8.6 // indirect |
||||
github.com/Microsoft/hcsshim v0.8.9 // indirect |
||||
github.com/containerd/cgroups v0.0.0-20190923161937-abd0b19954a6 // indirect |
||||
github.com/containerd/containerd v1.3.0-rc.2.0.20190924150618-aba201344ebf |
||||
github.com/containerd/containerd v1.3.4 |
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 // indirect |
||||
github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c // indirect |
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 // indirect |
||||
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd // indirect |
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c // indirect |
||||
github.com/docker/docker v1.4.2-0.20190905191220-3b23f9033967 |
||||
github.com/docker/distribution v0.0.0-20200319173657-742aab907b54 // indirect |
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200528204242-89382f2f2074+incompatible |
||||
github.com/docker/go-connections v0.4.0 |
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect |
||||
github.com/go-test/deep v1.0.4 |
||||
github.com/gogo/googleapis v1.3.0 // indirect |
||||
github.com/gogo/protobuf v1.3.1 // indirect |
||||
github.com/golang/protobuf v1.4.0 // indirect |
||||
github.com/golang/protobuf v1.4.2 // indirect |
||||
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5 |
||||
github.com/imdario/mergo v0.3.9 |
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de |
||||
github.com/mitchellh/go-homedir v1.1.0 |
||||
github.com/moby/sys/mount v0.1.0 // indirect |
||||
github.com/moby/term v0.0.0-20200507201656-73f35e472e8f // indirect |
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect |
||||
github.com/opencontainers/image-spec v1.0.1 // indirect |
||||
github.com/opencontainers/go-digest v1.0.0 // indirect |
||||
github.com/opencontainers/runc v0.1.1 // indirect |
||||
github.com/opencontainers/runtime-spec v1.0.1 // indirect |
||||
github.com/sirupsen/logrus v1.5.0 |
||||
github.com/spf13/cobra v1.0.0 |
||||
github.com/sirupsen/logrus v1.6.0 |
||||
github.com/spf13/cobra v1.0.1-0.20200629195214-2c5a0d300f8b |
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect |
||||
go.etcd.io/bbolt v1.3.3 // indirect |
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect |
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect |
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect |
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect |
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 |
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect |
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect |
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect |
||||
google.golang.org/grpc v1.23.0 // indirect |
||||
google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb // indirect |
||||
google.golang.org/grpc v1.29.1 // indirect |
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect |
||||
gopkg.in/yaml.v2 v2.2.8 // indirect |
||||
gotest.tools v2.2.0+incompatible // indirect |
||||
gotest.tools/v3 v3.0.2 // indirect |
||||
k8s.io/client-go v0.17.0 |
||||
k8s.io/utils v0.0.0-20200109141947-94aeca20bf09 // indirect |
||||
) |
||||
|
@ -0,0 +1,54 @@ |
||||
/* |
||||
Copyright © 2020 The k3d Author(s) |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
||||
*/ |
||||
package docker |
||||
|
||||
import ( |
||||
"context" |
||||
|
||||
"github.com/docker/docker/api/types" |
||||
"github.com/docker/docker/client" |
||||
log "github.com/sirupsen/logrus" |
||||
) |
||||
|
||||
// GetImages returns a list of images present in the runtime
|
||||
func (d Docker) GetImages(ctx context.Context) ([]string, error) { |
||||
// create docker client
|
||||
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) |
||||
if err != nil { |
||||
log.Errorln("Failed to create docker client") |
||||
return nil, err |
||||
} |
||||
defer docker.Close() |
||||
|
||||
imageSummary, err := docker.ImageList(ctx, types.ImageListOptions{All: true}) |
||||
if err != nil { |
||||
log.Errorln("Failed to list available docker images") |
||||
return nil, err |
||||
} |
||||
|
||||
var images []string |
||||
for _, image := range imageSummary { |
||||
images = append(images, image.RepoTags...) |
||||
} |
||||
|
||||
return images, nil |
||||
} |
@ -0,0 +1,13 @@ |
||||
FROM golang:1.14 as builder |
||||
ARG GIT_TAG |
||||
WORKDIR /app |
||||
COPY . . |
||||
ENV GIT_TAG=${GIT_TAG} |
||||
ENV GO111MODULE=on |
||||
ENV CGO_ENABLED=0 |
||||
RUN make build |
||||
|
||||
FROM busybox:1.31 |
||||
WORKDIR /app |
||||
COPY --from=builder /app/bin/k3d-tools . |
||||
ENTRYPOINT [ "/app/k3d-tools"] |