Compare commits
No commits in common. "main" and "gh-pages" have entirely different histories.
@ -1,150 +0,0 @@
|
||||
{
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": false,
|
||||
"contributors": [
|
||||
{
|
||||
"login": "iwilltry42",
|
||||
"name": "Thorsten Klein",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/25345277?v=4",
|
||||
"profile": "https://twitter.com/iwilltry42",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"ideas",
|
||||
"maintenance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zeerorg",
|
||||
"name": "Rishabh Gupta",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/13547997?v=4",
|
||||
"profile": "https://blog.zeerorg.site/",
|
||||
"contributions": [
|
||||
"ideas",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "louiznk",
|
||||
"name": "Louis Tournayre",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/25585516?v=4",
|
||||
"profile": "http://www.zenika.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lionelnicolas",
|
||||
"name": "Lionel Nicolas",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/6538664?v=4",
|
||||
"profile": "https://github.com/lionelnicolas",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "toonsevrin",
|
||||
"name": "Toon Sevrin",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/5507199?v=4",
|
||||
"profile": "https://github.com/toonsevrin.keys",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dhoppe",
|
||||
"name": "Dennis Hoppe",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/1111056?v=4",
|
||||
"profile": "http://debian-solutions.de",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"example"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "JohnnyCrazy",
|
||||
"name": "Jonas Dellinger",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/3109892?v=4",
|
||||
"profile": "https://dellinger.dev",
|
||||
"contributions": [
|
||||
"infra"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "markrexwinkel",
|
||||
"name": "markrexwinkel",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/10704814?v=4",
|
||||
"profile": "https://github.com/markrexwinkel",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "inercia",
|
||||
"name": "Alvaro",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/1841612?v=4",
|
||||
"profile": "http://inerciatech.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"ideas",
|
||||
"plugin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nunix",
|
||||
"name": "Nuno do Carmo",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/905874?v=4",
|
||||
"profile": "http://wsl.dev",
|
||||
"contributions": [
|
||||
"content",
|
||||
"tutorial",
|
||||
"question"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "erwinkersten",
|
||||
"name": "Erwin Kersten",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/4391121?v=4",
|
||||
"profile": "https://github.com/erwinkersten",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "searsaw",
|
||||
"name": "Alex Sears",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3712883?v=4",
|
||||
"profile": "http://www.alexsears.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Shanduur",
|
||||
"name": "Mateusz Urbanek",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/32583062?v=4",
|
||||
"profile": "http://shanduur.github.io",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "benjaminjb",
|
||||
"name": "Benjamin Blattberg",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4651855?v=4",
|
||||
"profile": "https://github.com/benjaminjb",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"projectName": "k3d",
|
||||
"projectOwner": "rancher",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"skipCi": true
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
.github/
|
||||
.local/
|
||||
bin/
|
||||
_dist/
|
||||
tools/
|
||||
proxy/
|
||||
site/
|
431
.drone.yml
431
.drone.yml
@ -1,431 +0,0 @@
|
||||
---
|
||||
###########################################
|
||||
##### k3d CLI/binary release pipeline #####
|
||||
###########################################
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: main
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
|
||||
- name: lint
|
||||
image: golang:1.17
|
||||
commands:
|
||||
- make ci-setup
|
||||
- make check-fmt lint
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
- tag
|
||||
|
||||
- name: test
|
||||
image: docker:20.10
|
||||
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.17
|
||||
environment:
|
||||
GIT_TAG: "${DRONE_TAG}"
|
||||
commands:
|
||||
- make ci-setup
|
||||
- make build-cross
|
||||
depends_on:
|
||||
- lint
|
||||
- test
|
||||
when:
|
||||
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:
|
||||
# include only pre-release tags
|
||||
- "refs/tags/*rc*"
|
||||
- "refs/tags/*beta*"
|
||||
- "refs/tags/*alpha*"
|
||||
- "refs/tags/*test*"
|
||||
- "refs/tags/*dev*"
|
||||
|
||||
- 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:
|
||||
# exclude pre-release tags
|
||||
- "refs/tags/*rc*"
|
||||
- "refs/tags/*beta*"
|
||||
- "refs/tags/*alpha*"
|
||||
- "refs/tags/*test*"
|
||||
- "refs/tags/*dev*"
|
||||
|
||||
services:
|
||||
# Starting the docker service to be used by dind
|
||||
- name: docker
|
||||
image: docker:20.10-dind
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run
|
||||
|
||||
volumes:
|
||||
- name: dockersock
|
||||
temp: {}
|
||||
|
||||
|
||||
---
|
||||
###########################
|
||||
###### Docker Images ######
|
||||
###########################
|
||||
#
|
||||
# +++ Docker Images +++
|
||||
# Tagged using the auto_tag feature of the docker plugin
|
||||
# See http://plugins.drone.io/drone-plugins/drone-docker/#autotag
|
||||
# > if event type is `tag`
|
||||
# > > 1.0.0 produces docker tags 1, 1.0, 1.0.0
|
||||
# > > 1.0.0-rc.1 produces docker tags 1.0.0-rc.1
|
||||
# > if event type is `push` and target branch == default branch (main)
|
||||
# > > tag `latest`
|
||||
|
||||
|
||||
################################
|
||||
##### Docker Images: amd64 #####
|
||||
################################
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux_amd64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
|
||||
- name: build_push_binary
|
||||
environment:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
dockerfile: Dockerfile
|
||||
target: binary-only
|
||||
context: .
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- GIT_TAG_OVERRIDE=${DRONE_TAG}
|
||||
|
||||
- name: build_push_dind
|
||||
image: plugins/docker
|
||||
environment:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
settings:
|
||||
repo: rancher/k3d
|
||||
auto_tag: true
|
||||
auto_tag_suffix: dind-linux-amd64
|
||||
dockerfile: Dockerfile
|
||||
target: dind
|
||||
context: .
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- GIT_TAG_OVERRIDE=${DRONE_TAG}
|
||||
- ARCH=amd64
|
||||
|
||||
- name: build_push_proxy
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-proxy
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
dockerfile: proxy/Dockerfile
|
||||
context: proxy/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
- name: build_push_tools
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-tools
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
dockerfile: tools/Dockerfile
|
||||
context: tools/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag # see note at the start of the "Docker Images" section: creates SemVer tagged images using the `auto_tag` option of the docker plugin
|
||||
- push # `auto_tag` option only creates the `latest` tag if target branch is default branch (i.e. `main`)
|
||||
|
||||
depends_on:
|
||||
- main
|
||||
|
||||
---
|
||||
|
||||
################################
|
||||
##### Docker Images: arm #####
|
||||
################################
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux_arm
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm
|
||||
|
||||
steps:
|
||||
|
||||
- name: build_push_proxy
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-proxy
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm
|
||||
dockerfile: proxy/Dockerfile
|
||||
context: proxy/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- ARCH=arm
|
||||
|
||||
- name: build_push_tools
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-tools
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm
|
||||
dockerfile: tools/Dockerfile
|
||||
context: tools/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag # see note at the start of the "Docker Images" section: creates SemVer tagged images using the `auto_tag` option of the docker plugin
|
||||
- push # `auto_tag` option only creates the `latest` tag if target branch is default branch (i.e. `main`)
|
||||
|
||||
depends_on:
|
||||
- main
|
||||
|
||||
---
|
||||
|
||||
################################
|
||||
##### Docker Images: arm64 #####
|
||||
################################
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux_arm64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
|
||||
- name: build_push_binary
|
||||
environment:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
dockerfile: Dockerfile
|
||||
target: binary-only
|
||||
context: .
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- GIT_TAG_OVERRIDE=${DRONE_TAG}
|
||||
|
||||
- name: build_push_dind
|
||||
image: plugins/docker
|
||||
environment:
|
||||
DOCKER_BUILDKIT: "1"
|
||||
settings:
|
||||
repo: rancher/k3d
|
||||
auto_tag: true
|
||||
auto_tag_suffix: dind-linux-arm64
|
||||
dockerfile: Dockerfile
|
||||
target: dind
|
||||
context: .
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- GIT_TAG_OVERRIDE=${DRONE_TAG}
|
||||
- ARCH=arm64
|
||||
|
||||
- name: build_push_proxy
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-proxy
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
dockerfile: proxy/Dockerfile
|
||||
context: proxy/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
build_args:
|
||||
- ARCH=arm64
|
||||
|
||||
- name: build_push_tools
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: rancher/k3d-tools
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
dockerfile: tools/Dockerfile
|
||||
context: tools/
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag # see note at the start of the "Docker Images" section: creates SemVer tagged images using the `auto_tag` option of the docker plugin
|
||||
- push # `auto_tag` option only creates the `latest` tag if target branch is default branch (i.e. `main`)
|
||||
|
||||
depends_on:
|
||||
- main
|
||||
|
||||
---
|
||||
|
||||
##############################
|
||||
###### Docker Manifests ######
|
||||
##############################
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: manifests
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: push_manifest_binary
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
spec: manifest.tmpl
|
||||
auto_tag: true
|
||||
ignore_missing: true # expected, as we dropped arm due to missing base image for that arch
|
||||
|
||||
- name: push_manifest_dind
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
spec: dind-manifest.tmpl
|
||||
auto_tag: true
|
||||
ignore_missing: true # expected, as we dropped arm due to missing base image for that arch
|
||||
|
||||
- name: push_manifest_proxy
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
spec: proxy/manifest.tmpl
|
||||
auto_tag: true
|
||||
ignore_missing: false
|
||||
|
||||
- name: push_manifest_tools
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
spec: tools/manifest.tmpl
|
||||
auto_tag: true
|
||||
ignore_missing: false
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag # see note at the start of the "Docker Images" section: creates SemVer tagged images using the `auto_tag` option of the manifest plugin
|
||||
- push # `auto_tag` option only creates the `latest` tag if target branch is default branch (i.e. `main`)
|
||||
|
||||
depends_on:
|
||||
- main
|
||||
- linux_amd64
|
||||
- linux_arm
|
||||
- linux_arm64
|
||||
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,38 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG] "
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## What did you do
|
||||
|
||||
- How was the cluster created?
|
||||
- `k3d cluster create -x A -y B`
|
||||
|
||||
- What did you do afterwards?
|
||||
- k3d commands?
|
||||
- docker commands?
|
||||
- OS operations (e.g. shutdown/reboot)?
|
||||
|
||||
## What did you expect to happen
|
||||
|
||||
Concise description of what you expected to happen after doing what you described above.
|
||||
|
||||
## Screenshots or terminal output
|
||||
|
||||
If applicable, add screenshots or terminal output (code block) to help explain your problem.
|
||||
|
||||
## Which OS & Architecture
|
||||
|
||||
- Linux, Windows, MacOS / amd64, x86, ...?
|
||||
|
||||
## Which version of `k3d`
|
||||
|
||||
- output of `k3d version`
|
||||
|
||||
## Which version of docker
|
||||
|
||||
- output of `docker version` and `docker info`
|
31
.github/ISSUE_TEMPLATE/feature_request.md
vendored
31
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FEATURE] "
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Is your feature request related to a problem or a Pull Request
|
||||
|
||||
Please link to the issue/PR here and explain how your request is related to it.
|
||||
|
||||
## Scope of your request
|
||||
|
||||
Do you need...
|
||||
|
||||
- a new noun (next to e.g. `cluster`, `node`, etc. used via `k3d <noun>`)?
|
||||
- a new verb (next to e.g. `cluster create`, `node start`, etc. used via `k3d <noun> <verb>`)
|
||||
- a new flag for a command (e.g. `k3d cluster create --<your-flag>`)?
|
||||
- which command?
|
||||
- different functionality for an existing command/flag
|
||||
- which command or flag?
|
||||
|
||||
## Describe the solution you'd like
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
## Describe alternatives you've considered
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
22
.github/ISSUE_TEMPLATE/question_help.md
vendored
22
.github/ISSUE_TEMPLATE/question_help.md
vendored
@ -1,22 +0,0 @@
|
||||
---
|
||||
name: Question or Help Wanted
|
||||
about: Get answers, receive Help.
|
||||
title: "[QUESTION/HELP] "
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
In general, please consider using GitHub Discussions for questions and general discussions: https://github.com/rancher/k3d/discussions .
|
||||
Especially please use Discussions for questions around use cases for k3d, etc.
|
||||
For everything else, fire away :)
|
||||
-->
|
||||
|
||||
## Question / Where do you need Help?
|
||||
|
||||
|
||||
## Scope of your Question
|
||||
|
||||
- Is your question related to a specific version of k3d (or k3s)?
|
||||
- Please paste the output of `k3d version` here
|
24
.github/pull_request_template.md
vendored
24
.github/pull_request_template.md
vendored
@ -1,24 +0,0 @@
|
||||
<!--
|
||||
Hi there, have an early THANK YOU for your contribution!
|
||||
k3d is a community-driven project, so we really highly appreciate any support.
|
||||
Please make sure, you've read our Code of Conduct and the Contributing Guidelines :)
|
||||
- Code of Conduct: https://github.com/rancher/k3d/blob/main/CODE_OF_CONDUCT.md
|
||||
- Contributing Guidelines: https://github.com/rancher/k3d/blob/main/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
# What
|
||||
|
||||
<!-- What does this PR do or change? -->
|
||||
|
||||
# Why
|
||||
|
||||
<!-- Link issues, discussions, etc. or just explain why you're creating this PR -->
|
||||
|
||||
# Implications
|
||||
|
||||
<!--
|
||||
Does this change existing behavior? If so, does it affect the CLI (cmd/) only or does it also/only change some internals of the Go module (pkg/)?
|
||||
Especially mention breaking changes here!
|
||||
-->
|
||||
|
||||
<!-- Get recognized using our all-contributors bot: https://github.com/rancher/k3d/blob/main/CONTRIBUTING.md#get-recognized -->
|
24
.github/workflows/aur-prerelease.yml
vendored
24
.github/workflows/aur-prerelease.yml
vendored
@ -1,24 +0,0 @@
|
||||
name: AUR Prerelease
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [prereleased]
|
||||
|
||||
jobs:
|
||||
aur-pre-release:
|
||||
runs-on: ubuntu-20.04
|
||||
container: archlinux:base-20210228.0.16308
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@v1
|
||||
- name: Publish Pre-Release to AUR
|
||||
run: |
|
||||
# AUR Packages are not allowed to use - in the package version. its used to combine pkgver and pkgrel
|
||||
export COMMIT_REF=${GITHUB_REF/-/_}
|
||||
./deploy-aur.sh
|
||||
env:
|
||||
PACKAGE_NAME: rancher-k3d-beta-bin
|
||||
COMMIT_USERNAME: GitHub Action
|
||||
COMMIT_EMAIL: iwilltry42+k3d@gmail.com
|
||||
COMMIT_MESSAGE: "[CI] Updated to $NEW_RELEASE"
|
||||
SSH_PRIVATE_KEY: ${{ secrets.AUR_PRIVATE_KEY }}
|
23
.github/workflows/aur-release.yml
vendored
23
.github/workflows/aur-release.yml
vendored
@ -1,23 +0,0 @@
|
||||
name: AUR Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
aur-release:
|
||||
runs-on: ubuntu-20.04
|
||||
container: archlinux:base-20210228.0.16308
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@v1
|
||||
- name: Publish Release to AUR
|
||||
run: |
|
||||
export COMMIT_REF=$GITHUB_REF
|
||||
./deploy-aur.sh
|
||||
env:
|
||||
PACKAGE_NAME: rancher-k3d-bin
|
||||
COMMIT_USERNAME: GitHub Action
|
||||
COMMIT_EMAIL: iwilltry42+k3d@gmail.com
|
||||
COMMIT_MESSAGE: "[CI] Updated to $NEW_RELEASE"
|
||||
SSH_PRIVATE_KEY: ${{ secrets.AUR_PRIVATE_KEY }}
|
46
.github/workflows/docs.yml
vendored
46
.github/workflows/docs.yml
vendored
@ -1,46 +0,0 @@
|
||||
name: k3d.io
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
# only run on tags for real releases and special docs releases
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-docs.[0-9]+'
|
||||
# tags-ignore:
|
||||
# - "*rc*"
|
||||
# - "*beta*"
|
||||
# - "*alpha*"
|
||||
# - "*test*"
|
||||
# - "*dev*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: python:3.9
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Requirements
|
||||
run: pip install -r docs/requirements.txt
|
||||
- name: Build with MkDocs (validation)
|
||||
run: |
|
||||
mkdocs build --verbose --clean --strict
|
||||
rm -r site/
|
||||
- name: Configure Git
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
id: git
|
||||
run: |
|
||||
git config --global user.name ghaction-k3d.io
|
||||
git config --global user.email ghaction@k3d.io
|
||||
echo ::set-output name=tag::${GITHUB_REF#refs/tags/}
|
||||
- name: Build & Deploy with Mike (versioned)
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
mike deploy --update-aliases --push --rebase ${{ steps.git.outputs.tag }} stable
|
||||
|
||||
|
28
.gitignore
vendored
28
.gitignore
vendored
@ -1,28 +0,0 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Output folders
|
||||
tools/bin/
|
||||
tools/_dist/
|
||||
bin/
|
||||
_dist/
|
||||
site/
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Editors
|
||||
.vscode/
|
||||
.local/
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# Pipenv
|
||||
Pipfile*
|
@ -1,3 +0,0 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
check-blank: false # to keep `_ = viper.BindPFlag(...)` from throwing errors
|
898
404.html
Normal file
898
404.html
Normal file
@ -0,0 +1,898 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
<meta name="description" content="Little helper to run Rancher Lab's k3s in Docker">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="icon" href="/v4.4.8-docs.0/static/img/favicons_black_blue/favicon.png">
|
||||
<meta name="generator" content="mkdocs-1.2.2, mkdocs-material-7.2.6">
|
||||
|
||||
|
||||
|
||||
<title>k3d</title>
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/v4.4.8-docs.0/assets/stylesheets/main.802231af.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/v4.4.8-docs.0/assets/stylesheets/palette.3f5d1f46.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
|
||||
<style>:root{--md-text-font-family:"Roboto";--md-code-font-family:"Roboto Mono"}</style>
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/v4.4.8-docs.0/static/css/asciinema-player.css">
|
||||
|
||||
<link rel="stylesheet" href="/v4.4.8-docs.0/static/css/extra.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="grey">
|
||||
|
||||
|
||||
<script>function __prefix(e){return new URL("/v4.4.8-docs.0",location).pathname+"."+e}function __get(e,t=localStorage){return JSON.parse(t.getItem(__prefix(e)))}</script>
|
||||
|
||||
<script>var palette=__get("__palette");if(null!==palette&&"object"==typeof palette.color)for(var key in palette.color)document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
<header class="md-header" data-md-component="header">
|
||||
<nav class="md-header__inner md-grid" aria-label="Header">
|
||||
<a href="/v4.4.8-docs.0/." title="k3d" class="md-header__button md-logo" aria-label="k3d" data-md-component="logo">
|
||||
|
||||
<img src="/v4.4.8-docs.0/static/img/k3d_logo_black_green.svg" alt="logo">
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
k3d
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="grey" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 10a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2m10-3a5 5 0 0 1 5 5 5 5 0 0 1-5 5H7a5 5 0 0 1-5-5 5 5 0 0 1 5-5h10M7 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3h10a3 3 0 0 0 3-3 3 3 0 0 0-3-3H7z"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="light-blue" data-md-color-accent="" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_2">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5m0 8a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3z"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
||||
</label>
|
||||
|
||||
<div class="md-search" data-md-component="search" role="dialog">
|
||||
<label class="md-search__overlay" for="__search"></label>
|
||||
<div class="md-search__inner" role="search">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
||||
<label class="md-search__icon md-icon" for="__search">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
||||
</label>
|
||||
<nav class="md-search__options" aria-label="Search">
|
||||
|
||||
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
||||
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Initializing search
|
||||
</div>
|
||||
<ol class="md-search-result__list"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-header__source">
|
||||
|
||||
<a href="https://github.com/rancher/k3d/" title="Go to repository" class="md-source" data-md-component="source">
|
||||
<div class="md-source__icon md-icon">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||||
</div>
|
||||
<div class="md-source__repository">
|
||||
rancher/k3d
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="md-container" data-md-component="container">
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
||||
<label class="md-nav__title" for="__drawer">
|
||||
<a href="/v4.4.8-docs.0/." title="k3d" class="md-nav__button md-logo" aria-label="k3d" data-md-component="logo">
|
||||
|
||||
<img src="/v4.4.8-docs.0/static/img/k3d_logo_black_green.svg" alt="logo">
|
||||
|
||||
</a>
|
||||
k3d
|
||||
</label>
|
||||
|
||||
<div class="md-nav__source">
|
||||
|
||||
<a href="https://github.com/rancher/k3d/" title="Go to repository" class="md-source" data-md-component="source">
|
||||
<div class="md-source__icon md-icon">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||||
</div>
|
||||
<div class="md-source__repository">
|
||||
rancher/k3d
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/." class="md-nav__link">
|
||||
Overview
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" >
|
||||
|
||||
<label class="md-nav__link" for="__nav_2">
|
||||
Usage
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav class="md-nav" aria-label="Usage" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_2">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Usage
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_1" type="checkbox" id="__nav_2_1" >
|
||||
|
||||
<label class="md-nav__link" for="__nav_2_1">
|
||||
Commands
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav class="md-nav" aria-label="Commands" data-md-level="2">
|
||||
<label class="md-nav__title" for="__nav_2_1">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Commands
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d/" class="md-nav__link">
|
||||
K3d
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster/" class="md-nav__link">
|
||||
K3d cluster
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster_create/" class="md-nav__link">
|
||||
K3d cluster create
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster_delete/" class="md-nav__link">
|
||||
K3d cluster delete
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster_list/" class="md-nav__link">
|
||||
K3d cluster list
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster_start/" class="md-nav__link">
|
||||
K3d cluster start
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_cluster_stop/" class="md-nav__link">
|
||||
K3d cluster stop
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_completion/" class="md-nav__link">
|
||||
K3d completion
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_config/" class="md-nav__link">
|
||||
K3d config
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_config_init/" class="md-nav__link">
|
||||
K3d config init
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_docgen/" class="md-nav__link">
|
||||
K3d docgen
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_image/" class="md-nav__link">
|
||||
K3d image
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_image_import/" class="md-nav__link">
|
||||
K3d image import
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_kubeconfig/" class="md-nav__link">
|
||||
K3d kubeconfig
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_kubeconfig_get/" class="md-nav__link">
|
||||
K3d kubeconfig get
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_kubeconfig_merge/" class="md-nav__link">
|
||||
K3d kubeconfig merge
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node/" class="md-nav__link">
|
||||
K3d node
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node_create/" class="md-nav__link">
|
||||
K3d node create
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node_delete/" class="md-nav__link">
|
||||
K3d node delete
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node_list/" class="md-nav__link">
|
||||
K3d node list
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node_start/" class="md-nav__link">
|
||||
K3d node start
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_node_stop/" class="md-nav__link">
|
||||
K3d node stop
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_registry/" class="md-nav__link">
|
||||
K3d registry
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_registry_create/" class="md-nav__link">
|
||||
K3d registry create
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_registry_delete/" class="md-nav__link">
|
||||
K3d registry delete
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_registry_list/" class="md-nav__link">
|
||||
K3d registry list
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/commands/k3d_version/" class="md-nav__link">
|
||||
K3d version
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/configfile/" class="md-nav__link">
|
||||
Config File
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/kubeconfig/" class="md-nav__link">
|
||||
Handling Kubeconfigs
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/multiserver/" class="md-nav__link">
|
||||
Creating multi-server clusters
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_5" type="checkbox" id="__nav_2_5" >
|
||||
|
||||
<label class="md-nav__link" for="__nav_2_5">
|
||||
Guides
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav class="md-nav" aria-label="Guides" data-md-level="2">
|
||||
<label class="md-nav__title" for="__nav_2_5">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Guides
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/guides/exposing_services/" class="md-nav__link">
|
||||
Exposing Services
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/guides/registries/" class="md-nav__link">
|
||||
Registries
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/guides/calico/" class="md-nav__link">
|
||||
Use Calico instead of Flannel
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/usage/guides/cuda/" class="md-nav__link">
|
||||
Running CUDA workloads
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" >
|
||||
|
||||
<label class="md-nav__link" for="__nav_3">
|
||||
Internals
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav class="md-nav" aria-label="Internals" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_3">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Internals
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/internals/defaults/" class="md-nav__link">
|
||||
Defaults
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/internals/project/" class="md-nav__link">
|
||||
Project Overview
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/internals/networking/" class="md-nav__link">
|
||||
Networking
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
|
||||
|
||||
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" >
|
||||
|
||||
<label class="md-nav__link" for="__nav_4">
|
||||
FAQ
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
</label>
|
||||
<nav class="md-nav" aria-label="FAQ" data-md-level="1">
|
||||
<label class="md-nav__title" for="__nav_4">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
FAQ
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/v4.4.8-docs.0/faq/faq/" class="md-nav__link">
|
||||
FAQ / Nice to know
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
<h1>404 - Not found</h1>
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" class="md-top md-icon" data-md-component="top" data-md-state="hidden">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"/></svg>
|
||||
Back to top
|
||||
</a>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-footer-copyright">
|
||||
|
||||
<div class="md-footer-copyright__highlight">
|
||||
Copyright © 2020-2021 k3d Authors
|
||||
</div>
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
<script id="__config" type="application/json">{"base": "/v4.4.8-docs.0", "features": ["navigation.top", "search.suggest", "search.highlight"], "translations": {"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing", "select.version.title": "Select version"}, "search": "/v4.4.8-docs.0/assets/javascripts/workers/search.409db549.min.js", "version": {"provider": "mike"}}</script>
|
||||
|
||||
|
||||
<script src="/v4.4.8-docs.0/assets/javascripts/bundle.756773cc.min.js"></script>
|
||||
|
||||
<script src="/v4.4.8-docs.0/static/js/asciinema-player.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
470
CHANGELOG.md
470
CHANGELOG.md
@ -1,470 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## v5.0.3
|
||||
|
||||
### Enhancements & Fixes
|
||||
|
||||
- simplified way of getting a Docker API Client that works with Docker Contexts and `DOCKER_*` environment variable configuration (#829, @dragonflylee)
|
||||
- fix: didn't honor `DOCKER_TLS` environment variables before
|
||||
|
||||
## v5.0.2
|
||||
|
||||
### Enhancements
|
||||
|
||||
- CoreDNS Configmap is now edited in the auto-deploy manifest on disk instead of relying on `kubectl patch` command (#814)
|
||||
- refactor: add cmd subcommands in a single function call (#819, @moeryomenko)
|
||||
- handle ready-log-messages by type and intent & check them in single log streams instead of checking whole chunks every time (#818)
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix: config file check failing with env var expansion because unexpanded input file was checked
|
||||
|
||||
### Misc
|
||||
|
||||
- cleanup: ensure that connections/streams are closed once unused (#818)
|
||||
- cleanup: split type definitions across multiple files to increase readability (#818)
|
||||
- docs: clarify `node create` help text about cluster reference (#808, @losinggeneration)
|
||||
- refactor: move from io/ioutil (deprecated) to io and os packages (#827, @Juneezee)
|
||||
|
||||
## v5.0.1
|
||||
|
||||
### Enhancement
|
||||
|
||||
- add `HostFromClusterNetwork` field to `LocalRegistryHosting` configmap as per KEP-1755 (#754)
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix: nilpointer exception on failed exec process with no returned logreader
|
||||
- make post-create cluster preparation (DNS stuff mostly) more resilient (#780)
|
||||
- fix v1alpha2 -> v1alpha3 config migration (and other related issues) (#799)
|
||||
|
||||
### Misc
|
||||
|
||||
- docs: fix typo (#784)
|
||||
- docs: fix usage of legacy `--k3s-agent/server-arg` flag
|
||||
|
||||
## v5.0.0
|
||||
|
||||
This release contains a whole lot of new features, breaking changes as well as smaller fixes and improvements.
|
||||
The changelog shown here is likely not complete but gives a broad overview over the changes.
|
||||
For more details, please check the v5 milestone (<https://github.com/rancher/k3d/milestone/27>) or even the commit history.
|
||||
The docs have been updated, so you should also find the information you need there, with more to come!
|
||||
|
||||
The demo repository has also been updated to work with k3d v5: <https://github.com/iwilltry42/k3d-demo>.
|
||||
|
||||
**Info**: <https://k3d.io> is now versioned, so you can checkout different versions of the documentation by using the dropdown menu in the page title bar!
|
||||
|
||||
**Feedback welcome!**
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- new syntax for nodefilters
|
||||
- dropped the usage of square brackets `[]` for indexing, as it caused problems with some shells trying to interpret them
|
||||
- new syntax: `@identifier[:index][:opt]` (see <https://github.com/rancher/k3d/discussions/652>)
|
||||
- example for a port-mapping: `--port 8080:80@server:0:proxy`
|
||||
- identifier = `server`, index = `0`, opt = `proxy`
|
||||
- `opt` is an extra optional argument used for different purposes depending on the flag
|
||||
- currently, only the `--port` flag has `opt`s, namely `proxy` and `direct` (see other breaking change)
|
||||
- port-mapping now go via the loadbalancer (serverlb) by default
|
||||
- the `--port` flag has the `proxy` opt (see new nodefilter syntax above) set by default
|
||||
- to leverage the old behavior of direct port-mappings, use the `direct` opt on the port flag
|
||||
- the nodefilter `loadbalancer` will now do the same as `servers:*;agents:*` (proxied via the loadbalancer)
|
||||
- flag `--registries-create` transformed from bool flag to string flag: let's you define the name and port-binding of the newly created registry, e.g. `--registry-create myregistry.localhost:5001`
|
||||
|
||||
### Fixes
|
||||
|
||||
- cleaned up and properly sorted the sanitization of existing resources used to create new nodes (#638)
|
||||
|
||||
### Features & Enhancements
|
||||
|
||||
- new command: `k3d node edit` to edit existing nodes (#615)
|
||||
- currently only allows `k3d node edit NODE --port-add HOSTPORT:CONTAINERPORT` for the serverlb/loadbalancer to add new ports
|
||||
- pkg: new `NodeEdit` function
|
||||
- new (hidden) command: `k3d debug` with some options for debugging k3d resources (#638)
|
||||
- e.g. `k3d debug loadbalancer get-config` to get the current loadbalancer configuration
|
||||
- loadbalancer / k3d-proxy (#638)
|
||||
- updated fork of `confd` to make usage of the file backend including a file watcher for auto-reloads
|
||||
- this also checks the config before applying it, so the lb doesn't crash on a faulty config
|
||||
- updating the loadbalancer writes the new config file and also checks if everything's going fine afterwards
|
||||
- some settings of the loadbalancer can now be configured using `--lb-config-override`, see docs at <https://k3d.io/v5.0.0/design/defaults/#k3d-loadbalancer>
|
||||
- helper images can now be set explicitly via environment variables: `K3D_IMAGE_LOADBALANCER` & `K3D_IMAGE_TOOLS` (#638)
|
||||
- concurrently add new nodes to an existing cluster (remove some dumb code) (#640)
|
||||
- `--wait` is now the default for `k3d node create`
|
||||
- normalized flag usage for k3s and runtime (#598, @ejose19)
|
||||
- rename `k3d cluster create --label` to `k3d cluster create --runtime-label` (as it's labelling the node on runtime level, e.g. docker)
|
||||
- config option moved to `options.runtime.labels`
|
||||
- add `k3d cluster create --k3s-node-label` to add Kubernetes node labels via k3s flag (#584, @developer-guy, @ejose, @dentrax)
|
||||
- new config option `options.k3s.nodeLabels`
|
||||
- the same for `k3d node create`
|
||||
- improved config file handling (#605)
|
||||
- new version `v1alpha3`
|
||||
- warning when using outdated version
|
||||
- validation dynamically based on provided config apiVersion
|
||||
- new default for `k3d config init`
|
||||
- new command `k3d config migrate INPUT [OUTPUT]` to migrate config files between versions
|
||||
- currently supported migration `v1alpha2` -> `v1alpha3`
|
||||
- pkg: new `Config` interface type to support new generic `FromViper` config file parsing
|
||||
- changed flags `--k3s-server-arg` & `--k3s-agent-arg` into `--k3s-arg` with nodefilter support (#605)
|
||||
- new config path `options.k3s.extraArgs`
|
||||
- config file: environment variables (`$VAR`, `${VAR}` will be expanded unconditionally) (#643)
|
||||
- docker context support (#601, @developer-guy & #674)
|
||||
- Feature flag using the environment variable `K3D_FIX_DNS` and setting it to a true value (e.g. `export K3D_FIX_DNS=1`) to forward DNS queries to your local machine, e.g. to use your local company DNS
|
||||
|
||||
### Misc
|
||||
|
||||
- tests/e2e: timeouts everywhere to avoid killing DroneCI (#638)
|
||||
- logs: really final output when creating/deleting nodes (so far, we were not outputting a final success message and the process was still doing stuff) (#640)
|
||||
- tests/e2e: add tests for v1alpha2 to v1alpha3 migration
|
||||
- docs: use v1alpha3 config version
|
||||
- docs: update general appearance and cleanup
|
||||
|
||||
## v4.4.8
|
||||
|
||||
## Enhancements
|
||||
|
||||
- Improved DroneCI Pipeline for Multiarch Images and SemVer Tags (#712)
|
||||
- **Important**: New images will not have the `v` prefix in the tag anymore!
|
||||
- but now real releases will use the "hierarchical" SemVer tags, so you could e.g. subscribe to rancher/k3d-proxy:4 to get v4.x.x images for the proxy container
|
||||
|
||||
## Fixes
|
||||
|
||||
- clusterCreate: do not override hostIP if hostPort is missing (#693, @lukaszo)
|
||||
- imageImport: import all listed images, not only the first one (#701, @mszostok)
|
||||
- clusterCreate: when memory constraints are set, only pull the image used for checking the edac folder, if it's not present on the machine
|
||||
- fix: update k3d-tools dependencies and use API Version Negotiation, so it still works with older versions of the Docker Engine (#679)
|
||||
|
||||
### Misc
|
||||
|
||||
- install script: add darwin/arm64 support (#676, @colelawrence)
|
||||
- docs: fix go install command (#677, @Rots)
|
||||
- docs: add project overview (<https://k3d.io/internals/project/>) (#680)
|
||||
|
||||
## v4.4.7
|
||||
|
||||
### Features / Enhancements
|
||||
|
||||
- new flag: `k3d image import --keep-tools` to not delete the tools node container after importing the image(s) (#672)
|
||||
- improve image name handling when importing images (#653, @cimnine)
|
||||
- normalize image names internally, e.g. strip prefixes that docker adds, but that break the process
|
||||
- see <https://k3d.io/usage/commands/k3d_image_import/> for more info
|
||||
|
||||
### Fixes
|
||||
|
||||
- Use default gateway, when bridge network doesn't have it (#666, @kuritka)
|
||||
- Start an existing, but not running tools node to re-use it when importing an image (#672)
|
||||
|
||||
### Misc
|
||||
|
||||
- deps: switching back to upstream viper including the StringArray fix
|
||||
- docs: reference to "nolar/setup-k3d-k3s" step for GitHub Actions (#668, @nolar)
|
||||
- docs: updated and simplified CUDA guide (#662, @vainkop) (#669)
|
||||
|
||||
## v4.4.6
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix an issue where the cluster creation would stall waiting for the `starting worker processes` log message from the loadbalancer/serverlb
|
||||
- this was likely caused by a rounding issue when asking docker to get the container logs starting at a specific timestamp
|
||||
- we now drop subsecond precision for this to avoid the rounding issue, which was confirmed to work
|
||||
- see issues #592 & #621
|
||||
|
||||
### Misc
|
||||
|
||||
- to debug the issue mentioned above, we introduced a new environment variable `K3D_LOG_NODE_WAIT_LOGS`, which can be set to a list of node roles (e.g. `K3D_LOG_NODE_WAIT_LOGS=loadbalancer,agent`) to output the container logs that k3d inspects
|
||||
|
||||
## v4.4.5
|
||||
|
||||
### Fixes
|
||||
|
||||
- overall: use the getDockerClient helper function everywhere to e.g. support docker via ssh everywhere
|
||||
- nodeCreate: do not copy meminfo/edac volume mounts from existing nodes, to avoid conflicts with generated mounts
|
||||
- kubeconfig: fix file handling on windows (#626 + #628, @dragonflylee)
|
||||
|
||||
### Misc
|
||||
|
||||
- docs: add [FAQ entry](https://k3d.io/faq/faq/#nodes-fail-to-start-or-get-stuck-in-notready-state-with-log-nf_conntrack_max-permission-denied) on nf_conntrack_max: permission denied issue from kube-proxy (#607)
|
||||
- docs: cleanup, fix formatting, etc.
|
||||
- license: update to include 2021 in time range
|
||||
- docs: link to AutoK3s (#614, @JacieChao)
|
||||
- tests/e2e: update the list of tested k3s versions
|
||||
|
||||
## v4.4.4
|
||||
|
||||
### Enhancements
|
||||
|
||||
- nodes created via `k3d node create` now inherit the registry config from existing nodes (if there is any) (#597)
|
||||
- the cgroupv2 hotfix (custom entrypoint script) is now enabled by default (#603)
|
||||
- disable by setting the environment variable `K3D_FIX_CGROUPV2=false`
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix using networks without IPAM config (e.g. `host`)
|
||||
|
||||
### Misc
|
||||
|
||||
- docs: edit links on k3d.io now point to the correct branch (`main`)
|
||||
- docs: new FAQ entry on spurious PID entries when using shared mounts (#609, @leelavg)
|
||||
|
||||
## v4.4.3
|
||||
|
||||
### Highlights
|
||||
|
||||
- cgroupv2 support: to properly work on cgroupv2 systems, k3s has to move all the processes from the root cgroup to a new /init cgroup and enable subtree_control
|
||||
- this is going to be included in the k3s agent code directly (<https://github.com/k3s-io/k3s/pull/3242>)
|
||||
- for now we're overriding the container entrypoint with a script that does this (#579, compare <https://github.com/k3s-io/k3s/pull/3237>)
|
||||
- thanks a lot for all the input and support @AkihiroSuda
|
||||
- **Usage**: set the environment variable `K3D_FIX_CGROUPV2` to a `true` value before/when creating a cluster with k3d
|
||||
- e.g. `export K3D_FIX_CGROUPV2=1`
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix: docker volume not mountable due to validation failure
|
||||
- was not able to mount named volume on windows as we're checking for `:` meant for drive-letters and k3d separators
|
||||
|
||||
### Misc
|
||||
|
||||
- fix create command's flags typo (#568, @Jason-ZW)
|
||||
|
||||
## v4.4.2
|
||||
|
||||
### Fixes
|
||||
|
||||
- k3d-proxy: rename udp upstreams to avoid collisions/duplicates (#564)
|
||||
|
||||
### Features
|
||||
|
||||
- add *hidden* command `k3d runtime-info` used for debugging (#553)
|
||||
- this comes with some additions on package/runtime level
|
||||
- add *experimental* `--subnet` flag to get some k3d IPAM to ensure that server nodes keep static IPs across restarts (#560)
|
||||
|
||||
### Misc
|
||||
|
||||
- docs: fix typo (#556, @gcalmettes)
|
||||
- docs: fix typo (#561, @alechartung)
|
||||
- ci/drone: pre-release on `-dev.X` tags
|
||||
- ci/drone: always build no matter the branch name (just not release)
|
||||
- docs: add automatic command tree generation via cobra (#562)
|
||||
- makefile: use `go env gopath` as install target for tools (as per #445)
|
||||
- JSONSchema: add some examples and defaults (now also available via <https://raw.githubusercontent.com/rancher/k3d/main/pkg/config/v1alpha2/schema.json> in your IDE)
|
||||
|
||||
## v4.4.1
|
||||
|
||||
### Fixes
|
||||
|
||||
- use viper fork that contains a fix to make cobra's `StringArray` flags work properly
|
||||
- this fixes the issue, that flag values containing commas got split (because we had to use `StringSlice` type flags)
|
||||
- this is to be changed back to upstream viper as soon as <https://github.com/spf13/viper/pull/398> (or a similar fix) got merged
|
||||
|
||||
## v4.4.0
|
||||
|
||||
### Features / Enhancements
|
||||
|
||||
- Support for Memory Limits using e.g. `--servers-memory 1g` or `--agents-memory 1.5g` (#494, @konradmalik)
|
||||
- enabled by providing fake `meminfo` files
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix absolute paths in volume mounts on Windows (#510, @markrexwinkel)
|
||||
|
||||
### Documentation
|
||||
|
||||
- clarify registry names in docs and help text
|
||||
- add usage section about config file (#534)
|
||||
- add FAQ entry on certificate error when running behind corporate proxy
|
||||
- add MacPorts install instructions (#539, @herbygillot)
|
||||
- Heal Shruggie: Replace amputated arm (#540, @claycooper)
|
||||
|
||||
## v4.3.0
|
||||
|
||||
### Features / Enhancements
|
||||
|
||||
- Use Go 1.16
|
||||
- update dependencies, including kubernetes, docker, containerd and more
|
||||
- add `darwin/arm64` (Apple Silicon, M1) build target (#530)
|
||||
- use the new `//go:embed` feature to directly embed the jsonschema in the binary (#529)
|
||||
- Add a status column to `k3d registry list` output (#496, @ebr)
|
||||
- Allow non-prefixed (i.e. without `k3d-` prefix) user input when fetching resources (e.g. `k3d node get mycluster-server-0` would return successfully)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Allow absolute paths for volumes on Windows (#510, @markrexwinkel)
|
||||
- fix nil-pointer exception in case of non-existent IPAM network config
|
||||
- Properly handle combinations of host/hostIP in kubeAPI settings reflected in the kubeconfig (#500, @fabricev)
|
||||
|
||||
### Misc
|
||||
|
||||
- docs: fix typo in stop command help text (#513, @searsaw)
|
||||
- ci/ghaction: AUR (pre-)release now on Ubuntu 20.04 and latest archlinux image
|
||||
- REMOVE incomplete and unused `containerd` runtime from codebase, as it was causing issues to build for windows and hasn't made any progress in quite some time now
|
||||
|
||||
## v4.2.0
|
||||
|
||||
### Features / Enhancements
|
||||
|
||||
- add processing step for cluster config, to configure it e.g. for hostnetwork mode (#477, @konradmalik)
|
||||
- allow proxying UDP ports via the load balancer (#488, @k0da)
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix usage of `DOCKER_HOST` env var for Kubeconfig server ref (trim port)
|
||||
- fix error when trying to attach the same node (e.g. registry) to the same network twice (#486, @kuritka)
|
||||
- fix Kube-API settings in configg file got overwritten (#490, @dtomasi)
|
||||
|
||||
### Misc
|
||||
|
||||
- add `k3d.version` label to created resources
|
||||
- add Pull-Request template
|
||||
- docs: add hint on minimal requirements for multi-server clusters (#481, @Filius-Patris)
|
||||
|
||||
## v4.1.1
|
||||
|
||||
### Fixes
|
||||
|
||||
- fix: `--k3s-server-arg` and `--k3s-agent-arg` didn't work (Viper StringArray incompatibility) (#482)
|
||||
|
||||
## v4.1.0
|
||||
|
||||
### Highlights
|
||||
|
||||
#### :scroll: Configuration Enhancements
|
||||
|
||||
- :snake: use [viper](https://github.com/spf13/viper) for configuration management
|
||||
- takes over the job of properly fetching and merging config options from
|
||||
- CLI arguments/flags
|
||||
- environment variables
|
||||
- config file
|
||||
- this also fixes some issues with using the config file (like cobra defaults overriding config file values)
|
||||
- :heavy_check_mark: add JSON-Schema validation for the `Simple` config file schema
|
||||
- :new: config version `k3d.io/v1alpha2` (some naming changes)
|
||||
- `exposeAPI` -> `kubeAPI`
|
||||
- `options.k3d.noRollback` -> `options.k3d.disableRollback`
|
||||
- `options.k3d.prepDisableHostIPInjection` -> `options.k3d.disableHostIPInjection`
|
||||
|
||||
#### :computer: Docker over SSH
|
||||
|
||||
- Support Docker over SSH (#324, @ekristen & @inercia)
|
||||
|
||||
### Features & Enhancements
|
||||
|
||||
- add root flag `--timestamps` to enable timestamped logs
|
||||
- improved multi-server cluster support (#467)
|
||||
- log a warning, if one tries to create a cluster with only 2 nodes (no majority possible, no fault tolerance)
|
||||
- revamped cluster start procedure: init-node, sorted servers, agents, helpers
|
||||
- different log messages per role and start-place (that we wait for to consider a node to be ready)
|
||||
- module: `NodeStartOpts` now accept a `ReadyLogMessage` and `NodeState` now takes a `Started` timestamp string
|
||||
|
||||
### Fixes
|
||||
|
||||
- do not ignore `--no-hostip` flag and don't inject hostip if `--network=host` (#471, @konradmalik)
|
||||
- fix: `--no-lb` ignored
|
||||
- fix: print error cause when serverlb fails to start
|
||||
|
||||
### Misc
|
||||
|
||||
- tests/e2e: add config override test
|
||||
- tests/e2e: add multi server start-stop cycle test
|
||||
- tests/e2e: improved logs with stage and test details.
|
||||
- builds&tests: use Docker 20.10 and BuildKit everywhere
|
||||
- :memo: docs: add <https://github.com/AbsaOSS/k3d-action> (GitHub Action) as a related project (#476, @kuritka)
|
||||
|
||||
### Tested with
|
||||
|
||||
- E2E Tests ran with k3s versions
|
||||
- v1.17.17-k3s1 (see Known Issues below)
|
||||
- v1.18.15-k3s1 (see Known Issues below)
|
||||
- v1.19.7-k3s1
|
||||
- v1.20.2-k3s1
|
||||
|
||||
### Known Issues
|
||||
|
||||
- automatic multi-server cluster restarts tend to fail with k3s versions v1.17.x & v1.18.x and probably earlier versions (using dqlite)
|
||||
- Using Viper brings us lots of nice features, but also one problem:
|
||||
- We had to switch StringArray flags to StringSlice flags, which
|
||||
- allow to use multiple flag values comma-separated in a single flag, but also
|
||||
- split flag values that contain a comma into separate parts (and we cannot handle issues that arise due to this)
|
||||
- so if you rely on commas in your flag values (e.g. for `--env X=a,b,c`), please consider filing an issue or supporting <https://github.com/spf13/viper/issues/246> and <https://github.com/spf13/viper/pull/398>
|
||||
- `--env X=a,b,c` would be treated the same as `--env X=a`, `--env b`, `--env c`
|
||||
|
||||
## v4.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
#### Module
|
||||
|
||||
**If you're using k3d as a Go module, please have a look into the code to see all the changes!**
|
||||
|
||||
- We're open for chats via Slack or GitHub discussions
|
||||
|
||||
- Module is now on `github.com/rancher/k3d/v4` due to lots of breaking changes
|
||||
- `pkg/cluster` is now `pkg/client`
|
||||
- `ClusterCreate` and `NodeCreate` don't start the entities (containers) anymore
|
||||
- `ClusterRun` and `NodeRun` orchestrate the new Create and Start functionality
|
||||
- `NodeDelete`/`ClusterDelete` now take an additional `NodeDeleteOpts`/`ClusterDeleteOpts` struct to toggle specific steps
|
||||
- NodeSpec now features a list of networks (required for registries)
|
||||
- New config flow: CLIConfig (SimpleConfig) -> ClusterConfig -> Cluster + Opts
|
||||
|
||||
#### CLI
|
||||
|
||||
- Some flags changed to also use `noun-action` syntax
|
||||
- e.g. `--switch-context --update-default-kubeconfig` -> `--kubeconfig-switch-context --kubeconfig-update-default`
|
||||
- this eases grouping and visibility
|
||||
|
||||
### Changes
|
||||
|
||||
#### Features
|
||||
|
||||
- **Registry Support**
|
||||
- k3d-managed registry like we had it in k3d v1.x
|
||||
- Option 1: default settings, paired with cluster creation
|
||||
- `k3d cluster create --registry-create` -> New registry for that cluster
|
||||
- `k3d cluster create --registry-use` -> Re-use existing registry
|
||||
- Option 2: customized, managed stand-alone
|
||||
- `k3d registry [create/start/stop/delete]`
|
||||
- Check the documentation, help text and tutorials for more details
|
||||
- Communicate managed registry using the LocalRegistryHostingV1 spec from [KEP-1755](https://github.com/kubernetes/enhancements/blob/0d69f7cea6fbe73a7d70fab569c6898f5ccb7be0/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry/README.md)
|
||||
- interesting especially for tools that reload images, like Tilt or Skaffold
|
||||
|
||||
- **Config File Support**
|
||||
- Put all your CLI-Arguments/Flags into a more readable config file and re-use it everywhere (keep it in your repo)
|
||||
- Note: this is not always a 1:1 matching in naming/syntax/semantics
|
||||
- `k3d cluster create --config myconfig.yaml`
|
||||
|
||||
```yaml
|
||||
apiVersion: k3d.io/v1alpha1
|
||||
kind: Simple
|
||||
name: mycluster
|
||||
servers: 3
|
||||
agents: 2
|
||||
ports:
|
||||
- port: 8080:80
|
||||
nodeFilters:
|
||||
- loadbalancer
|
||||
```
|
||||
|
||||
- Check out our test cases in [pkg/config/test_assets/](./pkg/config/test_assets/) for more config file examples
|
||||
- **Note**: The config file format (& feature) might still be a little rough around the edges and it's prone to change quickly until we hit a stable release of the config
|
||||
|
||||
- [WIP] Support for Lifecycle Hooks
|
||||
- Run any executable at specific stages during the cluster and node lifecycles
|
||||
- e.g. we modify the `registries.yaml` in the `preStart` stage of nodes
|
||||
- Guides will follow
|
||||
|
||||
- Print container creation time (#431, @inercia)
|
||||
- add output formats for `cluster ls` and `node ls` (#439, @inercia)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- import image: avoid nil pointer exception in specific cases
|
||||
- cluster delete: properly handle node and network (#437)
|
||||
- --port: fix bnil-pointer exception when exposing port on non-existent loadbalancer
|
||||
- completion/zsh: source completion file
|
||||
|
||||
#### Misc
|
||||
|
||||
- Now building with Go 1.15
|
||||
- same for the k3d-tools code
|
||||
- updated dependencies (including Docker v20.10)
|
||||
- tests/e2e: add `E2E_INCLUDE` and rename `E2E_SKIP` to `E2E_EXCLUDE`
|
||||
- tests/e2e: allow overriding the Helper Image Tag via `E2E_HELPER_IMAGE_TAG`
|
||||
- docs: spell checking (#434, @jsoref)
|
||||
- docs: add Chocolatey install option (#443, @erwinkersten)
|
@ -1,128 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
iwilltry42@gmail.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
<https://www.contributor-covenant.org/faq>. Translations are available at
|
||||
<https://www.contributor-covenant.org/translations>.
|
@ -1,27 +0,0 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Hi there! Welcome to the k3d and Rancher Community!
|
||||
We welcome everyone who likes to use and improve our software.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Before starting to work with and on k3d, please read and understand our [**Code of Conduct**](./CODE_OF_CONDUCT.md).
|
||||
|
||||
Get an Overview of the k3d project in the documentation: [k3d.io/internals/project](https://k3d.io/internals/project)
|
||||
|
||||
Before opening an issue or a Pull-Request, please use GitHub's search function to check whether something similar is already in process and hook in there instead.
|
||||
|
||||
## Get Recognized
|
||||
|
||||
We want to foster a collaborative environment, where every contribution is welcomed and recognized.
|
||||
|
||||
If you want to show up in our Contributors section, please make use of the @all-contributors bot integrated with this repository.
|
||||
|
||||
Here's a full guide on using the bot: <https://allcontributors.org/docs/en/bot/usage>.
|
||||
The simplest way to use it is (in a comment on an issue or a pull-request): `@all-contributors please add <username> for <contributions>`, where `<contributions>` is a [list of contributions](https://allcontributors.org/docs/en/emoji-key).
|
||||
|
||||
Here's an [example comment on a PR](https://github.com/rancher/k3d/pull/368#issuecomment-704320376) to tell the bot to add @zeerorg (who had the initial idea for k3s in docker) to the list of contributors for the ideas and code he added:
|
||||
|
||||
> @all-contributors please add @zeerorg for ideas and code
|
||||
|
||||
The bot will open a PR to add the user to the list and posts the link as a follow-up comment on the issue/PR.
|
41
Dockerfile
41
Dockerfile
@ -1,41 +0,0 @@
|
||||
############################################################
|
||||
# builder #
|
||||
# -> golang image used solely for building the k3d binary #
|
||||
# -> built executable can then be copied into other stages #
|
||||
############################################################
|
||||
FROM golang:1.17 as builder
|
||||
ARG GIT_TAG_OVERRIDE
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN make build -e GIT_TAG_OVERRIDE=${GIT_TAG_OVERRIDE} && bin/k3d version
|
||||
|
||||
#######################################################
|
||||
# dind #
|
||||
# -> k3d + some tools in a docker-in-docker container #
|
||||
# -> used e.g. in our CI pipelines for testing #
|
||||
#######################################################
|
||||
FROM docker:20.10-dind as dind
|
||||
ARG OS=linux
|
||||
ARG ARCH=amd64
|
||||
|
||||
# install some basic packages needed for testing, etc.
|
||||
RUN echo "building for ${OS}/${ARCH}" && \
|
||||
apk update && \
|
||||
apk add bash curl sudo jq git make netcat-openbsd
|
||||
|
||||
# install kubectl to interact with the k3d cluster
|
||||
RUN curl -L https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/${OS}/${ARCH}/kubectl -o /usr/local/bin/kubectl && \
|
||||
chmod +x /usr/local/bin/kubectl
|
||||
|
||||
# install yq (yaml processor) from source, as the busybox yq had some issues
|
||||
RUN curl -L https://github.com/mikefarah/yq/releases/download/v4.9.6/yq_${OS}_${ARCH} -o /usr/bin/yq &&\
|
||||
chmod +x /usr/bin/yq
|
||||
COPY --from=builder /app/bin/k3d /bin/k3d
|
||||
|
||||
#########################################
|
||||
# binary-only #
|
||||
# -> only the k3d binary.. nothing else #
|
||||
#########################################
|
||||
FROM scratch as binary-only
|
||||
COPY --from=builder /app/bin/k3d /bin/k3d
|
||||
ENTRYPOINT ["/bin/k3d"]
|
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2019-2021 Thorsten Klein <iwilltry42@gmail.com>
|
||||
|
||||
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.
|
225
Makefile
225
Makefile
@ -1,225 +0,0 @@
|
||||
###################################
|
||||
# #
|
||||
# CONFIGURATION #
|
||||
# #
|
||||
###################################
|
||||
|
||||
########## Shell/Terminal Settings ##########
|
||||
SHELL := /bin/bash
|
||||
|
||||
# determine if make is being executed from interactive terminal
|
||||
INTERACTIVE:=$(shell [ -t 0 ] && echo 1)
|
||||
|
||||
# Use Go Modules for everything
|
||||
export GO111MODULE=on
|
||||
|
||||
########## Tags ##########
|
||||
|
||||
# get git tag
|
||||
ifneq ($(GIT_TAG_OVERRIDE),)
|
||||
$(info GIT_TAG set from env override!)
|
||||
GIT_TAG := $(GIT_TAG_OVERRIDE)
|
||||
endif
|
||||
|
||||
GIT_TAG ?= $(shell git describe --tags)
|
||||
ifeq ($(GIT_TAG),)
|
||||
GIT_TAG := $(shell git describe --always)
|
||||
endif
|
||||
|
||||
# Docker image tag derived from Git tag (with prefix "v" stripped off)
|
||||
K3D_IMAGE_TAG := $(GIT_TAG:v%=%)
|
||||
|
||||
# get latest k3s version: grep the tag and replace + with - (difference between git and dockerhub tags)
|
||||
K3S_TAG := $(shell curl --silent "https://update.k3s.io/v1-release/channels/stable" | egrep -o '/v[^ ]+"' | sed -E 's/\/|\"//g' | sed -E 's/\+/\-/')
|
||||
|
||||
ifeq ($(K3S_TAG),)
|
||||
$(warning K3S_TAG undefined: couldn't get latest k3s image tag!)
|
||||
$(warning Output of curl: $(shell curl --silent "https://update.k3s.io/v1-release/channels/stable"))
|
||||
$(error exiting)
|
||||
endif
|
||||
|
||||
########## Source Options ##########
|
||||
# DIRS defines a single level directly, we only look at *.go in this directory.
|
||||
# REC_DIRS defines a source code tree. All go files are analyzed recursively.
|
||||
DIRS := .
|
||||
REC_DIRS := cmd
|
||||
|
||||
########## Test Settings ##########
|
||||
E2E_LOG_LEVEL ?= WARN
|
||||
E2E_INCLUDE ?=
|
||||
E2E_EXCLUDE ?=
|
||||
E2E_EXTRA ?=
|
||||
E2E_RUNNER_START_TIMEOUT ?= 10
|
||||
E2E_HELPER_IMAGE_TAG ?=
|
||||
|
||||
########## Go Build Options ##########
|
||||
# Build targets
|
||||
TARGETS ?= darwin/amd64 darwin/arm64 linux/amd64 linux/386 linux/arm linux/arm64 windows/amd64
|
||||
TARGET_OBJS ?= darwin-amd64.tar.gz darwin-amd64.tar.gz.sha256 darwin-arm64.tar.gz darwin-arm64.tar.gz.sha256 linux-amd64.tar.gz linux-amd64.tar.gz.sha256 linux-386.tar.gz linux-386.tar.gz.sha256 linux-arm.tar.gz linux-arm.tar.gz.sha256 linux-arm64.tar.gz linux-arm64.tar.gz.sha256 windows-amd64.zip windows-amd64.zip.sha256
|
||||
K3D_HELPER_VERSION ?=
|
||||
|
||||
# Go options
|
||||
GO ?= go
|
||||
GOENVPATH := $(shell go env GOPATH)
|
||||
PKG := $(shell go mod vendor)
|
||||
TAGS :=
|
||||
TESTS := ./...
|
||||
TESTFLAGS :=
|
||||
LDFLAGS := -w -s -X github.com/rancher/k3d/v5/version.Version=${GIT_TAG} -X github.com/rancher/k3d/v5/version.K3sVersion=${K3S_TAG}
|
||||
GCFLAGS :=
|
||||
GOFLAGS :=
|
||||
BINDIR := $(CURDIR)/bin
|
||||
BINARIES := k3d
|
||||
|
||||
# Set version of the k3d helper images for build
|
||||
ifneq ($(K3D_HELPER_VERSION),)
|
||||
$(info [INFO] Helper Image version set to ${K3D_HELPER_VERSION})
|
||||
LDFLAGS += -X github.com/rancher/k3d/v5/version.HelperVersionOverride=${K3D_HELPER_VERSION}
|
||||
endif
|
||||
|
||||
# Rules for finding all go source files using 'DIRS' and 'REC_DIRS'
|
||||
GO_SRC := $(foreach dir,$(DIRS),$(wildcard $(dir)/*.go))
|
||||
GO_SRC += $(foreach dir,$(REC_DIRS),$(shell find $(dir) -name "*.go"))
|
||||
|
||||
########## Required Tools ##########
|
||||
# Go Package required
|
||||
PKG_GOX := github.com/mitchellh/gox@v1.0.1
|
||||
PKG_GOLANGCI_LINT_VERSION := 1.39.0
|
||||
PKG_GOLANGCI_LINT_SCRIPT := https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh
|
||||
PKG_GOLANGCI_LINT := github.com/golangci/golangci-lint/cmd/golangci-lint@v${PKG_GOLANGCI_LINT_VERSION}
|
||||
|
||||
########## Linting Options ##########
|
||||
# configuration adjustments for golangci-lint
|
||||
GOLANGCI_LINT_DISABLED_LINTERS := "" # disabling typecheck, because it currently (06.09.2019) fails with Go 1.13
|
||||
|
||||
# Rules for directory list as input for the golangci-lint program
|
||||
LINT_DIRS := $(DIRS) $(foreach dir,$(REC_DIRS),$(dir)/...)
|
||||
|
||||
#############################
|
||||
# #
|
||||
# TARGETS #
|
||||
# #
|
||||
#############################
|
||||
|
||||
.PHONY: all build build-cross clean fmt check-fmt lint check extra-clean install-tools
|
||||
|
||||
all: clean fmt check test build
|
||||
|
||||
############################
|
||||
########## Builds ##########
|
||||
############################
|
||||
|
||||
# debug builds
|
||||
build-debug: GCFLAGS+="all=-N -l"
|
||||
build-debug: build
|
||||
|
||||
# default build target for the local platform
|
||||
build:
|
||||
CGO_ENABLED=0 $(GO) build $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -gcflags '$(GCFLAGS)' -o '$(BINDIR)/$(BINARIES)'
|
||||
|
||||
# cross-compilation for all targets
|
||||
build-cross: LDFLAGS += -extldflags "-static"
|
||||
build-cross:
|
||||
CGO_ENABLED=0 gox -parallel=3 -output="_dist/$(BINARIES)-{{.OS}}-{{.Arch}}" -osarch='$(TARGETS)' $(GOFLAGS) $(if $(TAGS),-tags '$(TAGS)',) -ldflags '$(LDFLAGS)'
|
||||
|
||||
# build a specific docker target ( '%' matches the target as specified in the Dockerfile)
|
||||
build-docker-%:
|
||||
@echo "Building Docker image k3d:$(K3D_IMAGE_TAG)-$*"
|
||||
DOCKER_BUILDKIT=1 docker build . -t k3d:$(K3D_IMAGE_TAG)-$* --target $*
|
||||
|
||||
# build helper images
|
||||
build-helper-images:
|
||||
@echo "Building docker image rancher/k3d-proxy:$(K3D_IMAGE_TAG)"
|
||||
DOCKER_BUILDKIT=1 docker build proxy/ -f proxy/Dockerfile -t rancher/k3d-proxy:$(K3D_IMAGE_TAG)
|
||||
@echo "Building docker image rancher/k3d-tools:$(K3D_IMAGE_TAG)"
|
||||
DOCKER_BUILDKIT=1 docker build --no-cache tools/ -f tools/Dockerfile -t rancher/k3d-tools:$(K3D_IMAGE_TAG) --build-arg GIT_TAG=$(GIT_TAG)
|
||||
|
||||
##############################
|
||||
########## Cleaning ##########
|
||||
##############################
|
||||
|
||||
clean:
|
||||
@rm -rf $(BINDIR) _dist/
|
||||
|
||||
extra-clean: clean
|
||||
$(GO) clean -i $(PKG_GOX)
|
||||
$(GO) clean -i $(PKG_GOLANGCI_LINT)
|
||||
|
||||
##########################################
|
||||
########## Formatting & Linting ##########
|
||||
##########################################
|
||||
|
||||
# fmt will fix the golang source style in place.
|
||||
fmt:
|
||||
@gofmt -s -l -w $(GO_SRC)
|
||||
|
||||
# check-fmt returns an error code if any source code contains format error.
|
||||
check-fmt:
|
||||
@test -z $(shell gofmt -s -l $(GO_SRC) | tee /dev/stderr) || echo "[WARN] Fix formatting issues with 'make fmt'"
|
||||
|
||||
lint:
|
||||
@golangci-lint run -D $(GOLANGCI_LINT_DISABLED_LINTERS) $(LINT_DIRS)
|
||||
|
||||
check: check-fmt lint
|
||||
|
||||
###########################
|
||||
########## Tests ##########
|
||||
###########################
|
||||
|
||||
test:
|
||||
$(GO) test $(TESTS) $(TESTFLAGS)
|
||||
|
||||
e2e: build-docker-dind
|
||||
@echo "Running e2e tests in k3d:$(K3D_IMAGE_TAG)"
|
||||
LOG_LEVEL="$(E2E_LOG_LEVEL)" E2E_INCLUDE="$(E2E_INCLUDE)" E2E_EXCLUDE="$(E2E_EXCLUDE)" E2E_EXTRA="$(E2E_EXTRA)" E2E_RUNNER_START_TIMEOUT=$(E2E_RUNNER_START_TIMEOUT) E2E_HELPER_IMAGE_TAG="$(E2E_HELPER_IMAGE_TAG)" tests/dind.sh "${K3D_IMAGE_TAG}-dind"
|
||||
|
||||
ci-tests: fmt check e2e
|
||||
|
||||
##########################
|
||||
########## Misc ##########
|
||||
##########################
|
||||
|
||||
drone:
|
||||
@echo "Running drone pipeline locally with branch=main and event=push"
|
||||
drone exec --trusted --branch main --event push
|
||||
|
||||
#########################################
|
||||
########## Setup & Preparation ##########
|
||||
#########################################
|
||||
|
||||
# Check for required executables
|
||||
HAS_GOX := $(shell command -v gox 2> /dev/null)
|
||||
HAS_GOLANGCI := $(shell command -v golangci-lint)
|
||||
HAS_GOLANGCI_VERSION := $(shell golangci-lint --version | grep "version $(PKG_GOLANGCI_LINT_VERSION) " 2>&1)
|
||||
|
||||
install-tools:
|
||||
ifndef HAS_GOX
|
||||
($(GO) get $(PKG_GOX))
|
||||
endif
|
||||
ifndef HAS_GOLANGCI
|
||||
(curl -sfL $(PKG_GOLANGCI_LINT_SCRIPT) | sh -s -- -b $(GOENVPATH)/bin v${PKG_GOLANGCI_LINT_VERSION})
|
||||
endif
|
||||
ifdef HAS_GOLANGCI
|
||||
ifeq ($(HAS_GOLANGCI_VERSION),)
|
||||
ifdef INTERACTIVE
|
||||
@echo "Warning: Your installed version of golangci-lint (interactive: ${INTERACTIVE}) differs from what we'd like to use. Switch to v${PKG_GOLANGCI_LINT_VERSION}? [Y/n]"
|
||||
@read line; if [ $$line == "y" ]; then (curl -sfL $(PKG_GOLANGCI_LINT_SCRIPT) | sh -s -- -b $(GOENVPATH)/bin v${PKG_GOLANGCI_LINT_VERSION}); fi
|
||||
else
|
||||
@echo "Warning: you're not using the same version of golangci-lint as us (v${PKG_GOLANGCI_LINT_VERSION})"
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# In the CI system, we need...
|
||||
# - golangci-lint for linting (lint)
|
||||
# - gox for cross-compilation (build-cross)
|
||||
# - kubectl for E2E-tests (e2e)
|
||||
ci-setup:
|
||||
@echo "Installing Go tools..."
|
||||
curl -sfL $(PKG_GOLANGCI_LINT_SCRIPT) | sh -s -- -b $(GOENVPATH)/bin v$(PKG_GOLANGCI_LINT_VERSION)
|
||||
$(GO) get $(PKG_GOX)
|
||||
|
||||
@echo "Installing kubectl..."
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
|
||||
chmod +x ./kubectl
|
||||
mv ./kubectl /usr/local/bin/kubectl
|
153
README.md
153
README.md
@ -1,153 +0,0 @@
|
||||
# [](https://k3d.io/)
|
||||
|
||||
[](https://drone-publish.rancher.io/rancher/k3d)
|
||||
[](./LICENSE.md)
|
||||

|
||||
|
||||
[](https://pkg.go.dev/github.com/rancher/k3d/v5)
|
||||
[](./go.mod)
|
||||
[](https://goreportcard.com/report/github.com/rancher/k3d)
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
[](code_of_conduct.md)
|
||||
|
||||
**Please Note:** `main` is now v5.0.0 and the code for v4.x can be found in the `main-v4` branch!
|
||||
|
||||
## [k3s in docker](https://k3d.io)
|
||||
|
||||
k3s is the lightweight Kubernetes distribution by Rancher: [rancher/k3s](https://github.com/rancher/k3s)
|
||||
|
||||
k3d creates containerized k3s clusters. This means, that you can spin up a multi-node k3s cluster on a single machine using docker.
|
||||
|
||||
[](https://asciinema.org/a/436420)
|
||||
|
||||
## Learning
|
||||
|
||||
- Website with documentation: [k3d.io](https://k3d.io/)
|
||||
- [Rancher Meetup - May 2020 - Simplifying Your Cloud-Native Development Workflow With K3s, K3c and K3d (YouTube)](https://www.youtube.com/watch?v=hMr3prm9gDM)
|
||||
- k3d demo repository: [iwilltry42/k3d-demo](https://github.com/iwilltry42/k3d-demo)
|
||||
|
||||
## Requirements
|
||||
|
||||
- [docker](https://docs.docker.com/install/)
|
||||
|
||||
## Releases
|
||||
|
||||
**Note**: In May 2020 we upgraded from v1.7.x to **v3.0.0** after a complete rewrite of k3d!
|
||||
**Note**: In January 2021 we upgraded from v3.x.x to **v4.0.0** which includes some breaking changes!
|
||||
**Note**: In September 2021 we upgraded from v4.4.8 to **v5.0.0** which includes some breaking changes!
|
||||
|
||||
| Platform | Stage | Version | Release Date | |
|
||||
|-----------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|---|
|
||||
| [**GitHub Releases**](https://github.com/rancher/k3d/releases) | stable | [](https://github.com/rancher/k3d/releases/latest) | [](https://github.com/rancher/k3d/releases/latest) | |
|
||||
| [**GitHub Releases**](https://github.com/rancher/k3d/releases) | latest | [](https://github.com/rancher/k3d/releases) | [](https://github.com/rancher/k3d/releases) | |
|
||||
| [**Homebrew**](https://formulae.brew.sh/formula/k3d) | - | [](https://formulae.brew.sh/formula/k3d) | - | |
|
||||
| [**Chocolatey**](https://chocolatey.org/packages/k3d/)| stable | [](https://chocolatey.org/packages/k3d/) | - | |
|
||||
|
||||
## Get
|
||||
|
||||
You have several options there:
|
||||
|
||||
- use the install script to grab the latest release:
|
||||
- wget: `wget -q -O - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash`
|
||||
- curl: `curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash`
|
||||
- use the install script to grab a specific release (via `TAG` environment variable):
|
||||
- wget: `wget -q -O - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | TAG=v5.0.0 bash`
|
||||
- curl: `curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | TAG=v5.0.0 bash`
|
||||
|
||||
- use [Homebrew](https://brew.sh): `brew install k3d` (Homebrew is available for MacOS and Linux)
|
||||
- Formula can be found in [homebrew/homebrew-core](https://github.com/Homebrew/homebrew-core/blob/master/Formula/k3d.rb) and is mirrored to [homebrew/linuxbrew-core](https://github.com/Homebrew/linuxbrew-core/blob/master/Formula/k3d.rb)
|
||||
- install via [MacPorts](https://www.macports.org): `sudo port selfupdate && sudo port install k3d` (MacPorts is available for MacOS)
|
||||
- install via [AUR](https://aur.archlinux.org/) package [rancher-k3d-bin](https://aur.archlinux.org/packages/rancher-k3d-bin/): `yay -S rancher-k3d-bin`
|
||||
- grab a release from the [release tab](https://github.com/rancher/k3d/releases) and install it yourself.
|
||||
- install via go: `go install github.com/rancher/k3d@latest` (**Note**: this will give you unreleased/bleeding-edge changes)
|
||||
- use [Chocolatey](https://chocolatey.org/): `choco install k3d` (Chocolatey package manager is available for Windows)
|
||||
- package source can be found in [erwinkersten/chocolatey-packages](https://github.com/erwinkersten/chocolatey-packages/tree/master/automatic/k3d)
|
||||
|
||||
or...
|
||||
|
||||
## Build
|
||||
|
||||
1. Clone this repo, e.g. via `git clone git@github.com:rancher/k3d.git` or `go get github.com/rancher/k3d/v5@main`
|
||||
2. Inside the repo run
|
||||
- 'make install-tools' to make sure required go packages are installed
|
||||
3. Inside the repo run one of the following commands
|
||||
- `make build` to build for your current system
|
||||
- `go install` to install it to your `GOPATH` (**Note**: this will give you unreleased/bleeding-edge changes)
|
||||
- `make build-cross` to build for all systems
|
||||
|
||||
## Usage
|
||||
|
||||
Check out what you can do via `k3d help` or check the docs @ [k3d.io](https://k3d.io)
|
||||
|
||||
Example Workflow: Create a new cluster and use it with `kubectl`
|
||||
|
||||
1. `k3d cluster create CLUSTER_NAME` to create a new single-node cluster (= 1 container running k3s + 1 loadbalancer container)
|
||||
2. [Optional, included in cluster create] `k3d kubeconfig merge CLUSTER_NAME --kubeconfig-switch-context` to update your default kubeconfig and switch the current-context to the new one
|
||||
3. execute some commands like `kubectl get pods --all-namespaces`
|
||||
4. `k3d cluster delete CLUSTER_NAME` to delete the default cluster
|
||||
|
||||
## Connect
|
||||
|
||||
1. Join the Rancher community on slack via [slack.rancher.io](https://slack.rancher.io/)
|
||||
2. Go to [rancher-users.slack.com](https://rancher-users.slack.com) and join our channel #k3d
|
||||
3. Start chatting
|
||||
|
||||
## History
|
||||
|
||||
This repository is based on [@zeerorg](https://github.com/zeerorg/)'s [zeerorg/k3s-in-docker](https://github.com/zeerorg/k3s-in-docker), reimplemented in Go by [@iwilltry42](https://github.com/iwilltry42/) in [iwilltry42/k3d](https://github.com/iwilltry42/k3d), which got adopted by Rancher in[rancher/k3d](https://github.com/rancher/k3d).
|
||||
|
||||
## Related Projects
|
||||
|
||||
- [k3x](https://github.com/inercia/k3x): GUI (Linux) to k3d
|
||||
- [vscode-k3d](https://github.com/inercia/vscode-k3d): vscode plugin for k3d
|
||||
- [AbsaOSS/k3d-action](https://github.com/AbsaOSS/k3d-action): fully customizable GitHub Action to run lightweight Kubernetes clusters.
|
||||
- [AutoK3s](https://github.com/cnrancher/autok3s): a lightweight tool to help run K3s everywhere including k3d provider.
|
||||
- [nolar/setup-k3d-k3s](https://github.com/nolar/setup-k3d-k3s): setup K3d/K3s for GitHub Actions.
|
||||
|
||||
## Contributing
|
||||
|
||||
k3d is a community-driven project and so we welcome contributions of any form, be it code, logic, documentation, examples, requests, bug reports, ideas or anything else that pushes this project forward.
|
||||
|
||||
Please read our [**Contributing Guidelines**](./CONTRIBUTING.md) and the related [**Code of Conduct**](./CODE_OF_CONDUCT.md).
|
||||
|
||||
You can find an overview of the k3d project (e.g. explanations and a repository guide) in the documentation: [k3d.io/internals/project](https://k3d.io/internals/project)
|
||||
|
||||
[](code_of_conduct.md)
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/iwilltry42"><img src="https://avatars3.githubusercontent.com/u/25345277?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thorsten Klein</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=iwilltry42" title="Code">💻</a> <a href="https://github.com/rancher/k3d/commits?author=iwilltry42" title="Documentation">📖</a> <a href="#ideas-iwilltry42" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-iwilltry42" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://blog.zeerorg.site/"><img src="https://avatars0.githubusercontent.com/u/13547997?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rishabh Gupta</b></sub></a><br /><a href="#ideas-zeerorg" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/rancher/k3d/commits?author=zeerorg" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.zenika.com"><img src="https://avatars3.githubusercontent.com/u/25585516?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Louis Tournayre</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=louiznk" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/lionelnicolas"><img src="https://avatars3.githubusercontent.com/u/6538664?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lionel Nicolas</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=lionelnicolas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/toonsevrin.keys"><img src="https://avatars1.githubusercontent.com/u/5507199?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Toon Sevrin</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=toonsevrin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://debian-solutions.de"><img src="https://avatars3.githubusercontent.com/u/1111056?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dennis Hoppe</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=dhoppe" title="Documentation">📖</a> <a href="#example-dhoppe" title="Examples">💡</a></td>
|
||||
<td align="center"><a href="https://dellinger.dev"><img src="https://avatars0.githubusercontent.com/u/3109892?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonas Dellinger</b></sub></a><br /><a href="#infra-JohnnyCrazy" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/markrexwinkel"><img src="https://avatars2.githubusercontent.com/u/10704814?v=4?s=100" width="100px;" alt=""/><br /><sub><b>markrexwinkel</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=markrexwinkel" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://inerciatech.com/"><img src="https://avatars2.githubusercontent.com/u/1841612?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alvaro</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=inercia" title="Code">💻</a> <a href="#ideas-inercia" title="Ideas, Planning, & Feedback">🤔</a> <a href="#plugin-inercia" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="http://wsl.dev"><img src="https://avatars2.githubusercontent.com/u/905874?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nuno do Carmo</b></sub></a><br /><a href="#content-nunix" title="Content">🖋</a> <a href="#tutorial-nunix" title="Tutorials">✅</a> <a href="#question-nunix" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="https://github.com/erwinkersten"><img src="https://avatars0.githubusercontent.com/u/4391121?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Erwin Kersten</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=erwinkersten" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.alexsears.com"><img src="https://avatars.githubusercontent.com/u/3712883?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Sears</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=searsaw" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://shanduur.github.io"><img src="https://avatars.githubusercontent.com/u/32583062?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mateusz Urbanek</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=Shanduur" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/benjaminjb"><img src="https://avatars.githubusercontent.com/u/4651855?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Blattberg</b></sub></a><br /><a href="https://github.com/rancher/k3d/commits?author=benjaminjb" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
BIN
assets/images/favicon.png
Normal file
BIN
assets/images/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
29
assets/javascripts/bundle.756773cc.min.js
vendored
Normal file
29
assets/javascripts/bundle.756773cc.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
assets/javascripts/bundle.756773cc.min.js.map
Normal file
7
assets/javascripts/bundle.756773cc.min.js.map
Normal file
File diff suppressed because one or more lines are too long
1
assets/javascripts/lunr/min/lunr.ar.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.ar.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.da.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.da.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Danish` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d<a&&(d=a)}}function n(){var e,r;if(f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});
|
18
assets/javascripts/lunr/min/lunr.de.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.de.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.du.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.du.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.es.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.es.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.fi.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.fi.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.fr.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.fr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/javascripts/lunr/min/lunr.hi.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.hi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}});
|
18
assets/javascripts/lunr/min/lunr.hu.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.hu.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.it.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.it.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/javascripts/lunr/min/lunr.ja.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.ja.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n<p.length;n++)r?a.push(new e.Token(p[n],{position:[f,p[n].length],index:a.length})):a.push(p[n]),f+=p[n].length;l=c+1}return a},e.ja.stemmer=function(){return function(e){return e}}(),e.Pipeline.registerFunction(e.ja.stemmer,"stemmer-ja"),e.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",e.ja.trimmer=e.trimmerSupport.generateTrimmer(e.ja.wordCharacters),e.Pipeline.registerFunction(e.ja.trimmer,"trimmer-ja"),e.ja.stopWordFilter=e.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),e.Pipeline.registerFunction(e.ja.stopWordFilter,"stopWordFilter-ja"),e.jp=e.ja,e.Pipeline.registerFunction(e.jp.stemmer,"stemmer-jp"),e.Pipeline.registerFunction(e.jp.trimmer,"trimmer-jp"),e.Pipeline.registerFunction(e.jp.stopWordFilter,"stopWordFilter-jp")}});
|
1
assets/javascripts/lunr/min/lunr.jp.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.jp.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports=require("./lunr.ja");
|
1
assets/javascripts/lunr/min/lunr.multi.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.multi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){e.multiLanguage=function(){for(var t=Array.prototype.slice.call(arguments),i=t.join("-"),r="",n=[],s=[],p=0;p<t.length;++p)"en"==t[p]?(r+="\\w",n.unshift(e.stopWordFilter),n.push(e.stemmer),s.push(e.stemmer)):(r+=e[t[p]].wordCharacters,e[t[p]].stopWordFilter&&n.unshift(e[t[p]].stopWordFilter),e[t[p]].stemmer&&(n.push(e[t[p]].stemmer),s.push(e[t[p]].stemmer)));var o=e.trimmerSupport.generateTrimmer(r);return e.Pipeline.registerFunction(o,"lunr-multi-trimmer-"+i),n.unshift(o),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,n),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,s))}}}});
|
18
assets/javascripts/lunr/min/lunr.nl.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.nl.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.no.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.no.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Norwegian` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a<s&&(a=s)}}function i(){var e,r,n;if(w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});
|
18
assets/javascripts/lunr/min/lunr.pt.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.pt.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.ro.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.ro.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
assets/javascripts/lunr/min/lunr.ru.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.ru.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/javascripts/lunr/min/lunr.stemmer.support.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.stemmer.support.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var r;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(t){r=t,this.cursor=0,this.limit=t.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var t=r;return r=null,t},in_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e>s||e<i)return this.cursor++,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e<i)return this.cursor--,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor+s)!=i.charCodeAt(s))return!1;return this.cursor+=t,!0},eq_s_b:function(t,i){if(this.cursor-this.limit_backward<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor-t+s)!=i.charCodeAt(s))return!1;return this.cursor-=t,!0},find_among:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=l;m<_.s_size;m++){if(n+l==u){f=-1;break}if(f=r.charCodeAt(n+l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=_.s_size-1-l;m>=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});
|
18
assets/javascripts/lunr/min/lunr.sv.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.sv.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Swedish` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o<a&&(o=a)}}function t(){var e,r=w.limit_backward;if(w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});
|
1
assets/javascripts/lunr/min/lunr.th.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.th.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[-]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}});
|
18
assets/javascripts/lunr/min/lunr.tr.min.js
vendored
Normal file
18
assets/javascripts/lunr/min/lunr.tr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/javascripts/lunr/min/lunr.vi.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.vi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});
|
1
assets/javascripts/lunr/min/lunr.zh.min.js
vendored
Normal file
1
assets/javascripts/lunr/min/lunr.zh.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("nodejieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}});
|
206
assets/javascripts/lunr/tinyseg.js
Normal file
206
assets/javascripts/lunr/tinyseg.js
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* export the module via AMD, CommonJS or as a browser global
|
||||
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
|
||||
*/
|
||||
;(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(factory)
|
||||
} else if (typeof exports === 'object') {
|
||||
/**
|
||||
* Node. Does not work with strict CommonJS, but
|
||||
* only CommonJS-like environments that support module.exports,
|
||||
* like Node.
|
||||
*/
|
||||
module.exports = factory()
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
factory()(root.lunr);
|
||||
}
|
||||
}(this, function () {
|
||||
/**
|
||||
* Just return a value to define the module export.
|
||||
* This example returns an object, but the module
|
||||
* can return a function as the exported value.
|
||||
*/
|
||||
|
||||
return function(lunr) {
|
||||
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
|
||||
// (c) 2008 Taku Kudo <taku@chasen.org>
|
||||
// TinySegmenter is freely distributable under the terms of a new BSD licence.
|
||||
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
|
||||
|
||||
function TinySegmenter() {
|
||||
var patterns = {
|
||||
"[一二三四五六七八九十百千万億兆]":"M",
|
||||
"[一-龠々〆ヵヶ]":"H",
|
||||
"[ぁ-ん]":"I",
|
||||
"[ァ-ヴーア-ン゙ー]":"K",
|
||||
"[a-zA-Za-zA-Z]":"A",
|
||||
"[0-90-9]":"N"
|
||||
}
|
||||
this.chartype_ = [];
|
||||
for (var i in patterns) {
|
||||
var regexp = new RegExp(i);
|
||||
this.chartype_.push([regexp, patterns[i]]);
|
||||
}
|
||||
|
||||
this.BIAS__ = -332
|
||||
this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378};
|
||||
this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920};
|
||||
this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266};
|
||||
this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352};
|
||||
this.BP2__ = {"BO":60,"OO":-1762};
|
||||
this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965};
|
||||
this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146};
|
||||
this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699};
|
||||
this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973};
|
||||
this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682};
|
||||
this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669};
|
||||
this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990};
|
||||
this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832};
|
||||
this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649};
|
||||
this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393};
|
||||
this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841};
|
||||
this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68};
|
||||
this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591};
|
||||
this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685};
|
||||
this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156};
|
||||
this.TW1__ = {"につい":-4681,"東京都":2026};
|
||||
this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216};
|
||||
this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287};
|
||||
this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865};
|
||||
this.UC1__ = {"A":484,"K":93,"M":645,"O":-505};
|
||||
this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646};
|
||||
this.UC3__ = {"A":-1370,"I":2311};
|
||||
this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646};
|
||||
this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831};
|
||||
this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387};
|
||||
this.UP1__ = {"O":-214};
|
||||
this.UP2__ = {"B":69,"O":935};
|
||||
this.UP3__ = {"B":189};
|
||||
this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422};
|
||||
this.UQ2__ = {"BH":216,"BI":113,"OK":1759};
|
||||
this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212};
|
||||
this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135};
|
||||
this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568};
|
||||
this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278};
|
||||
this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637};
|
||||
this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343};
|
||||
this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496};
|
||||
|
||||
return this;
|
||||
}
|
||||
TinySegmenter.prototype.ctype_ = function(str) {
|
||||
for (var i in this.chartype_) {
|
||||
if (str.match(this.chartype_[i][0])) {
|
||||
return this.chartype_[i][1];
|
||||
}
|
||||
}
|
||||
return "O";
|
||||
}
|
||||
|
||||
TinySegmenter.prototype.ts_ = function(v) {
|
||||
if (v) { return v; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
TinySegmenter.prototype.segment = function(input) {
|
||||
if (input == null || input == undefined || input == "") {
|
||||
return [];
|
||||
}
|
||||
var result = [];
|
||||
var seg = ["B3","B2","B1"];
|
||||
var ctype = ["O","O","O"];
|
||||
var o = input.split("");
|
||||
for (i = 0; i < o.length; ++i) {
|
||||
seg.push(o[i]);
|
||||
ctype.push(this.ctype_(o[i]))
|
||||
}
|
||||
seg.push("E1");
|
||||
seg.push("E2");
|
||||
seg.push("E3");
|
||||
ctype.push("O");
|
||||
ctype.push("O");
|
||||
ctype.push("O");
|
||||
var word = seg[3];
|
||||
var p1 = "U";
|
||||
var p2 = "U";
|
||||
var p3 = "U";
|
||||
for (var i = 4; i < seg.length - 3; ++i) {
|
||||
var score = this.BIAS__;
|
||||
var w1 = seg[i-3];
|
||||
var w2 = seg[i-2];
|
||||
var w3 = seg[i-1];
|
||||
var w4 = seg[i];
|
||||
var w5 = seg[i+1];
|
||||
var w6 = seg[i+2];
|
||||
var c1 = ctype[i-3];
|
||||
var c2 = ctype[i-2];
|
||||
var c3 = ctype[i-1];
|
||||
var c4 = ctype[i];
|
||||
var c5 = ctype[i+1];
|
||||
var c6 = ctype[i+2];
|
||||
score += this.ts_(this.UP1__[p1]);
|
||||
score += this.ts_(this.UP2__[p2]);
|
||||
score += this.ts_(this.UP3__[p3]);
|
||||
score += this.ts_(this.BP1__[p1 + p2]);
|
||||
score += this.ts_(this.BP2__[p2 + p3]);
|
||||
score += this.ts_(this.UW1__[w1]);
|
||||
score += this.ts_(this.UW2__[w2]);
|
||||
score += this.ts_(this.UW3__[w3]);
|
||||
score += this.ts_(this.UW4__[w4]);
|
||||
score += this.ts_(this.UW5__[w5]);
|
||||
score += this.ts_(this.UW6__[w6]);
|
||||
score += this.ts_(this.BW1__[w2 + w3]);
|
||||
score += this.ts_(this.BW2__[w3 + w4]);
|
||||
score += this.ts_(this.BW3__[w4 + w5]);
|
||||
score += this.ts_(this.TW1__[w1 + w2 + w3]);
|
||||
score += this.ts_(this.TW2__[w2 + w3 + w4]);
|
||||
score += this.ts_(this.TW3__[w3 + w4 + w5]);
|
||||
score += this.ts_(this.TW4__[w4 + w5 + w6]);
|
||||
score += this.ts_(this.UC1__[c1]);
|
||||
score += this.ts_(this.UC2__[c2]);
|
||||
score += this.ts_(this.UC3__[c3]);
|
||||
score += this.ts_(this.UC4__[c4]);
|
||||
score += this.ts_(this.UC5__[c5]);
|
||||
score += this.ts_(this.UC6__[c6]);
|
||||
score += this.ts_(this.BC1__[c2 + c3]);
|
||||
score += this.ts_(this.BC2__[c3 + c4]);
|
||||
score += this.ts_(this.BC3__[c4 + c5]);
|
||||
score += this.ts_(this.TC1__[c1 + c2 + c3]);
|
||||
score += this.ts_(this.TC2__[c2 + c3 + c4]);
|
||||
score += this.ts_(this.TC3__[c3 + c4 + c5]);
|
||||
score += this.ts_(this.TC4__[c4 + c5 + c6]);
|
||||
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
|
||||
score += this.ts_(this.UQ1__[p1 + c1]);
|
||||
score += this.ts_(this.UQ2__[p2 + c2]);
|
||||
score += this.ts_(this.UQ3__[p3 + c3]);
|
||||
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
|
||||
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
|
||||
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
|
||||
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
|
||||
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
|
||||
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
|
||||
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
|
||||
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
|
||||
var p = "O";
|
||||
if (score > 0) {
|
||||
result.push(word);
|
||||
word = "";
|
||||
p = "B";
|
||||
}
|
||||
p1 = p2;
|
||||
p2 = p3;
|
||||
p3 = p;
|
||||
word += seg[i];
|
||||
}
|
||||
result.push(word);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
lunr.TinySegmenter = TinySegmenter;
|
||||
};
|
||||
|
||||
}));
|
6708
assets/javascripts/lunr/wordcut.js
Normal file
6708
assets/javascripts/lunr/wordcut.js
Normal file
File diff suppressed because one or more lines are too long
48
assets/javascripts/workers/search.409db549.min.js
vendored
Normal file
48
assets/javascripts/workers/search.409db549.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
assets/javascripts/workers/search.409db549.min.js.map
Normal file
7
assets/javascripts/workers/search.409db549.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
assets/stylesheets/main.802231af.min.css
vendored
Normal file
2
assets/stylesheets/main.802231af.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/stylesheets/main.802231af.min.css.map
Normal file
1
assets/stylesheets/main.802231af.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
assets/stylesheets/palette.3f5d1f46.min.css
vendored
Normal file
2
assets/stylesheets/palette.3f5d1f46.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
assets/stylesheets/palette.3f5d1f46.min.css.map
Normal file
1
assets/stylesheets/palette.3f5d1f46.min.css.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,58 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdCluster returns a new cobra command
|
||||
func NewCmdCluster() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "cluster",
|
||||
Short: "Manage cluster(s)",
|
||||
Long: `Manage cluster(s)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdClusterCreate(),
|
||||
NewCmdClusterStart(),
|
||||
NewCmdClusterStop(),
|
||||
NewCmdClusterDelete(),
|
||||
NewCmdClusterList(),
|
||||
NewCmdClusterEdit())
|
||||
|
||||
// add flags
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,599 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright © 2020-2021 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
cliutil "github.com/rancher/k3d/v5/cmd/util"
|
||||
cliconfig "github.com/rancher/k3d/v5/cmd/util/config"
|
||||
k3dCluster "github.com/rancher/k3d/v5/pkg/client"
|
||||
"github.com/rancher/k3d/v5/pkg/config"
|
||||
conf "github.com/rancher/k3d/v5/pkg/config/v1alpha3"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/rancher/k3d/v5/version"
|
||||
)
|
||||
|
||||
var configFile string
|
||||
|
||||
const clusterCreateDescription = `
|
||||
Create a new k3s cluster with containerized nodes (k3s in docker).
|
||||
Every cluster will consist of one or more containers:
|
||||
- 1 (or more) server node container (k3s)
|
||||
- (optionally) 1 loadbalancer container as the entrypoint to the cluster (nginx)
|
||||
- (optionally) 1 (or more) agent node containers (k3s)
|
||||
`
|
||||
|
||||
/*
|
||||
* Viper for configuration handling
|
||||
* we use two different instances of Viper here to handle
|
||||
* - cfgViper: "static" configuration
|
||||
* - ppViper: "pre-processed" configuration, where CLI input has to be pre-processed
|
||||
* to be treated as part of the SImpleConfig
|
||||
*/
|
||||
var (
|
||||
cfgViper = viper.New()
|
||||
ppViper = viper.New()
|
||||
)
|
||||
|
||||
func initConfig() error {
|
||||
|
||||
// Viper for pre-processed config options
|
||||
ppViper.SetEnvPrefix("K3D")
|
||||
|
||||
if l.Log().GetLevel() >= logrus.DebugLevel {
|
||||
|
||||
c, _ := yaml.Marshal(ppViper.AllSettings())
|
||||
l.Log().Debugf("Additional CLI Configuration:\n%s", c)
|
||||
}
|
||||
|
||||
return cliconfig.InitViperWithConfigFile(cfgViper, configFile)
|
||||
}
|
||||
|
||||
// NewCmdClusterCreate returns a new cobra command
|
||||
func NewCmdClusterCreate() *cobra.Command {
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "create NAME",
|
||||
Short: "Create a new cluster",
|
||||
Long: clusterCreateDescription,
|
||||
Args: cobra.RangeArgs(0, 1), // exactly one cluster name can be set (default: k3d.DefaultClusterName)
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return initConfig()
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
/*************************
|
||||
* Compute Configuration *
|
||||
*************************/
|
||||
if cfgViper.GetString("apiversion") == "" {
|
||||
cfgViper.Set("apiversion", config.DefaultConfigApiVersion)
|
||||
}
|
||||
if cfgViper.GetString("kind") == "" {
|
||||
cfgViper.Set("kind", "Simple")
|
||||
}
|
||||
cfg, err := config.FromViper(cfgViper)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
if cfg.GetAPIVersion() != config.DefaultConfigApiVersion {
|
||||
l.Log().Warnf("Default config apiVersion is '%s', but you're using '%s': consider migrating.", config.DefaultConfigApiVersion, cfg.GetAPIVersion())
|
||||
cfg, err = config.Migrate(cfg, config.DefaultConfigApiVersion)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
simpleCfg := cfg.(conf.SimpleConfig)
|
||||
|
||||
l.Log().Debugf("========== Simple Config ==========\n%+v\n==========================\n", simpleCfg)
|
||||
|
||||
simpleCfg, err = applyCLIOverrides(simpleCfg)
|
||||
if err != nil {
|
||||
l.Log().Fatalf("Failed to apply CLI overrides: %+v", err)
|
||||
}
|
||||
|
||||
l.Log().Debugf("========== Merged Simple Config ==========\n%+v\n==========================\n", simpleCfg)
|
||||
|
||||
/**************************************
|
||||
* Transform, Process & Validate Configuration *
|
||||
**************************************/
|
||||
|
||||
// Set the name
|
||||
if len(args) != 0 {
|
||||
simpleCfg.Name = args[0]
|
||||
}
|
||||
|
||||
clusterConfig, err := config.TransformSimpleToClusterConfig(cmd.Context(), runtimes.SelectedRuntime, simpleCfg)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
l.Log().Debugf("===== Merged Cluster Config =====\n%+v\n===== ===== =====\n", clusterConfig)
|
||||
|
||||
clusterConfig, err = config.ProcessClusterConfig(*clusterConfig)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
l.Log().Debugf("===== Processed Cluster Config =====\n%+v\n===== ===== =====\n", clusterConfig)
|
||||
|
||||
if err := config.ValidateClusterConfig(cmd.Context(), runtimes.SelectedRuntime, *clusterConfig); err != nil {
|
||||
l.Log().Fatalln("Failed Cluster Configuration Validation: ", err)
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Create cluster if it doesn't exist *
|
||||
**************************************/
|
||||
|
||||
// check if a cluster with that name exists already
|
||||
if _, err := k3dCluster.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &clusterConfig.Cluster); err == nil {
|
||||
l.Log().Fatalf("Failed to create cluster '%s' because a cluster with that name already exists", clusterConfig.Cluster.Name)
|
||||
}
|
||||
|
||||
// create cluster
|
||||
if clusterConfig.KubeconfigOpts.UpdateDefaultKubeconfig {
|
||||
l.Log().Debugln("'--kubeconfig-update-default set: enabling wait-for-server")
|
||||
clusterConfig.ClusterCreateOpts.WaitForServer = true
|
||||
}
|
||||
//if err := k3dCluster.ClusterCreate(cmd.Context(), runtimes.SelectedRuntime, &clusterConfig.Cluster, &clusterConfig.ClusterCreateOpts); err != nil {
|
||||
if err := k3dCluster.ClusterRun(cmd.Context(), runtimes.SelectedRuntime, clusterConfig); err != nil {
|
||||
// rollback if creation failed
|
||||
l.Log().Errorln(err)
|
||||
if simpleCfg.Options.K3dOptions.NoRollback { // TODO: move rollback mechanics to pkg/
|
||||
l.Log().Fatalln("Cluster creation FAILED, rollback deactivated.")
|
||||
}
|
||||
// rollback if creation failed
|
||||
l.Log().Errorln("Failed to create cluster >>> Rolling Back")
|
||||
if err := k3dCluster.ClusterDelete(cmd.Context(), runtimes.SelectedRuntime, &clusterConfig.Cluster, k3d.ClusterDeleteOpts{SkipRegistryCheck: true}); err != nil {
|
||||
l.Log().Errorln(err)
|
||||
l.Log().Fatalln("Cluster creation FAILED, also FAILED to rollback changes!")
|
||||
}
|
||||
l.Log().Fatalln("Cluster creation FAILED, all changes have been rolled back!")
|
||||
}
|
||||
l.Log().Infof("Cluster '%s' created successfully!", clusterConfig.Cluster.Name)
|
||||
|
||||
/**************
|
||||
* Kubeconfig *
|
||||
**************/
|
||||
|
||||
if !clusterConfig.KubeconfigOpts.UpdateDefaultKubeconfig && clusterConfig.KubeconfigOpts.SwitchCurrentContext {
|
||||
l.Log().Infoln("--kubeconfig-update-default=false --> sets --kubeconfig-switch-context=false")
|
||||
clusterConfig.KubeconfigOpts.SwitchCurrentContext = false
|
||||
}
|
||||
|
||||
if clusterConfig.KubeconfigOpts.UpdateDefaultKubeconfig {
|
||||
l.Log().Debugf("Updating default kubeconfig with a new context for cluster %s", clusterConfig.Cluster.Name)
|
||||
if _, err := k3dCluster.KubeconfigGetWrite(cmd.Context(), runtimes.SelectedRuntime, &clusterConfig.Cluster, "", &k3dCluster.WriteKubeConfigOptions{UpdateExisting: true, OverwriteExisting: false, UpdateCurrentContext: simpleCfg.Options.KubeconfigOptions.SwitchCurrentContext}); err != nil {
|
||||
l.Log().Warningln(err)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************
|
||||
* User Feedback *
|
||||
*****************/
|
||||
|
||||
// print information on how to use the cluster with kubectl
|
||||
l.Log().Infoln("You can now use it like this:")
|
||||
if clusterConfig.KubeconfigOpts.UpdateDefaultKubeconfig && !clusterConfig.KubeconfigOpts.SwitchCurrentContext {
|
||||
fmt.Printf("kubectl config use-context %s\n", fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, clusterConfig.Cluster.Name))
|
||||
} else if !clusterConfig.KubeconfigOpts.SwitchCurrentContext {
|
||||
if runtime.GOOS == "windows" {
|
||||
fmt.Printf("$env:KUBECONFIG=(%s kubeconfig write %s)\n", os.Args[0], clusterConfig.Cluster.Name)
|
||||
} else {
|
||||
fmt.Printf("export KUBECONFIG=$(%s kubeconfig write %s)\n", os.Args[0], clusterConfig.Cluster.Name)
|
||||
}
|
||||
}
|
||||
fmt.Println("kubectl cluster-info")
|
||||
},
|
||||
}
|
||||
|
||||
/***************
|
||||
* Config File *
|
||||
***************/
|
||||
|
||||
cmd.Flags().StringVarP(&configFile, "config", "c", "", "Path of a config file to use")
|
||||
if err := cmd.MarkFlagFilename("config", "yaml", "yml"); err != nil {
|
||||
l.Log().Fatalln("Failed to mark flag 'config' as filename flag")
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Pre-Processed Flags *
|
||||
***********************
|
||||
*
|
||||
* Flags that have a different style in the CLI than their internal representation.
|
||||
* Also, we cannot set (viper) default values just here for those.
|
||||
* Example:
|
||||
* CLI: `--api-port 0.0.0.0:6443`
|
||||
* Config File:
|
||||
* exposeAPI:
|
||||
* hostIP: 0.0.0.0
|
||||
* port: 6443
|
||||
*
|
||||
* Note: here we also use Slice-type flags instead of Array because of https://github.com/spf13/viper/issues/380
|
||||
*/
|
||||
|
||||
cmd.Flags().String("api-port", "", "Specify the Kubernetes API server port exposed on the LoadBalancer (Format: `[HOST:]HOSTPORT`)\n - Example: `k3d cluster create --servers 3 --api-port 0.0.0.0:6550`")
|
||||
_ = ppViper.BindPFlag("cli.api-port", cmd.Flags().Lookup("api-port"))
|
||||
|
||||
cmd.Flags().StringArrayP("env", "e", nil, "Add environment variables to nodes (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -e \"HTTP_PROXY=my.proxy.com@server:0\" -e \"SOME_KEY=SOME_VAL@server:0\"`")
|
||||
_ = ppViper.BindPFlag("cli.env", cmd.Flags().Lookup("env"))
|
||||
|
||||
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `[SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -v /my/path@agent:0,1 -v /tmp/test:/tmp/other@server:0`")
|
||||
_ = ppViper.BindPFlag("cli.volumes", cmd.Flags().Lookup("volume"))
|
||||
|
||||
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers (via the serverlb) to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d cluster create --agents 2 -p 8080:80@agent:0 -p 8081@agent:1`")
|
||||
_ = ppViper.BindPFlag("cli.ports", cmd.Flags().Lookup("port"))
|
||||
|
||||
cmd.Flags().StringArrayP("k3s-node-label", "", nil, "Add label to k3s node (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 --k3s-node-label \"my.label@agent:0,1\" --k3s-node-label \"other.label=somevalue@server:0\"`")
|
||||
_ = ppViper.BindPFlag("cli.k3s-node-labels", cmd.Flags().Lookup("k3s-node-label"))
|
||||
|
||||
cmd.Flags().StringArrayP("runtime-label", "", nil, "Add label to container runtime (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 --runtime-label \"my.label@agent:0,1\" --runtime-label \"other.label=somevalue@server:0\"`")
|
||||
_ = ppViper.BindPFlag("cli.runtime-labels", cmd.Flags().Lookup("runtime-label"))
|
||||
|
||||
cmd.Flags().String("registry-create", "", "Create a k3d-managed registry and connect it to the cluster (Format: `NAME[:HOST][:HOSTPORT]`\n - Example: `k3d cluster create --registry-create mycluster-registry:0.0.0.0:5432`")
|
||||
_ = ppViper.BindPFlag("cli.registries.create", cmd.Flags().Lookup("registry-create"))
|
||||
|
||||
/* k3s */
|
||||
cmd.Flags().StringArray("k3s-arg", nil, "Additional args passed to k3s command (Format: `ARG@NODEFILTER[;@NODEFILTER]`)\n - Example: `k3d cluster create --k3s-arg \"--disable=traefik@server:0\"")
|
||||
_ = ppViper.BindPFlag("cli.k3sargs", cmd.Flags().Lookup("k3s-arg"))
|
||||
|
||||
/******************
|
||||
* "Normal" Flags *
|
||||
******************
|
||||
*
|
||||
* No pre-processing needed on CLI level.
|
||||
* Bound to Viper config value.
|
||||
* Default Values set via Viper.
|
||||
*/
|
||||
|
||||
cmd.Flags().IntP("servers", "s", 0, "Specify how many servers you want to create")
|
||||
_ = cfgViper.BindPFlag("servers", cmd.Flags().Lookup("servers"))
|
||||
cfgViper.SetDefault("servers", 1)
|
||||
|
||||
cmd.Flags().IntP("agents", "a", 0, "Specify how many agents you want to create")
|
||||
_ = cfgViper.BindPFlag("agents", cmd.Flags().Lookup("agents"))
|
||||
cfgViper.SetDefault("agents", 0)
|
||||
|
||||
cmd.Flags().StringP("image", "i", "", "Specify k3s image that you want to use for the nodes")
|
||||
_ = cfgViper.BindPFlag("image", cmd.Flags().Lookup("image"))
|
||||
cfgViper.SetDefault("image", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)))
|
||||
|
||||
cmd.Flags().String("network", "", "Join an existing network")
|
||||
_ = cfgViper.BindPFlag("network", cmd.Flags().Lookup("network"))
|
||||
|
||||
cmd.Flags().String("subnet", "", "[Experimental: IPAM] Define a subnet for the newly created container network (Example: `172.28.0.0/16`)")
|
||||
_ = cfgViper.BindPFlag("subnet", cmd.Flags().Lookup("subnet"))
|
||||
|
||||
cmd.Flags().String("token", "", "Specify a cluster token. By default, we generate one.")
|
||||
_ = cfgViper.BindPFlag("token", cmd.Flags().Lookup("token"))
|
||||
|
||||
cmd.Flags().Bool("wait", true, "Wait for the server(s) to be ready before returning. Use '--timeout DURATION' to not wait forever.")
|
||||
_ = cfgViper.BindPFlag("options.k3d.wait", cmd.Flags().Lookup("wait"))
|
||||
|
||||
cmd.Flags().Duration("timeout", 0*time.Second, "Rollback changes if cluster couldn't be created in specified duration.")
|
||||
_ = cfgViper.BindPFlag("options.k3d.timeout", cmd.Flags().Lookup("timeout"))
|
||||
|
||||
cmd.Flags().Bool("kubeconfig-update-default", true, "Directly update the default kubeconfig with the new cluster's context")
|
||||
_ = cfgViper.BindPFlag("options.kubeconfig.updatedefaultkubeconfig", cmd.Flags().Lookup("kubeconfig-update-default"))
|
||||
|
||||
cmd.Flags().Bool("kubeconfig-switch-context", true, "Directly switch the default kubeconfig's current-context to the new cluster's context (requires --kubeconfig-update-default)")
|
||||
_ = cfgViper.BindPFlag("options.kubeconfig.switchcurrentcontext", cmd.Flags().Lookup("kubeconfig-switch-context"))
|
||||
|
||||
cmd.Flags().Bool("no-lb", false, "Disable the creation of a LoadBalancer in front of the server nodes")
|
||||
_ = cfgViper.BindPFlag("options.k3d.disableloadbalancer", cmd.Flags().Lookup("no-lb"))
|
||||
|
||||
cmd.Flags().Bool("no-rollback", false, "Disable the automatic rollback actions, if anything goes wrong")
|
||||
_ = cfgViper.BindPFlag("options.k3d.disablerollback", cmd.Flags().Lookup("no-rollback"))
|
||||
|
||||
cmd.Flags().String("gpus", "", "GPU devices to add to the cluster node containers ('all' to pass all GPUs) [From docker]")
|
||||
_ = cfgViper.BindPFlag("options.runtime.gpurequest", cmd.Flags().Lookup("gpus"))
|
||||
|
||||
cmd.Flags().String("servers-memory", "", "Memory limit imposed on the server nodes [From docker]")
|
||||
_ = cfgViper.BindPFlag("options.runtime.serversmemory", cmd.Flags().Lookup("servers-memory"))
|
||||
|
||||
cmd.Flags().String("agents-memory", "", "Memory limit imposed on the agents nodes [From docker]")
|
||||
_ = cfgViper.BindPFlag("options.runtime.agentsmemory", cmd.Flags().Lookup("agents-memory"))
|
||||
|
||||
/* Image Importing */
|
||||
cmd.Flags().Bool("no-image-volume", false, "Disable the creation of a volume for importing images")
|
||||
_ = cfgViper.BindPFlag("options.k3d.disableimagevolume", cmd.Flags().Lookup("no-image-volume"))
|
||||
|
||||
/* Registry */
|
||||
cmd.Flags().StringArray("registry-use", nil, "Connect to one or more k3d-managed registries running locally")
|
||||
_ = cfgViper.BindPFlag("registries.use", cmd.Flags().Lookup("registry-use"))
|
||||
|
||||
cmd.Flags().String("registry-config", "", "Specify path to an extra registries.yaml file")
|
||||
_ = cfgViper.BindPFlag("registries.config", cmd.Flags().Lookup("registry-config"))
|
||||
if err := cmd.MarkFlagFilename("registry-config", "yaml", "yml"); err != nil {
|
||||
l.Log().Fatalln("Failed to mark flag 'config' as filename flag")
|
||||
}
|
||||
|
||||
/* Loadbalancer / Proxy */
|
||||
cmd.Flags().StringSlice("lb-config-override", nil, "Use dotted YAML path syntax to override nginx loadbalancer settings")
|
||||
_ = cfgViper.BindPFlag("options.k3d.loadbalancer.configoverrides", cmd.Flags().Lookup("lb-config-override"))
|
||||
|
||||
/* Subcommands */
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
func applyCLIOverrides(cfg conf.SimpleConfig) (conf.SimpleConfig, error) {
|
||||
|
||||
/****************************
|
||||
* Parse and validate flags *
|
||||
****************************/
|
||||
|
||||
// -> API-PORT
|
||||
// parse the port mapping
|
||||
var (
|
||||
err error
|
||||
exposeAPI *k3d.ExposureOpts
|
||||
)
|
||||
|
||||
// Apply config file values as defaults
|
||||
exposeAPI = &k3d.ExposureOpts{
|
||||
PortMapping: nat.PortMapping{
|
||||
Binding: nat.PortBinding{
|
||||
HostIP: cfg.ExposeAPI.HostIP,
|
||||
HostPort: cfg.ExposeAPI.HostPort,
|
||||
},
|
||||
},
|
||||
Host: cfg.ExposeAPI.Host,
|
||||
}
|
||||
|
||||
// Overwrite if cli arg is set
|
||||
if ppViper.IsSet("cli.api-port") {
|
||||
if cfg.ExposeAPI.HostPort != "" {
|
||||
l.Log().Debugf("Overriding pre-defined kubeAPI Exposure Spec %+v with CLI argument %s", cfg.ExposeAPI, ppViper.GetString("cli.api-port"))
|
||||
}
|
||||
exposeAPI, err = cliutil.ParsePortExposureSpec(ppViper.GetString("cli.api-port"), k3d.DefaultAPIPort)
|
||||
if err != nil {
|
||||
return cfg, fmt.Errorf("failed to parse API Port spec: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set to random port if port is empty string
|
||||
if len(exposeAPI.Binding.HostPort) == 0 {
|
||||
var freePort string
|
||||
port, err := cliutil.GetFreePort()
|
||||
freePort = strconv.Itoa(port)
|
||||
if err != nil || port == 0 {
|
||||
l.Log().Warnf("Failed to get random free port: %+v", err)
|
||||
l.Log().Warnf("Falling back to internal port %s (may be blocked though)...", k3d.DefaultAPIPort)
|
||||
freePort = k3d.DefaultAPIPort
|
||||
}
|
||||
exposeAPI.Binding.HostPort = freePort
|
||||
}
|
||||
|
||||
cfg.ExposeAPI = conf.SimpleExposureOpts{
|
||||
Host: exposeAPI.Host,
|
||||
HostIP: exposeAPI.Binding.HostIP,
|
||||
HostPort: exposeAPI.Binding.HostPort,
|
||||
}
|
||||
|
||||
// -> VOLUMES
|
||||
// volumeFilterMap will map volume mounts to applied node filters
|
||||
volumeFilterMap := make(map[string][]string, 1)
|
||||
for _, volumeFlag := range ppViper.GetStringSlice("cli.volumes") {
|
||||
|
||||
// split node filter from the specified volume
|
||||
volume, filters, err := cliutil.SplitFiltersFromFlag(volumeFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
if strings.Contains(volume, k3d.DefaultRegistriesFilePath) && (cfg.Registries.Create != nil || cfg.Registries.Config != "" || len(cfg.Registries.Use) != 0) {
|
||||
l.Log().Warnf("Seems like you're mounting a file at '%s' while also using a referenced registries config or k3d-managed registries: Your mounted file will probably be overwritten!", k3d.DefaultRegistriesFilePath)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := volumeFilterMap[volume]; exists {
|
||||
volumeFilterMap[volume] = append(volumeFilterMap[volume], filters...)
|
||||
} else {
|
||||
volumeFilterMap[volume] = filters
|
||||
}
|
||||
}
|
||||
|
||||
for volume, nodeFilters := range volumeFilterMap {
|
||||
cfg.Volumes = append(cfg.Volumes, conf.VolumeWithNodeFilters{
|
||||
Volume: volume,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("VolumeFilterMap: %+v", volumeFilterMap)
|
||||
|
||||
// -> PORTS
|
||||
portFilterMap := make(map[string][]string, 1)
|
||||
for _, portFlag := range ppViper.GetStringSlice("cli.ports") {
|
||||
// split node filter from the specified volume
|
||||
portmap, filters, err := cliutil.SplitFiltersFromFlag(portFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := portFilterMap[portmap]; exists {
|
||||
l.Log().Fatalln("Same Portmapping can not be used for multiple nodes")
|
||||
} else {
|
||||
portFilterMap[portmap] = filters
|
||||
}
|
||||
}
|
||||
|
||||
for port, nodeFilters := range portFilterMap {
|
||||
cfg.Ports = append(cfg.Ports, conf.PortWithNodeFilters{
|
||||
Port: port,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("PortFilterMap: %+v", portFilterMap)
|
||||
|
||||
// --k3s-node-label
|
||||
// k3sNodeLabelFilterMap will add k3s node label to applied node filters
|
||||
k3sNodeLabelFilterMap := make(map[string][]string, 1)
|
||||
for _, labelFlag := range ppViper.GetStringSlice("cli.k3s-node-labels") {
|
||||
|
||||
// split node filter from the specified label
|
||||
label, nodeFilters, err := cliutil.SplitFiltersFromFlag(labelFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := k3sNodeLabelFilterMap[label]; exists {
|
||||
k3sNodeLabelFilterMap[label] = append(k3sNodeLabelFilterMap[label], nodeFilters...)
|
||||
} else {
|
||||
k3sNodeLabelFilterMap[label] = nodeFilters
|
||||
}
|
||||
}
|
||||
|
||||
for label, nodeFilters := range k3sNodeLabelFilterMap {
|
||||
cfg.Options.K3sOptions.NodeLabels = append(cfg.Options.K3sOptions.NodeLabels, conf.LabelWithNodeFilters{
|
||||
Label: label,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("K3sNodeLabelFilterMap: %+v", k3sNodeLabelFilterMap)
|
||||
|
||||
// --runtime-label
|
||||
// runtimeLabelFilterMap will add container runtime label to applied node filters
|
||||
runtimeLabelFilterMap := make(map[string][]string, 1)
|
||||
for _, labelFlag := range ppViper.GetStringSlice("cli.runtime-labels") {
|
||||
|
||||
// split node filter from the specified label
|
||||
label, nodeFilters, err := cliutil.SplitFiltersFromFlag(labelFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
cliutil.ValidateRuntimeLabelKey(strings.Split(label, "=")[0])
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := runtimeLabelFilterMap[label]; exists {
|
||||
runtimeLabelFilterMap[label] = append(runtimeLabelFilterMap[label], nodeFilters...)
|
||||
} else {
|
||||
runtimeLabelFilterMap[label] = nodeFilters
|
||||
}
|
||||
}
|
||||
|
||||
for label, nodeFilters := range runtimeLabelFilterMap {
|
||||
cfg.Options.Runtime.Labels = append(cfg.Options.Runtime.Labels, conf.LabelWithNodeFilters{
|
||||
Label: label,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("RuntimeLabelFilterMap: %+v", runtimeLabelFilterMap)
|
||||
|
||||
// --env
|
||||
// envFilterMap will add container env vars to applied node filters
|
||||
envFilterMap := make(map[string][]string, 1)
|
||||
for _, envFlag := range ppViper.GetStringSlice("cli.env") {
|
||||
|
||||
// split node filter from the specified env var
|
||||
env, filters, err := cliutil.SplitFiltersFromFlag(envFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := envFilterMap[env]; exists {
|
||||
envFilterMap[env] = append(envFilterMap[env], filters...)
|
||||
} else {
|
||||
envFilterMap[env] = filters
|
||||
}
|
||||
}
|
||||
|
||||
for envVar, nodeFilters := range envFilterMap {
|
||||
cfg.Env = append(cfg.Env, conf.EnvVarWithNodeFilters{
|
||||
EnvVar: envVar,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("EnvFilterMap: %+v", envFilterMap)
|
||||
|
||||
// --k3s-arg
|
||||
argFilterMap := make(map[string][]string, 1)
|
||||
for _, argFlag := range ppViper.GetStringSlice("cli.k3sargs") {
|
||||
|
||||
// split node filter from the specified arg
|
||||
arg, filters, err := cliutil.SplitFiltersFromFlag(argFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := argFilterMap[arg]; exists {
|
||||
argFilterMap[arg] = append(argFilterMap[arg], filters...)
|
||||
} else {
|
||||
argFilterMap[arg] = filters
|
||||
}
|
||||
}
|
||||
|
||||
for arg, nodeFilters := range argFilterMap {
|
||||
cfg.Options.K3sOptions.ExtraArgs = append(cfg.Options.K3sOptions.ExtraArgs, conf.K3sArgWithNodeFilters{
|
||||
Arg: arg,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
// --registry-create
|
||||
if ppViper.IsSet("cli.registries.create") {
|
||||
flagvalue := ppViper.GetString("cli.registries.create")
|
||||
fvSplit := strings.SplitN(flagvalue, ":", 2)
|
||||
if cfg.Registries.Create == nil {
|
||||
cfg.Registries.Create = &conf.SimpleConfigRegistryCreateConfig{}
|
||||
}
|
||||
cfg.Registries.Create.Name = fvSplit[0]
|
||||
if len(fvSplit) > 1 {
|
||||
exposeAPI, err = cliutil.ParsePortExposureSpec(fvSplit[1], "1234") // internal port is unused after all
|
||||
if err != nil {
|
||||
return cfg, fmt.Errorf("failed to registry port spec: %w", err)
|
||||
}
|
||||
cfg.Registries.Create.Host = exposeAPI.Host
|
||||
cfg.Registries.Create.HostPort = exposeAPI.Binding.HostPort
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
cliconfig "github.com/rancher/k3d/v5/cmd/util/config"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
k3dutil "github.com/rancher/k3d/v5/pkg/util"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var clusterDeleteConfigFile string
|
||||
var clusterDeleteCfgViper = viper.New()
|
||||
|
||||
// NewCmdClusterDelete returns a new cobra command
|
||||
func NewCmdClusterDelete() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete [NAME [NAME ...] | --all]",
|
||||
Aliases: []string{"del", "rm"},
|
||||
Short: "Delete cluster(s).",
|
||||
Long: `Delete cluster(s).`,
|
||||
Args: cobra.MinimumNArgs(0), // 0 or n arguments; 0 = default cluster name
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return cliconfig.InitViperWithConfigFile(clusterDeleteCfgViper, clusterDeleteConfigFile)
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
clusters := parseDeleteClusterCmd(cmd, args)
|
||||
|
||||
if len(clusters) == 0 {
|
||||
l.Log().Infoln("No clusters found")
|
||||
} else {
|
||||
for _, c := range clusters {
|
||||
if err := client.ClusterDelete(cmd.Context(), runtimes.SelectedRuntime, c, k3d.ClusterDeleteOpts{SkipRegistryCheck: false}); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
l.Log().Infoln("Removing cluster details from default kubeconfig...")
|
||||
if err := client.KubeconfigRemoveClusterFromDefaultConfig(cmd.Context(), c); err != nil {
|
||||
l.Log().Warnln("Failed to remove cluster details from default kubeconfig")
|
||||
l.Log().Warnln(err)
|
||||
}
|
||||
l.Log().Infoln("Removing standalone kubeconfig file (if there is one)...")
|
||||
configDir, err := k3dutil.GetConfigDirOrCreate()
|
||||
if err != nil {
|
||||
l.Log().Warnf("Failed to delete kubeconfig file: %+v", err)
|
||||
} else {
|
||||
kubeconfigfile := path.Join(configDir, fmt.Sprintf("kubeconfig-%s.yaml", c.Name))
|
||||
if err := os.Remove(kubeconfigfile); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
l.Log().Warnf("Failed to delete kubeconfig file '%s'", kubeconfigfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l.Log().Infof("Successfully deleted cluster %s!", c.Name)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolP("all", "a", false, "Delete all existing clusters")
|
||||
|
||||
/***************
|
||||
* Config File *
|
||||
***************/
|
||||
|
||||
cmd.Flags().StringVarP(&clusterDeleteConfigFile, "config", "c", "", "Path of a config file to use")
|
||||
if err := cmd.MarkFlagFilename("config", "yaml", "yml"); err != nil {
|
||||
l.Log().Fatalln("Failed to mark flag 'config' as filename flag")
|
||||
}
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseDeleteClusterCmd parses the command input into variables required to delete clusters
|
||||
func parseDeleteClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
|
||||
|
||||
var clusters []*k3d.Cluster
|
||||
|
||||
// --all
|
||||
all, err := cmd.Flags().GetBool("all")
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// --config
|
||||
if clusterDeleteConfigFile != "" {
|
||||
// not allowed with --all or more args
|
||||
if len(args) > 0 || all {
|
||||
l.Log().Fatalln("failed to delete cluster: cannot use `--config` flag with additional arguments or `--all`")
|
||||
}
|
||||
|
||||
if clusterDeleteCfgViper.GetString("name") == "" {
|
||||
l.Log().Fatalln("failed to delete cluster via config file: no name in config file")
|
||||
}
|
||||
|
||||
c, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterDeleteCfgViper.GetString("name")})
|
||||
if err != nil {
|
||||
l.Log().Fatalf("failed to delete cluster '%s': %v", clusterDeleteCfgViper.GetString("name"), err)
|
||||
}
|
||||
|
||||
clusters = append(clusters, c)
|
||||
return clusters
|
||||
}
|
||||
|
||||
// --all was set
|
||||
if all {
|
||||
l.Log().Infoln("Deleting all clusters...")
|
||||
clusters, err = client.ClusterList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
return clusters
|
||||
}
|
||||
|
||||
// args only
|
||||
clusternames := []string{k3d.DefaultClusterName}
|
||||
if len(args) != 0 {
|
||||
clusternames = args
|
||||
}
|
||||
|
||||
for _, name := range clusternames {
|
||||
c, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
|
||||
if err != nil {
|
||||
if err == client.ClusterGetNoNodesFoundError {
|
||||
continue
|
||||
}
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, c)
|
||||
}
|
||||
|
||||
return clusters
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
cliutil "github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
conf "github.com/rancher/k3d/v5/pkg/config/v1alpha3"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdClusterEdit returns a new cobra command
|
||||
func NewCmdClusterEdit() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "edit CLUSTER",
|
||||
Short: "[EXPERIMENTAL] Edit cluster(s).",
|
||||
Long: `[EXPERIMENTAL] Edit cluster(s).`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Aliases: []string{"update"},
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
existingCluster, changeset := parseEditClusterCmd(cmd, args)
|
||||
|
||||
l.Log().Debugf("===== Current =====\n%+v\n===== Changeset =====\n%+v\n", existingCluster, changeset)
|
||||
|
||||
if err := client.ClusterEditChangesetSimple(cmd.Context(), runtimes.SelectedRuntime, existingCluster, changeset); err != nil {
|
||||
l.Log().Fatalf("Failed to update the cluster: %v", err)
|
||||
}
|
||||
|
||||
l.Log().Infof("Successfully updated %s", existingCluster.Name)
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
|
||||
// add flags
|
||||
cmd.Flags().StringArray("port-add", nil, "[EXPERIMENTAL] Map ports from the node containers (via the serverlb) to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d node edit k3d-mycluster-serverlb --port-add 8080:80`")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseEditClusterCmd parses the command input into variables required to delete nodes
|
||||
func parseEditClusterCmd(cmd *cobra.Command, args []string) (*k3d.Cluster, *conf.SimpleConfig) {
|
||||
|
||||
existingCluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: args[0]})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
if existingCluster == nil {
|
||||
l.Log().Infof("Cluster %s not found", args[0])
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
changeset := conf.SimpleConfig{}
|
||||
|
||||
/*
|
||||
* --port-add
|
||||
*/
|
||||
portFlags, err := cmd.Flags().GetStringArray("port-add")
|
||||
if err != nil {
|
||||
l.Log().Errorln(err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// init portmap
|
||||
changeset.Ports = []conf.PortWithNodeFilters{}
|
||||
|
||||
portFilterMap := make(map[string][]string, 1)
|
||||
for _, portFlag := range portFlags {
|
||||
|
||||
// split node filter from the specified volume
|
||||
portmap, filters, err := cliutil.SplitFiltersFromFlag(portFlag)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// create new entry or append filter to existing entry
|
||||
if _, exists := portFilterMap[portmap]; exists {
|
||||
l.Log().Fatalln("Same Portmapping can not be used for multiple nodes")
|
||||
} else {
|
||||
portFilterMap[portmap] = filters
|
||||
}
|
||||
}
|
||||
|
||||
for port, nodeFilters := range portFilterMap {
|
||||
changeset.Ports = append(changeset.Ports, conf.PortWithNodeFilters{
|
||||
Port: port,
|
||||
NodeFilters: nodeFilters,
|
||||
})
|
||||
}
|
||||
|
||||
l.Log().Tracef("PortFilterMap: %+v", portFilterMap)
|
||||
|
||||
return existingCluster, &changeset
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
k3cluster "github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"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
|
||||
output string
|
||||
}
|
||||
|
||||
// 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")
|
||||
cmd.Flags().StringVarP(&clusterFlags.output, "output", "o", "", "Output format. One of: json|yaml")
|
||||
|
||||
// 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 {
|
||||
l.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 {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, retrievedCluster)
|
||||
}
|
||||
}
|
||||
|
||||
return clusters
|
||||
}
|
||||
|
||||
// PrintPrintClusters : display list of cluster
|
||||
func PrintClusters(clusters []*k3d.Cluster, flags clusterFlags) {
|
||||
// the output details printed when we dump JSON/YAML
|
||||
type jsonOutput struct {
|
||||
k3d.Cluster
|
||||
ServersRunning int `yaml:"servers_running" json:"serversRunning"`
|
||||
ServersCount int `yaml:"servers_count" json:"serversCount"`
|
||||
AgentsRunning int `yaml:"agents_running" json:"agentsRunning"`
|
||||
AgentsCount int `yaml:"agents_count" json:"agentsCount"`
|
||||
LoadBalancer bool `yaml:"has_lb,omitempty" json:"hasLoadbalancer,omitempty"`
|
||||
}
|
||||
|
||||
jsonOutputEntries := []jsonOutput{}
|
||||
|
||||
outputFormat := strings.ToLower(flags.output)
|
||||
|
||||
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths)
|
||||
defer tabwriter.Flush()
|
||||
|
||||
if outputFormat != "json" && outputFormat != "yaml" {
|
||||
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 {
|
||||
l.Log().Fatalln("Failed to print headers")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k3cluster.SortClusters(clusters)
|
||||
|
||||
for _, cluster := range clusters {
|
||||
serverCount, serversRunning := cluster.ServerCountRunning()
|
||||
agentCount, agentsRunning := cluster.AgentCountRunning()
|
||||
hasLB := cluster.HasLoadBalancer()
|
||||
|
||||
if outputFormat == "json" || outputFormat == "yaml" {
|
||||
entry := jsonOutput{
|
||||
Cluster: *cluster,
|
||||
ServersRunning: serversRunning,
|
||||
ServersCount: serverCount,
|
||||
AgentsRunning: agentsRunning,
|
||||
AgentsCount: agentCount,
|
||||
LoadBalancer: hasLB,
|
||||
}
|
||||
|
||||
if !flags.token {
|
||||
entry.Token = ""
|
||||
}
|
||||
|
||||
// clear some things
|
||||
entry.ExternalDatastore = nil
|
||||
|
||||
jsonOutputEntries = append(jsonOutputEntries, entry)
|
||||
} else {
|
||||
if flags.token {
|
||||
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\t%s\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB, cluster.Token)
|
||||
} else {
|
||||
fmt.Fprintf(tabwriter, "%s\t%d/%d\t%d/%d\t%t\n", cluster.Name, serversRunning, serverCount, agentsRunning, agentCount, hasLB)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if outputFormat == "json" {
|
||||
b, err := json.Marshal(jsonOutputEntries)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
} else if outputFormat == "yaml" {
|
||||
b, err := yaml.Marshal(jsonOutputEntries)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"time"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
"github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
)
|
||||
|
||||
// NewCmdClusterStart returns a new cobra command
|
||||
func NewCmdClusterStart() *cobra.Command {
|
||||
|
||||
startClusterOpts := types.ClusterStartOpts{
|
||||
Intent: k3d.IntentClusterStart,
|
||||
}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "start [NAME [NAME...] | --all]",
|
||||
Long: `Start existing k3d cluster(s)`,
|
||||
Short: "Start existing k3d cluster(s)",
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
clusters := parseStartClusterCmd(cmd, args)
|
||||
if len(clusters) == 0 {
|
||||
l.Log().Infoln("No clusters found")
|
||||
} else {
|
||||
for _, c := range clusters {
|
||||
envInfo, err := client.GatherEnvironmentInfo(cmd.Context(), runtimes.SelectedRuntime, c)
|
||||
if err != nil {
|
||||
l.Log().Fatalf("failed to gather info about cluster environment: %v", err)
|
||||
}
|
||||
startClusterOpts.EnvironmentInfo = envInfo
|
||||
if err := client.ClusterStart(cmd.Context(), runtimes.SelectedRuntime, c, startClusterOpts); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
l.Log().Infof("Started cluster '%s'", c.Name)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolP("all", "a", false, "Start all existing clusters")
|
||||
cmd.Flags().BoolVar(&startClusterOpts.WaitForServer, "wait", true, "Wait for the server(s) (and loadbalancer) to be ready before returning.")
|
||||
cmd.Flags().DurationVar(&startClusterOpts.Timeout, "timeout", 0*time.Second, "Maximum waiting time for '--wait' before canceling/returning.")
|
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseStartClusterCmd parses the command input into variables required to start clusters
|
||||
func parseStartClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
|
||||
// --all
|
||||
var clusters []*k3d.Cluster
|
||||
|
||||
if all, err := cmd.Flags().GetBool("all"); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
} else if all {
|
||||
clusters, err = client.ClusterList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
return clusters
|
||||
}
|
||||
|
||||
clusternames := []string{k3d.DefaultClusterName}
|
||||
if len(args) != 0 {
|
||||
clusternames = args
|
||||
}
|
||||
|
||||
for _, name := range clusternames {
|
||||
cluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
|
||||
return clusters
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
)
|
||||
|
||||
// NewCmdClusterStop returns a new cobra command
|
||||
func NewCmdClusterStop() *cobra.Command {
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "stop [NAME [NAME...] | --all]",
|
||||
Short: "Stop existing k3d cluster(s)",
|
||||
Long: `Stop existing k3d cluster(s).`,
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
clusters := parseStopClusterCmd(cmd, args)
|
||||
if len(clusters) == 0 {
|
||||
l.Log().Infoln("No clusters found")
|
||||
} else {
|
||||
for _, c := range clusters {
|
||||
if err := client.ClusterStop(cmd.Context(), runtimes.SelectedRuntime, c); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolP("all", "a", false, "Stop all existing clusters")
|
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseStopClusterCmd parses the command input into variables required to start clusters
|
||||
func parseStopClusterCmd(cmd *cobra.Command, args []string) []*k3d.Cluster {
|
||||
// --all
|
||||
var clusters []*k3d.Cluster
|
||||
|
||||
if all, err := cmd.Flags().GetBool("all"); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
} else if all {
|
||||
clusters, err = client.ClusterList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
return clusters
|
||||
}
|
||||
|
||||
clusternames := []string{k3d.DefaultClusterName}
|
||||
if len(args) != 0 {
|
||||
clusternames = args
|
||||
}
|
||||
|
||||
for _, name := range clusternames {
|
||||
cluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: name})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
|
||||
return clusters
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 config
|
||||
|
||||
import (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdConfig returns a new cobra command
|
||||
func NewCmdConfig() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Work with config file(s)",
|
||||
Long: `Work with config file(s)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdConfigInit(), NewCmdConfigMigrate())
|
||||
|
||||
return cmd
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
config "github.com/rancher/k3d/v5/pkg/config/v1alpha3"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdConfigInit returns a new cobra command
|
||||
func NewCmdConfigInit() *cobra.Command {
|
||||
var output string
|
||||
var force bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Aliases: []string{"create"},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
l.Log().Infoln("COMING SOON: print a basic k3d config with default pre-filled.")
|
||||
if output == "-" {
|
||||
fmt.Println(config.DefaultConfig)
|
||||
} else {
|
||||
// check if file exists
|
||||
var file *os.File
|
||||
var err error
|
||||
_, err = os.Stat(output)
|
||||
if os.IsNotExist(err) || force {
|
||||
// create/overwrite file
|
||||
file, err = os.Create(output)
|
||||
if err != nil {
|
||||
l.Log().Fatalf("Failed to create/overwrite output file: %s", err)
|
||||
}
|
||||
// write content
|
||||
if _, err = file.WriteString(config.DefaultConfig); err != nil {
|
||||
l.Log().Fatalf("Failed to write to output file: %+v", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
l.Log().Fatalf("Failed to stat output file: %+v", err)
|
||||
} else {
|
||||
l.Log().Errorln("Output file exists and --force was not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&output, "output", "o", "k3d-default.yaml", "Write a default k3d config")
|
||||
if err := cmd.MarkFlagFilename("output", "yaml", "yml"); err != nil {
|
||||
l.Log().Fatalf("Failed to mark flag 'output' as filename flag: %v", err)
|
||||
}
|
||||
cmd.Flags().BoolVarP(&force, "force", "f", false, "Force overwrite of target file")
|
||||
|
||||
return cmd
|
||||
}
|
@ -1,112 +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 config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/k3d/v5/pkg/config"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// NewCmdConfigMigrate returns a new cobra command
|
||||
func NewCmdConfigMigrate() *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate INPUT [OUTPUT]",
|
||||
Aliases: []string{"update"},
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
configFile := args[0]
|
||||
|
||||
if _, err := os.Stat(configFile); err != nil {
|
||||
l.Log().Fatalf("Failed to stat config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
cfgViper := viper.New()
|
||||
cfgViper.SetConfigType("yaml")
|
||||
|
||||
cfgViper.SetConfigFile(configFile)
|
||||
|
||||
// try to read config into memory (viper map structure)
|
||||
if err := cfgViper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
l.Log().Fatalf("Config file %s not found: %+v", configFile, err)
|
||||
}
|
||||
// config file found but some other error happened
|
||||
l.Log().Fatalf("Failed to read config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
schema, err := config.GetSchemaByVersion(cfgViper.GetString("apiVersion"))
|
||||
if err != nil {
|
||||
l.Log().Fatalf("Cannot validate config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
if err := config.ValidateSchemaFile(configFile, schema); err != nil {
|
||||
l.Log().Fatalf("Schema Validation failed for config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
l.Log().Infof("Using config file %s (%s#%s)", cfgViper.ConfigFileUsed(), strings.ToLower(cfgViper.GetString("apiVersion")), strings.ToLower(cfgViper.GetString("kind")))
|
||||
|
||||
cfg, err := config.FromViper(cfgViper)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
if cfg.GetAPIVersion() != config.DefaultConfigApiVersion {
|
||||
cfg, err = config.Migrate(cfg, config.DefaultConfigApiVersion)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
yamlout, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
output := "-"
|
||||
|
||||
if len(args) > 1 {
|
||||
output = args[1]
|
||||
}
|
||||
|
||||
if output == "-" {
|
||||
if _, err := os.Stdout.Write(yamlout); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
if err := os.WriteFile(output, yamlout, os.ModePerm); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewCmdConfig returns a new cobra command
|
||||
func NewCmdConfigView() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "view",
|
||||
Aliases: []string{"show"},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("%+v", viper.AllSettings())
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 debug
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
"github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// NewCmdDebug returns a new cobra command
|
||||
func NewCmdDebug() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "debug",
|
||||
Hidden: true,
|
||||
Short: "Debug k3d cluster(s)",
|
||||
Long: `Debug k3d cluster(s)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdDebugLoadbalancer())
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewCmdDebugLoadbalancer() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "loadbalancer",
|
||||
Aliases: []string{"lb"},
|
||||
Short: "Debug the loadbalancer",
|
||||
Long: `Debug the loadbalancer`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(&cobra.Command{
|
||||
Use: "get-config CLUSTERNAME",
|
||||
Args: cobra.ExactArgs(1), // cluster name
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
c, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &types.Cluster{Name: args[0]})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
lbconf, err := client.GetLoadbalancerConfig(cmd.Context(), runtimes.SelectedRuntime, c)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
yamlized, err := yaml.Marshal(lbconf)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
fmt.Println(string(yamlized))
|
||||
},
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 image
|
||||
|
||||
import (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdImage returns a new cobra command
|
||||
func NewCmdImage() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "image",
|
||||
Aliases: []string{"images"},
|
||||
Short: "Handle container images.",
|
||||
Long: `Handle container images.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdImageImport())
|
||||
|
||||
// add flags
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 image
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
)
|
||||
|
||||
// NewCmdImageImport returns a new cobra command
|
||||
func NewCmdImageImport() *cobra.Command {
|
||||
|
||||
loadImageOpts := k3d.ImageImportOpts{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "import [IMAGE | ARCHIVE [IMAGE | ARCHIVE...]]",
|
||||
Short: "Import image(s) from docker into k3d cluster(s).",
|
||||
Long: `Import image(s) from docker into k3d cluster(s).
|
||||
|
||||
If an IMAGE starts with the prefix 'docker.io/', then this prefix is stripped internally.
|
||||
That is, 'docker.io/rancher/k3d-tools:latest' is treated as 'rancher/k3d-tools:latest'.
|
||||
|
||||
If an IMAGE starts with the prefix 'library/' (or 'docker.io/library/'), then this prefix is stripped internally.
|
||||
That is, 'library/busybox:latest' (or 'docker.io/library/busybox:latest') are treated as 'busybox:latest'.
|
||||
|
||||
If an IMAGE does not have a version tag, then ':latest' is assumed.
|
||||
That is, 'rancher/k3d-tools' is treated as 'rancher/k3d-tools:latest'.
|
||||
|
||||
A file ARCHIVE always takes precedence.
|
||||
So if a file './rancher/k3d-tools' exists, k3d will try to import it instead of the IMAGE of the same name.`,
|
||||
Aliases: []string{"load"},
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
images, clusters := parseLoadImageCmd(cmd, args)
|
||||
l.Log().Debugf("Importing image(s) [%+v] from runtime [%s] into cluster(s) [%+v]...", images, runtimes.SelectedRuntime, clusters)
|
||||
errOccured := false
|
||||
for _, cluster := range clusters {
|
||||
l.Log().Infof("Importing image(s) into cluster '%s'", cluster.Name)
|
||||
if err := client.ImageImportIntoClusterMulti(cmd.Context(), runtimes.SelectedRuntime, images, &cluster, loadImageOpts); err != nil {
|
||||
l.Log().Errorf("Failed to import image(s) into cluster '%s': %+v", cluster.Name, err)
|
||||
errOccured = true
|
||||
}
|
||||
}
|
||||
if errOccured {
|
||||
l.Log().Warnln("At least one error occured while trying to import the image(s) into the selected cluster(s)")
|
||||
os.Exit(1)
|
||||
}
|
||||
l.Log().Infof("Successfully imported %d image(s) into %d cluster(s)", len(images), len(clusters))
|
||||
},
|
||||
}
|
||||
|
||||
/*********
|
||||
* Flags *
|
||||
*********/
|
||||
cmd.Flags().StringArrayP("cluster", "c", []string{k3d.DefaultClusterName}, "Select clusters to load the image to.")
|
||||
if err := cmd.RegisterFlagCompletionFunc("cluster", util.ValidArgsAvailableClusters); err != nil {
|
||||
l.Log().Fatalln("Failed to register flag completion for '--cluster'", err)
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&loadImageOpts.KeepTar, "keep-tarball", "k", false, "Do not delete the tarball containing the saved images from the shared volume")
|
||||
cmd.Flags().BoolVarP(&loadImageOpts.KeepToolsNode, "keep-tools", "t", false, "Do not delete the tools node after import")
|
||||
|
||||
/* Subcommands */
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseLoadImageCmd parses the command input into variables required to create a cluster
|
||||
func parseLoadImageCmd(cmd *cobra.Command, args []string) ([]string, []k3d.Cluster) {
|
||||
|
||||
// --cluster
|
||||
clusterNames, err := cmd.Flags().GetStringArray("cluster")
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters := []k3d.Cluster{}
|
||||
for _, clusterName := range clusterNames {
|
||||
clusters = append(clusters, k3d.Cluster{Name: clusterName})
|
||||
}
|
||||
|
||||
// images
|
||||
images := args
|
||||
if len(images) == 0 {
|
||||
l.Log().Fatalln("No images specified!")
|
||||
}
|
||||
|
||||
return images, clusters
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdKubeconfig returns a new cobra command
|
||||
func NewCmdKubeconfig() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "kubeconfig",
|
||||
Short: "Manage kubeconfig(s)",
|
||||
Long: `Manage kubeconfig(s)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdKubeconfigGet(), NewCmdKubeconfigMerge())
|
||||
|
||||
// add flags
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type getKubeconfigFlags struct {
|
||||
all bool
|
||||
}
|
||||
|
||||
// NewCmdKubeconfigGet returns a new cobra command
|
||||
func NewCmdKubeconfigGet() *cobra.Command {
|
||||
|
||||
writeKubeConfigOptions := client.WriteKubeConfigOptions{
|
||||
UpdateExisting: true,
|
||||
UpdateCurrentContext: true,
|
||||
OverwriteExisting: true,
|
||||
}
|
||||
|
||||
getKubeconfigFlags := getKubeconfigFlags{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "get [CLUSTER [CLUSTER [...]] | --all]",
|
||||
Short: "Print kubeconfig(s) from cluster(s).",
|
||||
Long: `Print kubeconfig(s) from cluster(s).`,
|
||||
Aliases: []string{"print", "show"},
|
||||
ValidArgsFunction: util.ValidArgsAvailableClusters,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if (len(args) < 1 && !getKubeconfigFlags.all) || (len(args) > 0 && getKubeconfigFlags.all) {
|
||||
return fmt.Errorf("Need to specify one or more cluster names *or* set `--all` flag")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var clusters []*k3d.Cluster
|
||||
var err error
|
||||
|
||||
// generate list of clusters
|
||||
if getKubeconfigFlags.all {
|
||||
clusters, err = client.ClusterList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
for _, clusterName := range args {
|
||||
retrievedCluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, retrievedCluster)
|
||||
}
|
||||
}
|
||||
|
||||
// get kubeconfigs from all clusters
|
||||
errorGettingKubeconfig := false
|
||||
for _, c := range clusters {
|
||||
l.Log().Debugf("Getting kubeconfig for cluster '%s'", c.Name)
|
||||
fmt.Println("---") // YAML document separator
|
||||
if _, err := client.KubeconfigGetWrite(cmd.Context(), runtimes.SelectedRuntime, c, "-", &writeKubeConfigOptions); err != nil {
|
||||
l.Log().Errorln(err)
|
||||
errorGettingKubeconfig = true
|
||||
}
|
||||
}
|
||||
|
||||
// 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().BoolVarP(&getKubeconfigFlags.all, "all", "a", false, "Output kubeconfigs from all existing clusters")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
k3dutil "github.com/rancher/k3d/v5/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
type mergeKubeconfigFlags struct {
|
||||
all bool
|
||||
output string
|
||||
targetDefault bool
|
||||
}
|
||||
|
||||
// NewCmdKubeconfigMerge returns a new cobra command
|
||||
func NewCmdKubeconfigMerge() *cobra.Command {
|
||||
|
||||
writeKubeConfigOptions := client.WriteKubeConfigOptions{}
|
||||
|
||||
mergeKubeconfigFlags := mergeKubeconfigFlags{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "merge [CLUSTER [CLUSTER [...]] | --all]",
|
||||
Aliases: []string{"write"},
|
||||
Long: `Write/Merge kubeconfig(s) from cluster(s) into new or existing kubeconfig/file.`,
|
||||
Short: "Write/Merge kubeconfig(s) from cluster(s) into new or 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 != "" {
|
||||
l.Log().Fatalln("Cannot use both '--output' and '--kubeconfig-merge-default' at the same time")
|
||||
}
|
||||
|
||||
// generate list of clusters
|
||||
if mergeKubeconfigFlags.all {
|
||||
clusters, err = client.ClusterList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
|
||||
clusternames := []string{k3d.DefaultClusterName}
|
||||
if len(args) != 0 {
|
||||
clusternames = args
|
||||
}
|
||||
|
||||
for _, clusterName := range clusternames {
|
||||
retrievedCluster, err := client.ClusterGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Cluster{Name: clusterName})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
clusters = append(clusters, retrievedCluster)
|
||||
}
|
||||
}
|
||||
|
||||
// get kubeconfigs from all clusters
|
||||
errorGettingKubeconfig := false
|
||||
var outputs []string
|
||||
outputDir, err := k3dutil.GetConfigDirOrCreate()
|
||||
if err != nil {
|
||||
l.Log().Errorln(err)
|
||||
l.Log().Fatalln("Failed to save kubeconfig to local directory")
|
||||
}
|
||||
for _, c := range clusters {
|
||||
l.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 = client.KubeconfigGetWrite(cmd.Context(), runtimes.SelectedRuntime, c, output, &writeKubeConfigOptions)
|
||||
if err != nil {
|
||||
l.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 {
|
||||
l.Log().Fatalln("Failed to mark flag --output as filename")
|
||||
}
|
||||
cmd.Flags().BoolVarP(&mergeKubeconfigFlags.targetDefault, "kubeconfig-merge-default", "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, "kubeconfig-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
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdNode returns a new cobra command
|
||||
func NewCmdNode() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "node",
|
||||
Short: "Manage node(s)",
|
||||
Long: `Manage node(s)`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdNodeCreate(),
|
||||
NewCmdNodeStart(),
|
||||
NewCmdNodeStop(),
|
||||
NewCmdNodeDelete(),
|
||||
NewCmdNodeList(),
|
||||
NewCmdNodeEdit())
|
||||
|
||||
// add flags
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
dockerunits "github.com/docker/go-units"
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
cliutil "github.com/rancher/k3d/v5/cmd/util"
|
||||
k3dc "github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/rancher/k3d/v5/version"
|
||||
)
|
||||
|
||||
// NewCmdNodeCreate returns a new cobra command
|
||||
func NewCmdNodeCreate() *cobra.Command {
|
||||
|
||||
createNodeOpts := k3d.NodeCreateOpts{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "create NAME",
|
||||
Short: "Create a new k3s node in docker",
|
||||
Long: `Create a new containerized k3s node (k3s in docker).`,
|
||||
Args: cobra.ExactArgs(1), // exactly one name accepted // TODO: if not specified, inherit from cluster that the node shall belong to, if that is specified
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
nodes, clusterName := parseCreateNodeCmd(cmd, args)
|
||||
if strings.HasPrefix(clusterName, "https://") {
|
||||
l.Log().Infof("Adding %d node(s) to the remote cluster '%s'...", len(nodes), clusterName)
|
||||
if err := k3dc.NodeAddToClusterMultiRemote(cmd.Context(), runtimes.SelectedRuntime, nodes, clusterName, createNodeOpts); err != nil {
|
||||
l.Log().Fatalf("failed to add %d node(s) to the remote cluster '%s': %v", len(nodes), clusterName, err)
|
||||
}
|
||||
} else {
|
||||
l.Log().Infof("Adding %d node(s) to the runtime local cluster '%s'...", len(nodes), clusterName)
|
||||
if err := k3dc.NodeAddToClusterMulti(cmd.Context(), runtimes.SelectedRuntime, nodes, &k3d.Cluster{Name: clusterName}, createNodeOpts); err != nil {
|
||||
l.Log().Fatalf("failed to add %d node(s) to the runtime local cluster '%s': %v", len(nodes), clusterName, err)
|
||||
}
|
||||
}
|
||||
l.Log().Infof("Successfully created %d node(s)!", len(nodes))
|
||||
},
|
||||
}
|
||||
|
||||
// add flags
|
||||
cmd.Flags().Int("replicas", 1, "Number of replicas of this node specification.")
|
||||
cmd.Flags().String("role", string(k3d.AgentRole), "Specify node role [server, agent]")
|
||||
if err := cmd.RegisterFlagCompletionFunc("role", util.ValidArgsNodeRoles); err != nil {
|
||||
l.Log().Fatalln("Failed to register flag completion for '--role'", err)
|
||||
}
|
||||
cmd.Flags().StringP("cluster", "c", k3d.DefaultClusterName, "Cluster URL or k3d cluster name to connect to.")
|
||||
if err := cmd.RegisterFlagCompletionFunc("cluster", util.ValidArgsAvailableClusters); err != nil {
|
||||
l.Log().Fatalln("Failed to register flag completion for '--cluster'", err)
|
||||
}
|
||||
|
||||
cmd.Flags().StringP("image", "i", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image used for the node(s)")
|
||||
cmd.Flags().String("memory", "", "Memory limit imposed on the node [From docker]")
|
||||
|
||||
cmd.Flags().BoolVar(&createNodeOpts.Wait, "wait", true, "Wait for the node(s) to be ready before returning.")
|
||||
cmd.Flags().DurationVar(&createNodeOpts.Timeout, "timeout", 0*time.Second, "Maximum waiting time for '--wait' before canceling/returning.")
|
||||
|
||||
cmd.Flags().StringSliceP("runtime-label", "", []string{}, "Specify container runtime labels in format \"foo=bar\"")
|
||||
cmd.Flags().StringSliceP("k3s-node-label", "", []string{}, "Specify k3s node labels in format \"foo=bar\"")
|
||||
|
||||
cmd.Flags().StringSliceP("network", "n", []string{}, "Add node to (another) runtime network")
|
||||
|
||||
cmd.Flags().StringVarP(&createNodeOpts.ClusterToken, "token", "t", "", "Override cluster token (required when connecting to an external cluster)")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseCreateNodeCmd parses the command input into variables required to create a node
|
||||
func parseCreateNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, string) {
|
||||
|
||||
// --replicas
|
||||
replicas, err := cmd.Flags().GetInt("replicas")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No replica count specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// --role
|
||||
roleStr, err := cmd.Flags().GetString("role")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No node role specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
if _, ok := k3d.NodeRoles[roleStr]; !ok {
|
||||
l.Log().Fatalf("Unknown node role '%s'\n", roleStr)
|
||||
}
|
||||
role := k3d.NodeRoles[roleStr]
|
||||
|
||||
// --image
|
||||
image, err := cmd.Flags().GetString("image")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No image specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// --cluster
|
||||
clusterName, err := cmd.Flags().GetString("cluster")
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// --memory
|
||||
memory, err := cmd.Flags().GetString("memory")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No memory specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
if _, err := dockerunits.RAMInBytes(memory); memory != "" && err != nil {
|
||||
l.Log().Errorf("Provided memory limit value is invalid")
|
||||
}
|
||||
|
||||
// --runtime-label
|
||||
runtimeLabelsFlag, err := cmd.Flags().GetStringSlice("runtime-label")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No runtime-label specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
runtimeLabels := make(map[string]string, len(runtimeLabelsFlag)+1)
|
||||
for _, label := range runtimeLabelsFlag {
|
||||
labelSplitted := strings.Split(label, "=")
|
||||
if len(labelSplitted) != 2 {
|
||||
l.Log().Fatalf("unknown runtime-label format format: %s, use format \"foo=bar\"", label)
|
||||
}
|
||||
cliutil.ValidateRuntimeLabelKey(labelSplitted[0])
|
||||
runtimeLabels[labelSplitted[0]] = labelSplitted[1]
|
||||
}
|
||||
|
||||
// Internal k3d runtime labels take precedence over user-defined labels
|
||||
runtimeLabels[k3d.LabelRole] = roleStr
|
||||
|
||||
// --k3s-node-label
|
||||
k3sNodeLabelsFlag, err := cmd.Flags().GetStringSlice("k3s-node-label")
|
||||
if err != nil {
|
||||
l.Log().Errorln("No k3s-node-label specified")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
k3sNodeLabels := make(map[string]string, len(k3sNodeLabelsFlag))
|
||||
for _, label := range k3sNodeLabelsFlag {
|
||||
labelSplitted := strings.Split(label, "=")
|
||||
if len(labelSplitted) != 2 {
|
||||
l.Log().Fatalf("unknown k3s-node-label format format: %s, use format \"foo=bar\"", label)
|
||||
}
|
||||
k3sNodeLabels[labelSplitted[0]] = labelSplitted[1]
|
||||
}
|
||||
|
||||
// --network
|
||||
networks, err := cmd.Flags().GetStringSlice("network")
|
||||
if err != nil {
|
||||
l.Log().Fatalf("failed to get --network string slice flag: %v", err)
|
||||
}
|
||||
|
||||
// generate list of nodes
|
||||
nodes := []*k3d.Node{}
|
||||
for i := 0; i < replicas; i++ {
|
||||
node := &k3d.Node{
|
||||
Name: fmt.Sprintf("%s-%s-%d", k3d.DefaultObjectNamePrefix, args[0], i),
|
||||
Role: role,
|
||||
Image: image,
|
||||
K3sNodeLabels: k3sNodeLabels,
|
||||
RuntimeLabels: runtimeLabels,
|
||||
Restart: true,
|
||||
Memory: memory,
|
||||
Networks: networks,
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return nodes, clusterName
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type nodeDeleteFlags struct {
|
||||
All bool
|
||||
IncludeRegistries bool
|
||||
}
|
||||
|
||||
// NewCmdNodeDelete returns a new cobra command
|
||||
func NewCmdNodeDelete() *cobra.Command {
|
||||
|
||||
flags := nodeDeleteFlags{}
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete (NAME | --all)",
|
||||
Short: "Delete node(s).",
|
||||
Long: `Delete node(s).`,
|
||||
ValidArgsFunction: util.ValidArgsAvailableNodes,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
nodes := parseDeleteNodeCmd(cmd, args, &flags)
|
||||
nodeDeleteOpts := k3d.NodeDeleteOpts{SkipLBUpdate: flags.All} // do not update LB, if we're deleting all nodes anyway
|
||||
|
||||
if len(nodes) == 0 {
|
||||
l.Log().Infoln("No nodes found")
|
||||
} else {
|
||||
for _, node := range nodes {
|
||||
if err := client.NodeDelete(cmd.Context(), runtimes.SelectedRuntime, node, nodeDeleteOpts); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
l.Log().Infof("Successfully deleted %d node(s)!", len(nodes))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolVarP(&flags.All, "all", "a", false, "Delete all existing nodes")
|
||||
cmd.Flags().BoolVarP(&flags.IncludeRegistries, "registries", "r", false, "Also delete registries")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseDeleteNodeCmd parses the command input into variables required to delete nodes
|
||||
func parseDeleteNodeCmd(cmd *cobra.Command, args []string, flags *nodeDeleteFlags) []*k3d.Node {
|
||||
|
||||
var nodes []*k3d.Node
|
||||
var err error
|
||||
|
||||
// --all
|
||||
if flags.All {
|
||||
if !flags.IncludeRegistries {
|
||||
l.Log().Infoln("Didn't set '--registries', so won't delete registries.")
|
||||
}
|
||||
nodes, err = client.NodeList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
include := k3d.ClusterInternalNodeRoles
|
||||
exclude := []k3d.Role{}
|
||||
if flags.IncludeRegistries {
|
||||
include = append(include, k3d.RegistryRole)
|
||||
}
|
||||
nodes = client.NodeFilterByRoles(nodes, include, exclude)
|
||||
return nodes
|
||||
}
|
||||
|
||||
if !flags.All && len(args) < 1 {
|
||||
l.Log().Fatalln("Expecting at least one node name if `--all` is not set")
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
node, err := client.NodeGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Node{Name: name})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdNodeEdit returns a new cobra command
|
||||
func NewCmdNodeEdit() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "edit NODE",
|
||||
Short: "[EXPERIMENTAL] Edit node(s).",
|
||||
Long: `[EXPERIMENTAL] Edit node(s).`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Aliases: []string{"update"},
|
||||
ValidArgsFunction: util.ValidArgsAvailableNodes,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
existingNode, changeset := parseEditNodeCmd(cmd, args)
|
||||
|
||||
l.Log().Debugf("===== Current =====\n%+v\n===== Changeset =====\n%+v\n", existingNode, changeset)
|
||||
|
||||
if err := client.NodeEdit(cmd.Context(), runtimes.SelectedRuntime, existingNode, changeset); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
l.Log().Infof("Successfully updated %s", existingNode.Name)
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
|
||||
// add flags
|
||||
cmd.Flags().StringArray("port-add", nil, "[EXPERIMENTAL] (serverlb only!) Map ports from the node container to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d node edit k3d-mycluster-serverlb --port-add 8080:80`")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseEditNodeCmd parses the command input into variables required to delete nodes
|
||||
func parseEditNodeCmd(cmd *cobra.Command, args []string) (*k3d.Node, *k3d.Node) {
|
||||
|
||||
existingNode, err := client.NodeGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Node{Name: args[0]})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
if existingNode == nil {
|
||||
l.Log().Infof("Node %s not found", args[0])
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if existingNode.Role != k3d.LoadBalancerRole {
|
||||
l.Log().Fatalln("Currently only the loadbalancer can be updated!")
|
||||
}
|
||||
|
||||
changeset := &k3d.Node{}
|
||||
|
||||
/*
|
||||
* --port-add
|
||||
*/
|
||||
portFlags, err := cmd.Flags().GetStringArray("port-add")
|
||||
if err != nil {
|
||||
l.Log().Errorln(err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// init portmap
|
||||
changeset.Ports = nat.PortMap{}
|
||||
|
||||
for _, flag := range portFlags {
|
||||
|
||||
portmappings, err := nat.ParsePortSpec(flag)
|
||||
if err != nil {
|
||||
l.Log().Fatalf("Failed to parse port spec '%s': %+v", flag, err)
|
||||
}
|
||||
|
||||
for _, pm := range portmappings {
|
||||
changeset.Ports[pm.Port] = append(changeset.Ports[pm.Port], pm.Binding)
|
||||
}
|
||||
}
|
||||
|
||||
return existingNode, changeset
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/liggitt/tabwriter"
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type nodeListFlags struct {
|
||||
noHeader bool
|
||||
output string
|
||||
}
|
||||
|
||||
// NewCmdNodeList returns a new cobra command
|
||||
func NewCmdNodeList() *cobra.Command {
|
||||
nodeListFlags := nodeListFlags{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "list [NODE [NODE...]]",
|
||||
Aliases: []string{"ls", "get"},
|
||||
Short: "List node(s)",
|
||||
Long: `List node(s).`,
|
||||
Args: cobra.MinimumNArgs(0), // 0 or more; 0 = all
|
||||
ValidArgsFunction: util.ValidArgsAvailableNodes,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
nodes := []*k3d.Node{}
|
||||
for _, name := range args {
|
||||
nodes = append(nodes, &k3d.Node{
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
var existingNodes []*k3d.Node
|
||||
if len(nodes) == 0 { // Option a) no name specified -> get all nodes
|
||||
found, err := client.NodeList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
existingNodes = append(existingNodes, found...)
|
||||
} else { // Option b) cluster name specified -> get specific cluster
|
||||
for _, node := range nodes {
|
||||
found, err := client.NodeGet(cmd.Context(), runtimes.SelectedRuntime, node)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
existingNodes = append(existingNodes, found)
|
||||
}
|
||||
}
|
||||
|
||||
// print existing nodes
|
||||
headers := &[]string{}
|
||||
if !nodeListFlags.noHeader {
|
||||
headers = &[]string{"NAME", "ROLE", "CLUSTER", "STATUS"}
|
||||
}
|
||||
|
||||
util.PrintNodes(existingNodes, nodeListFlags.output,
|
||||
headers, util.NodePrinterFunc(func(tabwriter *tabwriter.Writer, node *k3d.Node) {
|
||||
fmt.Fprintf(tabwriter, "%s\t%s\t%s\t%s\n",
|
||||
strings.TrimPrefix(node.Name, "/"),
|
||||
string(node.Role),
|
||||
node.RuntimeLabels[k3d.LabelClusterName],
|
||||
node.State.Status)
|
||||
}))
|
||||
},
|
||||
}
|
||||
// add flags
|
||||
cmd.Flags().BoolVar(&nodeListFlags.noHeader, "no-headers", false, "Disable headers")
|
||||
cmd.Flags().StringVarP(&nodeListFlags.output, "output", "o", "", "Output format. One of: json|yaml")
|
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdNodeStart returns a new cobra command
|
||||
func NewCmdNodeStart() *cobra.Command {
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "start NODE", // TODO: startNode: allow one or more names or --all
|
||||
Short: "Start an existing k3d node",
|
||||
Long: `Start an existing k3d node.`,
|
||||
ValidArgsFunction: util.ValidArgsAvailableNodes,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
node := parseStartNodeCmd(cmd, args)
|
||||
if err := runtimes.SelectedRuntime.StartNode(cmd.Context(), node); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseStartNodeCmd parses the command input into variables required to start a node
|
||||
func parseStartNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
|
||||
// node name // TODO: startNode: allow node filters, e.g. `k3d node start mycluster@agent` to start all agent nodes of cluster 'mycluster'
|
||||
if len(args) == 0 || len(args[0]) == 0 {
|
||||
l.Log().Fatalln("No node name given")
|
||||
}
|
||||
|
||||
return &k3d.Node{Name: args[0]}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 node
|
||||
|
||||
import (
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
)
|
||||
|
||||
// NewCmdNodeStop returns a new cobra command
|
||||
func NewCmdNodeStop() *cobra.Command {
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "stop NAME", // TODO: stopNode: allow one or more names or --all",
|
||||
Short: "Stop an existing k3d node",
|
||||
Long: `Stop an existing k3d node.`,
|
||||
ValidArgsFunction: util.ValidArgsAvailableNodes,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
node := parseStopNodeCmd(cmd, args)
|
||||
if err := runtimes.SelectedRuntime.StopNode(cmd.Context(), node); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseStopNodeCmd parses the command input into variables required to stop a node
|
||||
func parseStopNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
|
||||
// node name // TODO: allow node filters, e.g. `k3d node stop mycluster@agent` to stop all agent nodes of cluster 'mycluster'
|
||||
if len(args) == 0 || len(args[0]) == 0 {
|
||||
l.Log().Fatalln("No node name given")
|
||||
}
|
||||
|
||||
return &k3d.Node{Name: args[0]}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import (
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewCmdRegistry returns a new cobra command
|
||||
func NewCmdRegistry() *cobra.Command {
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "registry",
|
||||
Aliases: []string{"registries", "reg"},
|
||||
Short: "Manage registry/registries",
|
||||
Long: `Manage registry/registries`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := cmd.Help(); err != nil {
|
||||
l.Log().Errorln("Couldn't get help text")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
cmd.AddCommand(NewCmdRegistryCreate(),
|
||||
NewCmdRegistryStart(),
|
||||
NewCmdRegistryStop(),
|
||||
NewCmdRegistryDelete(),
|
||||
NewCmdRegistryList())
|
||||
|
||||
// add flags
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
|
||||
cliutil "github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type regCreatePreProcessedFlags struct {
|
||||
Port string
|
||||
Clusters []string
|
||||
}
|
||||
|
||||
type regCreateFlags struct {
|
||||
Image string
|
||||
NoHelp bool
|
||||
}
|
||||
|
||||
var helptext string = `# You can now use the registry like this (example):
|
||||
# 1. create a new cluster that uses this registry
|
||||
k3d cluster create --registry-use %s
|
||||
|
||||
# 2. tag an existing local image to be pushed to the registry
|
||||
docker tag nginx:latest %s/mynginx:v0.1
|
||||
|
||||
# 3. push that image to the registry
|
||||
docker push %s/mynginx:v0.1
|
||||
|
||||
# 4. run a pod that uses this image
|
||||
kubectl run mynginx --image %s/mynginx:v0.1
|
||||
`
|
||||
|
||||
// NewCmdRegistryCreate returns a new cobra command
|
||||
func NewCmdRegistryCreate() *cobra.Command {
|
||||
|
||||
flags := ®CreateFlags{}
|
||||
ppFlags := ®CreatePreProcessedFlags{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "create NAME",
|
||||
Short: "Create a new registry",
|
||||
Long: `Create a new registry.`,
|
||||
Args: cobra.MaximumNArgs(1), // maximum one name accepted
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
reg, clusters := parseCreateRegistryCmd(cmd, args, flags, ppFlags)
|
||||
regNode, err := client.RegistryRun(cmd.Context(), runtimes.SelectedRuntime, reg)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
if err := client.RegistryConnectClusters(cmd.Context(), runtimes.SelectedRuntime, regNode, clusters); err != nil {
|
||||
l.Log().Errorln(err)
|
||||
}
|
||||
l.Log().Infof("Successfully created registry '%s'", reg.Host)
|
||||
regString := fmt.Sprintf("%s:%s", reg.Host, reg.ExposureOpts.Binding.HostPort)
|
||||
if !flags.NoHelp {
|
||||
fmt.Println(fmt.Sprintf(helptext, regString, regString, regString, regString))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add flags
|
||||
|
||||
// TODO: connecting to clusters requires non-existing config reload functionality in containerd
|
||||
cmd.Flags().StringArrayVarP(&ppFlags.Clusters, "cluster", "c", nil, "[NotReady] Select the cluster(s) that the registry shall connect to.")
|
||||
if err := cmd.RegisterFlagCompletionFunc("cluster", cliutil.ValidArgsAvailableClusters); err != nil {
|
||||
l.Log().Fatalln("Failed to register flag completion for '--cluster'", err)
|
||||
}
|
||||
if err := cmd.Flags().MarkHidden("cluster"); err != nil {
|
||||
l.Log().Fatalln("Failed to hide --cluster flag on registry create command")
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&flags.Image, "image", "i", fmt.Sprintf("%s:%s", k3d.DefaultRegistryImageRepo, k3d.DefaultRegistryImageTag), "Specify image used for the registry")
|
||||
|
||||
cmd.Flags().StringVarP(&ppFlags.Port, "port", "p", "random", "Select which port the registry should be listening on on your machine (localhost) (Format: `[HOST:]HOSTPORT`)\n - Example: `k3d registry create --port 0.0.0.0:5111`")
|
||||
|
||||
cmd.Flags().BoolVar(&flags.NoHelp, "no-help", false, "Disable the help text (How-To use the registry)")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseCreateRegistryCmd parses the command input into variables required to create a registry
|
||||
func parseCreateRegistryCmd(cmd *cobra.Command, args []string, flags *regCreateFlags, ppFlags *regCreatePreProcessedFlags) (*k3d.Registry, []*k3d.Cluster) {
|
||||
|
||||
// --cluster
|
||||
clusters := []*k3d.Cluster{}
|
||||
for _, name := range ppFlags.Clusters {
|
||||
clusters = append(clusters,
|
||||
&k3d.Cluster{
|
||||
Name: name,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// --port
|
||||
exposePort, err := cliutil.ParsePortExposureSpec(ppFlags.Port, k3d.DefaultRegistryPort)
|
||||
if err != nil {
|
||||
l.Log().Errorln("Failed to parse registry port")
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
|
||||
// set the name for the registry node
|
||||
registryName := ""
|
||||
if len(args) > 0 {
|
||||
registryName = fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, args[0])
|
||||
}
|
||||
|
||||
return &k3d.Registry{Host: registryName, Image: flags.Image, ExposureOpts: *exposePort}, clusters
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import (
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type registryDeleteFlags struct {
|
||||
All bool
|
||||
}
|
||||
|
||||
// NewCmdRegistryDelete returns a new cobra command
|
||||
func NewCmdRegistryDelete() *cobra.Command {
|
||||
|
||||
flags := registryDeleteFlags{}
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete (NAME | --all)",
|
||||
Short: "Delete registry/registries.",
|
||||
Long: `Delete registry/registries.`,
|
||||
Aliases: []string{"del", "rm"},
|
||||
ValidArgsFunction: util.ValidArgsAvailableRegistries,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
nodes := parseRegistryDeleteCmd(cmd, args, &flags)
|
||||
|
||||
if len(nodes) == 0 {
|
||||
l.Log().Infoln("No registries found")
|
||||
} else {
|
||||
for _, node := range nodes {
|
||||
if err := client.NodeDelete(cmd.Context(), runtimes.SelectedRuntime, node, k3d.NodeDeleteOpts{SkipLBUpdate: true}); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// add subcommands
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolVarP(&flags.All, "all", "a", false, "Delete all existing registries")
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
||||
|
||||
// parseRegistryDeleteCmd parses the command input into variables required to delete nodes
|
||||
func parseRegistryDeleteCmd(cmd *cobra.Command, args []string, flags *registryDeleteFlags) []*k3d.Node {
|
||||
|
||||
var nodes []*k3d.Node
|
||||
var err error
|
||||
|
||||
if flags.All {
|
||||
nodes, err = client.NodeList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
if !flags.All && len(args) < 1 {
|
||||
l.Log().Fatalln("Expecting at least one registry name if `--all` is not set")
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
node, err := client.NodeGet(cmd.Context(), runtimes.SelectedRuntime, &k3d.Node{Name: name})
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
nodes = client.NodeFilterByRoles(nodes, []k3d.Role{k3d.RegistryRole}, []k3d.Role{})
|
||||
|
||||
return nodes
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/liggitt/tabwriter"
|
||||
"github.com/rancher/k3d/v5/cmd/util"
|
||||
"github.com/rancher/k3d/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type registryListFlags struct {
|
||||
noHeader bool
|
||||
output string
|
||||
}
|
||||
|
||||
// NewCmdRegistryList creates a new cobra command
|
||||
func NewCmdRegistryList() *cobra.Command {
|
||||
registryListFlags := registryListFlags{}
|
||||
|
||||
// create new command
|
||||
cmd := &cobra.Command{
|
||||
Use: "list [NAME [NAME...]]",
|
||||
Aliases: []string{"ls", "get"},
|
||||
Short: "List registries",
|
||||
Long: `List registries.`,
|
||||
Args: cobra.MinimumNArgs(0), // 0 or more; 0 = all
|
||||
ValidArgsFunction: util.ValidArgsAvailableRegistries,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var existingNodes []*k3d.Node
|
||||
|
||||
nodes := []*k3d.Node{}
|
||||
for _, name := range args {
|
||||
nodes = append(nodes, &k3d.Node{
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
|
||||
if len(nodes) == 0 { // Option a) no name specified -> get all registries
|
||||
found, err := client.NodeList(cmd.Context(), runtimes.SelectedRuntime)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
existingNodes = append(existingNodes, found...)
|
||||
} else { // Option b) registry name(s) specified -> get specific registries
|
||||
for _, node := range nodes {
|
||||
l.Log().Tracef("Node %s", node.Name)
|
||||
found, err := client.NodeGet(cmd.Context(), runtimes.SelectedRuntime, node)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
existingNodes = append(existingNodes, found)
|
||||
}
|
||||
}
|
||||
existingNodes = client.NodeFilterByRoles(existingNodes, []k3d.Role{k3d.RegistryRole}, []k3d.Role{})
|
||||
|
||||
// print existing registries
|
||||
headers := &[]string{}
|
||||
if !registryListFlags.noHeader {
|
||||
headers = &[]string{"NAME", "ROLE", "CLUSTER", "STATUS"}
|
||||
}
|
||||
|
||||
util.PrintNodes(existingNodes, registryListFlags.output,
|
||||
headers, util.NodePrinterFunc(func(tabwriter *tabwriter.Writer, node *k3d.Node) {
|
||||
cluster := "*"
|
||||
if _, ok := node.RuntimeLabels[k3d.LabelClusterName]; ok {
|
||||
cluster = node.RuntimeLabels[k3d.LabelClusterName]
|
||||
}
|
||||
fmt.Fprintf(tabwriter, "%s\t%s\t%s\t%s\n",
|
||||
strings.TrimPrefix(node.Name, "/"),
|
||||
string(node.Role),
|
||||
cluster,
|
||||
node.State.Status,
|
||||
)
|
||||
}),
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
// add flags
|
||||
cmd.Flags().BoolVar(®istryListFlags.noHeader, "no-headers", false, "Disable headers")
|
||||
cmd.Flags().StringVarP(®istryListFlags.output, "output", "o", "", "Output format. One of: json|yaml")
|
||||
|
||||
// add subcommands
|
||||
|
||||
// done
|
||||
return cmd
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
// NewCmdRegistryStart creates a new cobra command
|
||||
func NewCmdRegistryStart() *cobra.Command {
|
||||
return &cobra.Command{}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 registry
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
// NewCmdRegistryStop creates a new cobra command
|
||||
func NewCmdRegistryStop() *cobra.Command {
|
||||
return &cobra.Command{}
|
||||
}
|
295
cmd/root.go
295
cmd/root.go
@ -1,295 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/rancher/k3d/v5/cmd/cluster"
|
||||
cfg "github.com/rancher/k3d/v5/cmd/config"
|
||||
"github.com/rancher/k3d/v5/cmd/debug"
|
||||
"github.com/rancher/k3d/v5/cmd/image"
|
||||
"github.com/rancher/k3d/v5/cmd/kubeconfig"
|
||||
"github.com/rancher/k3d/v5/cmd/node"
|
||||
"github.com/rancher/k3d/v5/cmd/registry"
|
||||
cliutil "github.com/rancher/k3d/v5/cmd/util"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
"github.com/rancher/k3d/v5/version"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/writer"
|
||||
)
|
||||
|
||||
// RootFlags describes a struct that holds flags that can be set on root level of the command
|
||||
type RootFlags struct {
|
||||
debugLogging bool
|
||||
traceLogging bool
|
||||
timestampedLogging bool
|
||||
version bool
|
||||
}
|
||||
|
||||
var flags = RootFlags{}
|
||||
|
||||
func NewCmdK3d() *cobra.Command {
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "k3d",
|
||||
Short: "https://k3d.io/ -> Run k3s in Docker!",
|
||||
Long: `https://k3d.io/
|
||||
k3d is a wrapper CLI that helps you to easily create k3s clusters inside docker.
|
||||
Nodes of a k3d cluster are docker containers running a k3s image.
|
||||
All Nodes of a k3d cluster are part of the same docker network.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if flags.version {
|
||||
printVersion()
|
||||
} else {
|
||||
if err := cmd.Usage(); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.debugLogging, "verbose", false, "Enable verbose output (debug logging)")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.traceLogging, "trace", false, "Enable super verbose output (trace logging)")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.timestampedLogging, "timestamps", false, "Enable Log timestamps")
|
||||
|
||||
// add local flags
|
||||
rootCmd.Flags().BoolVar(&flags.version, "version", false, "Show k3d and default k3s version")
|
||||
|
||||
// add subcommands
|
||||
rootCmd.AddCommand(NewCmdCompletion(rootCmd),
|
||||
cluster.NewCmdCluster(),
|
||||
kubeconfig.NewCmdKubeconfig(),
|
||||
node.NewCmdNode(),
|
||||
image.NewCmdImage(),
|
||||
cfg.NewCmdConfig(),
|
||||
registry.NewCmdRegistry(),
|
||||
debug.NewCmdDebug(),
|
||||
&cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Show k3d and default k3s version",
|
||||
Long: "Show k3d and default k3s version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
printVersion()
|
||||
},
|
||||
},
|
||||
&cobra.Command{
|
||||
Use: "runtime-info",
|
||||
Short: "Show runtime information",
|
||||
Long: "Show some information about the runtime environment (e.g. docker info)",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
info, err := runtimes.SelectedRuntime.Info()
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
err = yaml.NewEncoder(os.Stdout).Encode(info)
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
},
|
||||
Hidden: true,
|
||||
})
|
||||
|
||||
// Init
|
||||
cobra.OnInitialize(initLogging, initRuntime)
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
cmd := NewCmdK3d()
|
||||
if len(os.Args) > 1 {
|
||||
parts := os.Args[1:]
|
||||
// Check if it's a built-in command, else try to execute it as a plugin
|
||||
if _, _, err := cmd.Find(parts); err != nil {
|
||||
pluginFound, err := cliutil.HandlePlugin(context.Background(), parts)
|
||||
if err != nil {
|
||||
l.Log().Errorf("Failed to execute plugin '%+v'", parts)
|
||||
l.Log().Fatalln(err)
|
||||
} else if pluginFound {
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := cmd.Execute(); err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
// initLogging initializes the logger
|
||||
func initLogging() {
|
||||
if flags.traceLogging {
|
||||
l.Log().SetLevel(logrus.TraceLevel)
|
||||
} else if flags.debugLogging {
|
||||
l.Log().SetLevel(logrus.DebugLevel)
|
||||
} else {
|
||||
switch logLevel := strings.ToUpper(os.Getenv("LOG_LEVEL")); logLevel {
|
||||
case "TRACE":
|
||||
l.Log().SetLevel(logrus.TraceLevel)
|
||||
case "DEBUG":
|
||||
l.Log().SetLevel(logrus.DebugLevel)
|
||||
case "WARN":
|
||||
l.Log().SetLevel(logrus.WarnLevel)
|
||||
case "ERROR":
|
||||
l.Log().SetLevel(logrus.ErrorLevel)
|
||||
default:
|
||||
l.Log().SetLevel(logrus.InfoLevel)
|
||||
}
|
||||
}
|
||||
l.Log().SetOutput(io.Discard)
|
||||
l.Log().AddHook(&writer.Hook{
|
||||
Writer: os.Stderr,
|
||||
LogLevels: []logrus.Level{
|
||||
logrus.PanicLevel,
|
||||
logrus.FatalLevel,
|
||||
logrus.ErrorLevel,
|
||||
logrus.WarnLevel,
|
||||
},
|
||||
})
|
||||
l.Log().AddHook(&writer.Hook{
|
||||
Writer: os.Stdout,
|
||||
LogLevels: []logrus.Level{
|
||||
logrus.InfoLevel,
|
||||
logrus.DebugLevel,
|
||||
logrus.TraceLevel,
|
||||
},
|
||||
})
|
||||
|
||||
formatter := &logrus.TextFormatter{
|
||||
ForceColors: true,
|
||||
}
|
||||
|
||||
if flags.timestampedLogging || os.Getenv("LOG_TIMESTAMPS") != "" {
|
||||
formatter.FullTimestamp = true
|
||||
}
|
||||
|
||||
l.Log().SetFormatter(formatter)
|
||||
|
||||
}
|
||||
|
||||
func initRuntime() {
|
||||
runtime, err := runtimes.GetRuntime("docker")
|
||||
if err != nil {
|
||||
l.Log().Fatalln(err)
|
||||
}
|
||||
runtimes.SelectedRuntime = runtime
|
||||
if rtinfo, err := runtime.Info(); err == nil {
|
||||
l.Log().Debugf("Runtime Info:\n%+v", rtinfo)
|
||||
}
|
||||
}
|
||||
|
||||
func printVersion() {
|
||||
fmt.Printf("k3d version %s\n", version.GetVersion())
|
||||
fmt.Printf("k3s version %s (default)\n", version.K3sVersion)
|
||||
}
|
||||
|
||||
// NewCmdCompletion creates a new completion command
|
||||
func NewCmdCompletion(rootCmd *cobra.Command) *cobra.Command {
|
||||
|
||||
completionFunctions := map[string]func(io.Writer) error{
|
||||
"bash": rootCmd.GenBashCompletion,
|
||||
"zsh": func(writer io.Writer) error {
|
||||
if err := rootCmd.GenZshCompletion(writer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(writer, "\n# source completion file\ncompdef _k3d k3d\n")
|
||||
|
||||
return nil
|
||||
},
|
||||
"psh": rootCmd.GenPowerShellCompletion,
|
||||
"powershell": rootCmd.GenPowerShellCompletionWithDesc,
|
||||
"fish": func(writer io.Writer) error {
|
||||
return rootCmd.GenFishCompletion(writer, true)
|
||||
},
|
||||
}
|
||||
|
||||
// create new cobra command
|
||||
cmd := &cobra.Command{
|
||||
Use: "completion SHELL",
|
||||
Short: "Generate completion scripts for [bash, zsh, fish, powershell | psh]",
|
||||
Long: `To load completions:
|
||||
|
||||
Bash:
|
||||
|
||||
$ source <(k3d completion bash)
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
# Linux:
|
||||
$ k3d completion bash > /etc/bash_completion.d/k3d
|
||||
# macOS:
|
||||
$ k3d completion bash > /usr/local/etc/bash_completion.d/k3d
|
||||
|
||||
Zsh:
|
||||
|
||||
# If shell completion is not already enabled in your environment,
|
||||
# you will need to enable it. You can execute the following once:
|
||||
|
||||
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ k3d completion zsh > "${fpath[1]}/k3d"
|
||||
|
||||
# You will need to start a new shell for this setup to take effect.
|
||||
|
||||
fish:
|
||||
|
||||
$ k3d completion fish | source
|
||||
|
||||
# To load completions for each session, execute once:
|
||||
$ k3d completion fish > ~/.config/fish/completions/k3d.fish
|
||||
|
||||
PowerShell:
|
||||
|
||||
PS> k3d completion powershell | Out-String | Invoke-Expression
|
||||
|
||||
# To load completions for every new session, run:
|
||||
PS> k3d completion powershell > k3d.ps1
|
||||
# and source this file from your PowerShell profile.
|
||||
`,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
ArgAliases: []string{"psh"},
|
||||
DisableFlagsInUseLine: true,
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if completionFunc, ok := completionFunctions[args[0]]; ok {
|
||||
if err := completionFunc(os.Stdout); err != nil {
|
||||
l.Log().Fatalf("Failed to generate completion script for shell '%s'", args[0])
|
||||
}
|
||||
return
|
||||
}
|
||||
l.Log().Fatalf("Shell '%s' not supported for completion", args[0])
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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/v5/pkg/client"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"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 {
|
||||
l.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 {
|
||||
l.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 nodes, that are not in the args yet
|
||||
continue nodeLoop
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(node.Name, toComplete) {
|
||||
completions = append(completions, node.Name)
|
||||
}
|
||||
}
|
||||
return completions, cobra.ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
// ValidArgsAvailableRegistries is used for shell completions: proposes the list of existing registries
|
||||
func ValidArgsAvailableRegistries(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 {
|
||||
l.Log().Errorln("Failed to get list of nodes for shell completion")
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
nodes = k3dcluster.NodeFilterByRoles(nodes, []k3d.Role{k3d.RegistryRole}, []k3d.Role{})
|
||||
|
||||
nodeLoop:
|
||||
for _, node := range nodes {
|
||||
for _, arg := range args {
|
||||
if arg == node.Name { // only nodes, 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,97 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/k3d/v5/pkg/config"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func InitViperWithConfigFile(cfgViper *viper.Viper, configFile string) error {
|
||||
|
||||
// viper for the general config (file, env and non pre-processed flags)
|
||||
cfgViper.SetEnvPrefix("K3D")
|
||||
cfgViper.AutomaticEnv()
|
||||
|
||||
cfgViper.SetConfigType("yaml")
|
||||
|
||||
// Set config file, if specified
|
||||
if configFile != "" {
|
||||
|
||||
if _, err := os.Stat(configFile); err != nil {
|
||||
l.Log().Fatalf("Failed to stat config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
// create temporary file to expand environment variables in the config without writing that back to the original file
|
||||
// we're doing it here, because this happens just before absolutely all other processing
|
||||
tmpfile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("k3d-config-tmp-%s", filepath.Base(configFile)))
|
||||
if err != nil {
|
||||
l.Log().Fatalf("error creating temp copy of configfile %s for variable expansion: %v", configFile, err)
|
||||
}
|
||||
defer tmpfile.Close()
|
||||
|
||||
originalcontent, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
l.Log().Fatalf("error reading config file %s: %v", configFile, err)
|
||||
}
|
||||
expandedcontent := os.ExpandEnv(string(originalcontent))
|
||||
if _, err := tmpfile.WriteString(expandedcontent); err != nil {
|
||||
l.Log().Fatalf("error writing expanded config file contents to temp file %s: %v", tmpfile.Name(), err)
|
||||
}
|
||||
|
||||
// use temp file with expanded variables
|
||||
cfgViper.SetConfigFile(tmpfile.Name())
|
||||
|
||||
// try to read config into memory (viper map structure)
|
||||
if err := cfgViper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
l.Log().Fatalf("Config file %s not found: %+v", configFile, err)
|
||||
}
|
||||
// config file found but some other error happened
|
||||
l.Log().Fatalf("Failed to read config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
schema, err := config.GetSchemaByVersion(cfgViper.GetString("apiVersion"))
|
||||
if err != nil {
|
||||
l.Log().Fatalf("Cannot validate config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
if err := config.ValidateSchemaFile(tmpfile.Name(), schema); err != nil {
|
||||
l.Log().Fatalf("Schema Validation failed for config file %s: %+v", configFile, err)
|
||||
}
|
||||
|
||||
l.Log().Infof("Using config file %s (%s#%s)", configFile, strings.ToLower(cfgViper.GetString("apiVersion")), strings.ToLower(cfgViper.GetString("kind")))
|
||||
}
|
||||
if l.Log().GetLevel() >= logrus.DebugLevel {
|
||||
c, _ := yaml.Marshal(cfgViper.AllSettings())
|
||||
l.Log().Debugf("Configuration:\n%s", c)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
)
|
||||
|
||||
// SplitFiltersFromFlag separates a flag's value from the node filter, if there is one
|
||||
func SplitFiltersFromFlag(flag string) (string, []string, error) {
|
||||
|
||||
/* Case 1) no filter specified */
|
||||
|
||||
if !strings.Contains(flag, "@") {
|
||||
return flag, nil, nil
|
||||
}
|
||||
|
||||
/* Case 2) filter indicated using '@' in flag */
|
||||
|
||||
split := strings.Split(flag, "@")
|
||||
newsplit := []string{}
|
||||
buffer := ""
|
||||
|
||||
for i, it := range split {
|
||||
|
||||
// Case 1: There's a '\' just before the '@' sign -> Should it be escaped (aka be a literal '@')?
|
||||
if strings.HasSuffix(it, "\\") && i != len(split)-1 {
|
||||
// Case 1.1: Escaped backslash
|
||||
if strings.HasSuffix(it, "\\\\") {
|
||||
it = strings.TrimSuffix(it, "\\")
|
||||
l.Log().Warnf("The part '%s' of the flag input '%s' ends with a double backslash, so we assume you want to escape the backslash before the '@'. That's the only time we do this.", it, flag)
|
||||
} else {
|
||||
// Case 1.2: Unescaped backslash -> Escaping the '@' -> remove suffix and append it to buffer, followed by the escaped @ sign
|
||||
l.Log().Tracef("Item '%s' just before an '@' ends with '\\', so we assume it's escaping a literal '@'", it)
|
||||
buffer += strings.TrimSuffix(it, "\\") + "@"
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Case 2: There's no '\': append item to buffer, save it to new slice, empty buffer and continue
|
||||
newsplit = append(newsplit, buffer+it)
|
||||
buffer = ""
|
||||
continue
|
||||
}
|
||||
|
||||
// max number of pieces after split = 2 (only one @ allowed in flag)
|
||||
if len(newsplit) > 2 {
|
||||
return "", nil, fmt.Errorf("Invalid flag '%s': only one unescaped '@' allowed for node filter(s) (Escape literal '@' with '\\')", flag)
|
||||
}
|
||||
|
||||
// trailing or leading '@'
|
||||
if len(newsplit) < 2 {
|
||||
return "", nil, fmt.Errorf("Invalid flag '%s' includes unescaped '@' but is missing a node filter (Escape literal '@' with '\\')", flag)
|
||||
}
|
||||
|
||||
return newsplit[0], strings.Split(newsplit[1], ";"), nil
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/liggitt/tabwriter"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type NodePrinter interface {
|
||||
Print(*tabwriter.Writer, *k3d.Node)
|
||||
}
|
||||
|
||||
type NodePrinterFunc func(*tabwriter.Writer, *k3d.Node)
|
||||
|
||||
func (npf NodePrinterFunc) Print(writter *tabwriter.Writer, node *k3d.Node) {
|
||||
npf(writter, node)
|
||||
}
|
||||
|
||||
// PrintNodes prints a list of nodes, either as a table or as a JSON/YAML listing
|
||||
func PrintNodes(nodes []*k3d.Node, outputFormat string, headers *[]string, nodePrinter NodePrinter) {
|
||||
outputFormat = strings.ToLower(outputFormat)
|
||||
|
||||
tabwriter := tabwriter.NewWriter(os.Stdout, 6, 4, 3, ' ', tabwriter.RememberWidths)
|
||||
defer tabwriter.Flush()
|
||||
|
||||
if outputFormat != "json" && outputFormat != "yaml" {
|
||||
if headers != nil {
|
||||
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(*headers, "\t"))
|
||||
if err != nil {
|
||||
l.Log().Fatalln("Failed to print headers")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(nodes, func(i, j int) bool {
|
||||
return nodes[i].Name < nodes[j].Name
|
||||
})
|
||||
|
||||
if outputFormat == "json" || outputFormat == "yaml" {
|
||||
var b []byte
|
||||
var err error
|
||||
|
||||
switch outputFormat {
|
||||
case "json":
|
||||
b, err = json.Marshal(nodes)
|
||||
case "yaml":
|
||||
b, err = yaml.Marshal(nodes)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
} else {
|
||||
for _, node := range nodes {
|
||||
if !(outputFormat == "json" || outputFormat == "yaml") {
|
||||
nodePrinter.Print(tabwriter, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
)
|
||||
|
||||
// HandlePlugin takes care of finding and executing a plugin based on the longest prefix
|
||||
func HandlePlugin(ctx context.Context, args []string) (bool, error) {
|
||||
argsPrefix := []string{}
|
||||
|
||||
for _, arg := range args {
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
continue // drop flags
|
||||
}
|
||||
argsPrefix = append(argsPrefix, strings.ReplaceAll(arg, "-", "_")) // plugin executables assumed to have underscores
|
||||
}
|
||||
|
||||
execPath := ""
|
||||
|
||||
for len(argsPrefix) > 0 {
|
||||
path, found := FindPlugin(strings.Join(argsPrefix, "-"))
|
||||
|
||||
if !found {
|
||||
argsPrefix = argsPrefix[:len(argsPrefix)-1] // drop last element
|
||||
continue
|
||||
}
|
||||
|
||||
execPath = path
|
||||
break
|
||||
}
|
||||
|
||||
if execPath == "" {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, ExecPlugin(ctx, execPath, args[len(argsPrefix):], os.Environ())
|
||||
|
||||
}
|
||||
|
||||
// FindPlugin tries to find the plugin executable on the filesystem
|
||||
func FindPlugin(name string) (string, bool) {
|
||||
path, err := exec.LookPath(fmt.Sprintf("%s-%s", k3d.DefaultObjectNamePrefix, name))
|
||||
if err == nil && len(path) > 0 {
|
||||
return path, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// ExecPlugin executes a found plugin
|
||||
func ExecPlugin(ctx context.Context, path string, args []string, env []string) error {
|
||||
cmd := exec.CommandContext(ctx, path, args...)
|
||||
cmd.Env = env
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
return cmd.Run()
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
k3d "github.com/rancher/k3d/v5/pkg/types"
|
||||
"github.com/rancher/k3d/v5/pkg/util"
|
||||
)
|
||||
|
||||
var apiPortRegexp = regexp.MustCompile(`^(?P<hostref>(?P<hostip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?P<hostname>\S+):)?(?P<port>(\d{1,5}|random))$`)
|
||||
|
||||
// ParsePortExposureSpec parses/validates a string to create an exposePort struct from it
|
||||
func ParsePortExposureSpec(exposedPortSpec, internalPort string) (*k3d.ExposureOpts, error) {
|
||||
|
||||
match := apiPortRegexp.FindStringSubmatch(exposedPortSpec)
|
||||
|
||||
if len(match) == 0 {
|
||||
return nil, fmt.Errorf("Failed to parse Port Exposure specification '%s': Format must be [(HostIP|HostName):]HostPort", exposedPortSpec)
|
||||
}
|
||||
|
||||
submatches := util.MapSubexpNames(apiPortRegexp.SubexpNames(), match)
|
||||
|
||||
// no port specified (or not matched via regex)
|
||||
if submatches["port"] == "" {
|
||||
return nil, fmt.Errorf("Failed to find port in Port Exposure spec '%s'", exposedPortSpec)
|
||||
}
|
||||
|
||||
api := &k3d.ExposureOpts{}
|
||||
|
||||
// check if there's a host reference
|
||||
if submatches["hostname"] != "" {
|
||||
l.Log().Tracef("Port Exposure: found hostname: %s", submatches["hostname"])
|
||||
addrs, err := net.LookupHost(submatches["hostname"])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to lookup host '%s' specified for Port Exposure: %+v", submatches["hostname"], err)
|
||||
}
|
||||
api.Host = submatches["hostname"]
|
||||
submatches["hostip"] = addrs[0] // set hostip to the resolved address
|
||||
}
|
||||
|
||||
realPortString := ""
|
||||
|
||||
if submatches["hostip"] == "" {
|
||||
submatches["hostip"] = k3d.DefaultAPIHost
|
||||
}
|
||||
|
||||
// start with the IP, if there is any
|
||||
if submatches["hostip"] != "" {
|
||||
realPortString += submatches["hostip"] + ":"
|
||||
}
|
||||
|
||||
// port: get a free one if there's none defined or set to random
|
||||
if submatches["port"] == "" || submatches["port"] == "random" {
|
||||
l.Log().Debugf("Port Exposure Mapping didn't specify hostPort, choosing one randomly...")
|
||||
freePort, err := GetFreePort()
|
||||
if err != nil || freePort == 0 {
|
||||
l.Log().Warnf("Failed to get random free port: %+v", err)
|
||||
l.Log().Warnf("Falling back to internal port %s (may be blocked though)...", internalPort)
|
||||
submatches["port"] = internalPort
|
||||
} else {
|
||||
submatches["port"] = strconv.Itoa(freePort)
|
||||
l.Log().Debugf("Got free port for Port Exposure: '%d'", freePort)
|
||||
}
|
||||
}
|
||||
|
||||
realPortString += fmt.Sprintf("%s:%s/tcp", submatches["port"], internalPort)
|
||||
|
||||
portMapping, err := nat.ParsePortSpec(realPortString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse port spec for Port Exposure '%s': %+v", realPortString, err)
|
||||
}
|
||||
|
||||
api.Port = portMapping[0].Port // there can be only one due to our regexp
|
||||
api.Binding = portMapping[0].Binding
|
||||
|
||||
return api, nil
|
||||
|
||||
}
|
||||
|
||||
// ValidatePortMap validates a port mapping
|
||||
func ValidatePortMap(portmap string) (string, error) {
|
||||
return portmap, nil // TODO: ValidatePortMap: add validation of port mapping
|
||||
}
|
||||
|
||||
// GetFreePort tries to fetch an open port from the OS-Kernel
|
||||
func GetFreePort() (int, error) {
|
||||
tcpAddress, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to resolve address 'localhost:0': %w", err)
|
||||
}
|
||||
|
||||
tcpListener, err := net.ListenTCP("tcp", tcpAddress)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to create tcp listener: %w", err)
|
||||
}
|
||||
defer tcpListener.Close()
|
||||
|
||||
return tcpListener.Addr().(*net.TCPAddr).Port, nil
|
||||
}
|
@ -1,35 +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 util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
)
|
||||
|
||||
// validateRuntimeLabelKey validates a given label key is not reserved for internal k3d usage
|
||||
func ValidateRuntimeLabelKey(labelKey string) {
|
||||
if strings.HasPrefix(labelKey, "k3s.") || strings.HasPrefix(labelKey, "k3d.") || labelKey == "app" {
|
||||
l.Log().Fatalf("runtime label \"%s\" is reserved for internal usage", labelKey)
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 "strings"
|
||||
|
||||
// SplitKV splits an '='-delimited string into a key-value-pair (if any)
|
||||
func SplitKV(kvstring string) (string, string) {
|
||||
// split only on first '=' sign (like `docker run` do)
|
||||
kvSlice := strings.SplitN(kvstring, "=", 2)
|
||||
|
||||
if len(kvSlice) > 1 {
|
||||
return kvSlice[0], kvSlice[1]
|
||||
}
|
||||
|
||||
// defaults to key with empty value (like `docker run` do)
|
||||
return kvstring, ""
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
Copyright © 2020-2021 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
rt "runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/k3d/v5/pkg/runtimes"
|
||||
|
||||
l "github.com/rancher/k3d/v5/pkg/logger"
|
||||
)
|
||||
|
||||
// ValidateVolumeMount checks, if the source of volume mounts exists and if the destination is an absolute path
|
||||
// - SRC: source directory/file -> tests: must exist
|
||||
// - DEST: source directory/file -> tests: must be absolute path
|
||||
// ValidateVolumeMount checks, if the source of volume mounts exists and if the destination is an absolute path
|
||||
// - SRC: source directory/file -> tests: must exist
|
||||
// - DEST: source directory/file -> tests: must be absolute path
|
||||
func ValidateVolumeMount(runtime runtimes.Runtime, volumeMount string) (string, error) {
|
||||
src := ""
|
||||
dest := ""
|
||||
|
||||
// validate 'SRC[:DEST]' substring
|
||||
split := strings.Split(volumeMount, ":")
|
||||
// a volume mapping can have 3 parts seperated by a ':' followed by a node filter
|
||||
// [SOURCE:]DEST[:OPT[,OPT]][@NODEFILTER[;NODEFILTER...]]
|
||||
// On Windows the source path needs to be an absolute path which means the path starts with
|
||||
// a drive designator and will also have a ':' in it. So for Windows the maxParts is increased by one.
|
||||
maxParts := 3
|
||||
if rt.GOOS == "windows" {
|
||||
maxParts++
|
||||
}
|
||||
if len(split) < 1 {
|
||||
return "", fmt.Errorf("No volume/path specified")
|
||||
}
|
||||
if len(split) > maxParts {
|
||||
return "", fmt.Errorf("Invalid volume mount '%s': maximal %d ':' allowed", volumeMount, maxParts-1)
|
||||
}
|
||||
|
||||
// we only have SRC specified -> DEST = SRC
|
||||
// On windows the first part of the SRC is the drive letter, so we need to concat the first and second parts to get the path.
|
||||
if len(split) == 1 {
|
||||
src = split[0]
|
||||
dest = src
|
||||
} else if rt.GOOS == "windows" {
|
||||
src = split[0] + ":" + split[1]
|
||||
dest = split[2]
|
||||
} else {
|
||||
src = split[0]
|
||||
dest = split[1]
|
||||
}
|
||||
|
||||
// verify that the source exists
|
||||
if src != "" {
|
||||
// a) named volume
|
||||
isNamedVolume := true
|
||||
if err := verifyNamedVolume(runtime, src); err != nil {
|
||||
isNamedVolume = false
|
||||
}
|
||||
if !isNamedVolume {
|
||||
if _, err := os.Stat(src); err != nil {
|
||||
l.Log().Warnf("Failed to stat file/directory/named volume that you're trying to mount: '%s' in '%s' -> Please make sure it exists", src, volumeMount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the destination is an absolute path
|
||||
if !strings.HasPrefix(dest, "/") {
|
||||
return "", fmt.Errorf("Volume mount destination doesn't appear to be an absolute path: '%s' in '%s'", dest, volumeMount)
|
||||
}
|
||||
|
||||
return volumeMount, nil
|
||||
}
|
||||
|
||||
// verifyNamedVolume checks whether a named volume exists in the runtime
|
||||
func verifyNamedVolume(runtime runtimes.Runtime, volumeName string) error {
|
||||
volumeName, err := runtime.GetVolume(volumeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to verify named volume: %w", err)
|
||||
}
|
||||
if volumeName == "" {
|
||||
return fmt.Errorf("Failed to find named volume '%s'", volumeName)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Setup base system
|
||||
pacman -Syu --noconfirm openssh git gettext binutils
|
||||
sed -i "s/INTEGRITY_CHECK=.*$/INTEGRITY_CHECK=(sha256)/" /etc/makepkg.conf
|
||||
useradd -ms /bin/bash aur
|
||||
su -m aur <<'EOSU'
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
export HOME=/home/aur
|
||||
export REPO_URL="ssh://aur@aur.archlinux.org/$PACKAGE_NAME.git"
|
||||
export NEW_RELEASE="${COMMIT_REF##*/v}"
|
||||
export COMMIT_MESSAGE="$(echo $COMMIT_MESSAGE | envsubst)"
|
||||
echo "---------------- AUR Package version $PACKAGE_NAME/$NEW_RELEASE ----------------"
|
||||
|
||||
# SSH & GIT Setup
|
||||
mkdir "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
|
||||
ssh-keyscan -t ed25519 aur.archlinux.org >> "$HOME/.ssh/known_hosts"
|
||||
echo -e "$SSH_PRIVATE_KEY" | base64 -d > "$HOME/.ssh/id_rsa"
|
||||
chmod 600 "$HOME/.ssh/id_rsa"
|
||||
git config --global user.name "$COMMIT_USERNAME"
|
||||
git config --global user.email "$COMMIT_EMAIL"
|
||||
|
||||
# Clone AUR Package
|
||||
cd /tmp
|
||||
echo "$REPO_URL"
|
||||
git clone "$REPO_URL"
|
||||
cd "$PACKAGE_NAME"
|
||||
|
||||
# Generate a dummy PKGBUILD so we can grab the latest releases SHA256SUMS
|
||||
cat PKGBUILD.template | envsubst '$NEW_RELEASE' > PKGBUILD
|
||||
|
||||
export SHA256_SUMS_x86_64="$(CARCH=x86_64 makepkg -g 2> /dev/null)"
|
||||
echo "SHA256_SUMS_x86_64: $SHA256_SUMS_x86_64"
|
||||
|
||||
export SHA256_SUMS_aarch64="$(CARCH=aarch64 makepkg -g 2> /dev/null)"
|
||||
echo "SHA256_SUMS_aarch64: $SHA256_SUMS_aarch64"
|
||||
|
||||
export SHA256_SUMS_arm="$(CARCH=arm makepkg -g 2> /dev/null)"
|
||||
echo "SHA256_SUMS_arm: $SHA256_SUMS_arm"
|
||||
|
||||
cat PKGBUILD.template | envsubst '$NEW_RELEASE$SHA256_SUMS_x86_64$SHA256_SUMS_aarch64$SHA256_SUMS_arm' > PKGBUILD
|
||||
makepkg --printsrcinfo > .SRCINFO
|
||||
|
||||
echo "------------- BUILD DONE ----------------"
|
||||
git add PKGBUILD .SRCINFO
|
||||
git commit -m "$COMMIT_MESSAGE"
|
||||
git push
|
||||
echo "------------- PUBLISH DONE ----------------"
|
||||
EOSU
|
@ -1,27 +0,0 @@
|
||||
image: rancher/k3d:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}-dind
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
- image: rancher/k3d:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}dind-linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
- image: rancher/k3d:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}dind-linux-arm64
|
||||
platform:
|
||||
variant: v8
|
||||
architecture: arm64
|
||||
os: linux
|
||||
- image: rancher/k3d:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}dind-linux-arm
|
||||
platform:
|
||||
variant: v7
|
||||
architecture: arm
|
||||
os: linux
|
||||
- image: rancher/k3d:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}dind-linux-arm
|
||||
platform:
|
||||
variant: v6
|
||||
architecture: arm
|
||||
os: linux
|
@ -1,15 +0,0 @@
|
||||
# docgen
|
||||
|
||||
Only used to generate the command tree for <https://k3d.io/usage/commands>.
|
||||
|
||||
The code will output files in [`../docs/usage/commands/`](../docs/usage/commands/)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
# ensure that you're in the docgen dir, as the relative path to the docs/ dir is hardcoded
|
||||
cd docgen
|
||||
|
||||
# run
|
||||
./run.sh
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user